[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
This commit is contained in:
Sam Clegg 2019-05-21 10:07:30 +00:00
parent 4a8835c655
commit 7804dbddcc
5 changed files with 115 additions and 12 deletions

View File

@ -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

View File

@ -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)

View File

@ -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");

View File

@ -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();

View File

@ -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("-- assignIndexes");
assignIndexes();
log("-- calculateInitFunctions");
calculateInitFunctions();
log("-- calculateTypes");
calculateTypes();
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();
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");