summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-05-21 10:07:30 +0000
committerSam Clegg <sbc@chromium.org>2019-05-21 10:07:30 +0000
commit7804dbddccba412087a15cab8db4412939700952 (patch)
treec16e58ba25cc30753c87ba55b1ce2cd749cbb50e
parent4a8835c655e83326f121a1340bd5ea372177d60b (diff)
downloadbcm5719-llvm-7804dbddccba412087a15cab8db4412939700952.tar.gz
bcm5719-llvm-7804dbddccba412087a15cab8db4412939700952.zip
[WebAssembly] Add __start_/_stop_ symbols for data sections
Fixes https://bugs.llvm.org/show_bug.cgi?id=41565 Differential Revision: https://reviews.llvm.org/D61876 llvm-svn: 361236
-rw-r--r--lld/test/wasm/startstop.ll57
-rw-r--r--lld/wasm/Driver.cpp4
-rw-r--r--lld/wasm/SymbolTable.cpp11
-rw-r--r--lld/wasm/SymbolTable.h2
-rw-r--r--lld/wasm/Writer.cpp49
5 files changed, 113 insertions, 10 deletions
diff --git a/lld/test/wasm/startstop.ll b/lld/test/wasm/startstop.ll
new file mode 100644
index 00000000000..f83d1ac5378
--- /dev/null
+++ b/lld/test/wasm/startstop.ll
@@ -0,0 +1,57 @@
+; RUN: llc -filetype=obj -o %t.o %s
+; RUN: wasm-ld --no-gc-sections %t.o -o %t.wasm
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+@foo = global i32 3, section "mysection", align 4
+@bar = global i32 4, section "mysection", align 4
+
+@__start_mysection = external global i8*
+@__stop_mysection = external global i8*
+
+define i8** @get_start() {
+ ret i8** @__start_mysection
+}
+
+define i8** @get_end() {
+ ret i8** @__stop_mysection
+}
+
+define void @_start() {
+entry:
+ ret void
+}
+; CHECK: - Type: CODE
+; CHECK-NEXT: Functions:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Locals: []
+; CHECK-NEXT: Body: 0B
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Locals: []
+; CHECK-NEXT: Body: 4180888080000B
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Locals: []
+; CHECK-NEXT: Body: 4188888080000B
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Locals: []
+; CHECK-NEXT: Body: 0B
+; CHECK-NEXT: - Type: DATA
+; CHECK-NEXT: Segments:
+; CHECK-NEXT: - SectionOffset: 7
+; CHECK-NEXT: InitFlags: 0
+; CHECK-NEXT: Offset:
+; CHECK-NEXT: Opcode: I32_CONST
+; CHECK-NEXT: Value: 1024
+; CHECK-NEXT: Content: '0300000004000000'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: name
+; CHECK-NEXT: FunctionNames:
+; CHECK-NEXT: - Index: 0
+; CHECK-NEXT: Name: __wasm_call_ctors
+; CHECK-NEXT: - Index: 1
+; CHECK-NEXT: Name: get_start
+; CHECK-NEXT: - Index: 2
+; CHECK-NEXT: Name: get_end
+; CHECK-NEXT: - Index: 3
+; CHECK-NEXT: Name: _start
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index d6ee9076717..3bc20f6737b 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -608,10 +608,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Add synthetic dummies for weak undefined functions. Must happen
// after LTO otherwise functions may not yet have signatures.
Symtab->handleWeakUndefines();
-
- // Make sure we have resolved all symbols.
- if (!Config->AllowUndefined)
- Symtab->reportRemainingUndefines();
}
if (EntrySym)
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 1a16b6390ba..ce1aa5132ba 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -198,6 +198,17 @@ DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
Flags, nullptr, Function);
}
+DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value,
+ uint32_t Flags) {
+ Symbol *S = find(Name);
+ if (!S || S->isDefined())
+ return nullptr;
+ LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n");
+ auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags);
+ rtn->setVirtualAddress(Value);
+ return rtn;
+}
+
DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
uint32_t Flags) {
LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h
index ee4ee244ef5..a35140df136 100644
--- a/lld/wasm/SymbolTable.h
+++ b/lld/wasm/SymbolTable.h
@@ -81,6 +81,8 @@ public:
InputGlobal *Global);
DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags,
InputFunction *Function);
+ DefinedData *addOptionalDataSymbol(StringRef Name, uint32_t Value,
+ uint32_t Flags);
void handleSymbolVariants();
void handleWeakUndefines();
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index eb567ecf5c5..88c93fc2b5e 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -73,6 +73,8 @@ private:
void addSection(OutputSection *Sec);
void addSections();
+ void addStartStopSymbols(const InputSegment *Seg);
+
void createCustomSections();
void createSyntheticSections();
void finalizeSections();
@@ -293,6 +295,22 @@ void Writer::addSection(OutputSection *Sec) {
OutputSections.push_back(Sec);
}
+// If a section name is valid as a C identifier (which is rare because of
+// the leading '.'), linkers are expected to define __start_<secname> and
+// __stop_<secname> symbols. They are at beginning and end of the section,
+// respectively. This is not requested by the ELF standard, but GNU ld and
+// gold provide the feature, and used by many programs.
+void Writer::addStartStopSymbols(const InputSegment *Seg) {
+ StringRef S = Seg->getName();
+ LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << S << "\n");
+ if (!isValidCIdentifier(S))
+ return;
+ uint32_t Start = Seg->OutputSeg->StartVA + Seg->OutputSegmentOffset;
+ uint32_t Stop = Start + Seg->getSize();
+ Symtab->addOptionalDataSymbol(Saver.save("__start_" + S), Start, 0);
+ Symtab->addOptionalDataSymbol(Saver.save("__stop_" + S), Stop, 0);
+}
+
void Writer::addSections() {
addSection(Out.DylinkSec);
addSection(Out.TypeSec);
@@ -543,8 +561,6 @@ void Writer::assignIndexes() {
Out.FunctionSec->addFunction(Func);
}
- scanRelocations();
-
for (InputGlobal *Global : Symtab->SyntheticGlobals)
Out.GlobalSec->addGlobal(Global);
@@ -724,19 +740,40 @@ void Writer::run() {
populateTargetFeatures();
log("-- calculateImports");
calculateImports();
+ log("-- layoutMemory");
+ layoutMemory();
+
+ if (!Config->Relocatable) {
+ // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
+ // This has to be done after memory layout is performed.
+ for (const OutputSegment *Seg : Segments)
+ for (const InputSegment *S : Seg->InputSegments)
+ addStartStopSymbols(S);
+ }
+
log("-- assignIndexes");
assignIndexes();
+ log("-- scanRelocations");
+ scanRelocations();
log("-- calculateInitFunctions");
calculateInitFunctions();
- log("-- calculateTypes");
- calculateTypes();
- log("-- layoutMemory");
- layoutMemory();
+
if (!Config->Relocatable) {
+ // Create linker synthesized functions
if (Config->Pic)
createApplyRelocationsFunction();
createCallCtorsFunction();
+
+ // Make sure we have resolved all symbols.
+ if (!Config->AllowUndefined)
+ Symtab->reportRemainingUndefines();
+
+ if (errorCount())
+ return;
}
+
+ log("-- calculateTypes");
+ calculateTypes();
log("-- calculateExports");
calculateExports();
log("-- calculateCustomSections");
OpenPOWER on IntegriCloud