summaryrefslogtreecommitdiffstats
path: root/lld/wasm/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/wasm/Writer.cpp')
-rw-r--r--lld/wasm/Writer.cpp49
1 files changed, 43 insertions, 6 deletions
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