Skip to content

Commit

Permalink
[WebAssembly] Add __start_/_stop_ symbols for data sections
Browse files Browse the repository at this point in the history
  • Loading branch information
sbc100 authored and MrSidims committed May 24, 2019
1 parent 25d9e5f commit cd32d7f
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
57 changes: 57 additions & 0 deletions 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
4 changes: 0 additions & 4 deletions lld/wasm/Driver.cpp
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions lld/wasm/SymbolTable.cpp
Expand Up @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions lld/wasm/SymbolTable.h
Expand Up @@ -81,6 +81,8 @@ class SymbolTable {
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();
Expand Down
49 changes: 43 additions & 6 deletions lld/wasm/Writer.cpp
Expand Up @@ -73,6 +73,8 @@ class Writer {
void addSection(OutputSection *Sec);

void addSections();
void addStartStopSymbols(const InputSegment *Seg);

void createCustomSections();
void createSyntheticSections();
void finalizeSections();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -543,8 +561,6 @@ void Writer::assignIndexes() {
Out.FunctionSec->addFunction(Func);
}

scanRelocations();

for (InputGlobal *Global : Symtab->SyntheticGlobals)
Out.GlobalSec->addGlobal(Global);

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

0 comments on commit cd32d7f

Please sign in to comment.