Skip to content

Commit 8fcf012

Browse files
committed
[WebAssembly] Refactor synthetic sections and relocation processing. NFC.
Major refactor to better match the structure of the ELF linker. - Split out relocation processing into scanRelocations - Split out synthetic sections into their own classes. Differential Revision: https://reviews.llvm.org/D61811 llvm-svn: 361233
1 parent f33f181 commit 8fcf012

13 files changed

+1186
-931
lines changed

lld/wasm/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ add_lld_library(lldWasm
1313
LTO.cpp
1414
MarkLive.cpp
1515
OutputSections.cpp
16+
Relocations.cpp
1617
SymbolTable.cpp
1718
Symbols.cpp
19+
SyntheticSections.cpp
1820
Writer.cpp
1921
WriterUtils.cpp
2022

@@ -35,4 +37,4 @@ add_lld_library(lldWasm
3537
DEPENDS
3638
WasmOptionsTableGen
3739
${tablegen_deps}
38-
)
40+
)

lld/wasm/InputChunks.h

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace wasm {
3131

3232
class ObjFile;
3333
class OutputSegment;
34+
class OutputSection;
3435

3536
class InputChunk {
3637
public:
@@ -207,6 +208,8 @@ class InputSection : public InputChunk {
207208
StringRef getDebugName() const override { return StringRef(); }
208209
uint32_t getComdat() const override { return UINT32_MAX; }
209210

211+
OutputSection *OutputSec = nullptr;
212+
210213
protected:
211214
ArrayRef<uint8_t> data() const override { return Section.Content; }
212215

lld/wasm/InputFiles.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
7575
assert(TypeIsUsed[Reloc.Index]);
7676
return TypeMap[Reloc.Index];
7777
}
78-
return Symbols[Reloc.Index]->getOutputSymbolIndex();
78+
const Symbol *Sym = Symbols[Reloc.Index];
79+
if (auto *SS = dyn_cast<SectionSymbol>(Sym))
80+
Sym = SS->getOutputSectionSymbol();
81+
return Sym->getOutputSymbolIndex();
7982
}
8083

8184
// Relocations can contain addend for combined sections. This function takes a
@@ -395,7 +398,7 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
395398
case WASM_SYMBOL_TYPE_SECTION: {
396399
InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
397400
assert(Sym.isBindingLocal());
398-
return make<SectionSymbol>(Name, Flags, Section, this);
401+
return make<SectionSymbol>(Flags, Section, this);
399402
}
400403
case WASM_SYMBOL_TYPE_EVENT: {
401404
InputEvent *Event =

lld/wasm/OutputSections.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ void CustomSection::finalizeContents() {
206206

207207
for (InputSection *Section : InputSections) {
208208
Section->OutputOffset = PayloadSize;
209+
Section->OutputSec = this;
209210
PayloadSize += Section->getSize();
210211
}
211212

@@ -241,9 +242,3 @@ void CustomSection::writeRelocations(raw_ostream &OS) const {
241242
for (const InputSection *S : InputSections)
242243
S->writeRelocations(OS);
243244
}
244-
245-
void RelocSection::writeBody() {
246-
writeUleb128(BodyOutputStream, SectionIndex, "reloc section");
247-
writeUleb128(BodyOutputStream, Sec->numRelocations(), "reloc count");
248-
Sec->writeRelocations(BodyOutputStream);
249-
}

lld/wasm/OutputSections.h

+6-47
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class OutputSection {
3838
Offset = NewOffset;
3939
}
4040
void createHeader(size_t BodySize);
41+
virtual bool isNeeded() const { return true; }
4142
virtual size_t getSize() const = 0;
4243
virtual void writeTo(uint8_t *Buf) = 0;
4344
virtual void finalizeContents() = 0;
@@ -46,54 +47,24 @@ class OutputSection {
4647

4748
std::string Header;
4849
uint32_t Type;
50+
uint32_t SectionIndex = UINT32_MAX;
4951
std::string Name;
52+
OutputSectionSymbol *SectionSym = nullptr;
5053

5154
protected:
5255
size_t Offset = 0;
5356
};
5457

55-
class SyntheticSection : public OutputSection {
56-
public:
57-
SyntheticSection(uint32_t Type, std::string Name = "")
58-
: OutputSection(Type, Name), BodyOutputStream(Body) {
59-
if (!Name.empty())
60-
writeStr(BodyOutputStream, Name, "section name");
61-
}
62-
63-
void writeTo(uint8_t *Buf) override {
64-
assert(Offset);
65-
log("writing " + toString(*this));
66-
memcpy(Buf + Offset, Header.data(), Header.size());
67-
memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
68-
}
69-
70-
size_t getSize() const override { return Header.size() + Body.size(); }
71-
72-
virtual void writeBody() {}
73-
74-
void finalizeContents() override {
75-
writeBody();
76-
BodyOutputStream.flush();
77-
createHeader(Body.size());
78-
}
79-
80-
raw_ostream &getStream() { return BodyOutputStream; }
81-
82-
std::string Body;
83-
84-
protected:
85-
llvm::raw_string_ostream BodyOutputStream;
86-
};
87-
8858
class CodeSection : public OutputSection {
8959
public:
9060
explicit CodeSection(ArrayRef<InputFunction *> Functions)
9161
: OutputSection(llvm::wasm::WASM_SEC_CODE), Functions(Functions) {}
9262

93-
size_t getSize() const override { assert(BodySize); return Header.size() + BodySize; }
63+
size_t getSize() const override { return Header.size() + BodySize; }
9464
void writeTo(uint8_t *Buf) override;
9565
uint32_t numRelocations() const override;
9666
void writeRelocations(raw_ostream &OS) const override;
67+
bool isNeeded() const override { return Functions.size() > 0; }
9768
void finalizeContents() override;
9869

9970
protected:
@@ -111,6 +82,7 @@ class DataSection : public OutputSection {
11182
void writeTo(uint8_t *Buf) override;
11283
uint32_t numRelocations() const override;
11384
void writeRelocations(raw_ostream &OS) const override;
85+
bool isNeeded() const override { return Segments.size() > 0; }
11486
void finalizeContents() override;
11587

11688
protected:
@@ -145,19 +117,6 @@ class CustomSection : public OutputSection {
145117
std::string NameData;
146118
};
147119

148-
class RelocSection : public SyntheticSection {
149-
public:
150-
RelocSection(StringRef Name, OutputSection *Sec, uint32_t SectionIndex)
151-
: SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, Name), Sec(Sec),
152-
SectionIndex(SectionIndex) {}
153-
void writeBody() override;
154-
155-
protected:
156-
OutputSection* Sec;
157-
uint32_t SectionIndex;
158-
};
159-
160-
161120
} // namespace wasm
162121
} // namespace lld
163122

lld/wasm/Relocations.cpp

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===- Relocations.cpp ----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Relocations.h"
10+
11+
#include "InputChunks.h"
12+
#include "SyntheticSections.h"
13+
14+
using namespace llvm;
15+
using namespace llvm::wasm;
16+
17+
using namespace lld;
18+
using namespace lld::wasm;
19+
20+
static bool requiresGOTAccess(const Symbol *Sym) {
21+
return Config->Pic && !Sym->isHidden() && !Sym->isLocal();
22+
}
23+
24+
void lld::wasm::scanRelocations(InputChunk *Chunk) {
25+
if (!Chunk->Live)
26+
return;
27+
ObjFile *File = Chunk->File;
28+
ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
29+
for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
30+
if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
31+
// Mark target type as live
32+
File->TypeMap[Reloc.Index] =
33+
Out.TypeSec->registerType(Types[Reloc.Index]);
34+
File->TypeIsUsed[Reloc.Index] = true;
35+
continue;
36+
}
37+
38+
// Other relocation types all have a corresponding symbol
39+
Symbol *Sym = File->getSymbols()[Reloc.Index];
40+
41+
switch (Reloc.Type) {
42+
case R_WASM_TABLE_INDEX_I32:
43+
case R_WASM_TABLE_INDEX_SLEB:
44+
case R_WASM_TABLE_INDEX_REL_SLEB:
45+
if (requiresGOTAccess(Sym))
46+
break;
47+
Out.ElemSec->addEntry(cast<FunctionSymbol>(Sym));
48+
break;
49+
case R_WASM_GLOBAL_INDEX_LEB:
50+
if (!isa<GlobalSymbol>(Sym))
51+
Out.ImportSec->addGOTEntry(Sym);
52+
break;
53+
case R_WASM_MEMORY_ADDR_SLEB:
54+
case R_WASM_MEMORY_ADDR_LEB:
55+
case R_WASM_MEMORY_ADDR_REL_SLEB:
56+
if (!Config->Relocatable && Sym->isUndefined() && !Sym->isWeak()) {
57+
error(toString(File) + ": cannot resolve relocation of type " +
58+
relocTypeToString(Reloc.Type) +
59+
" against undefined (non-weak) data symbol: " + toString(*Sym));
60+
}
61+
break;
62+
}
63+
64+
if (Config->Pic) {
65+
switch (Reloc.Type) {
66+
case R_WASM_TABLE_INDEX_SLEB:
67+
case R_WASM_MEMORY_ADDR_SLEB:
68+
case R_WASM_MEMORY_ADDR_LEB:
69+
// Certain relocation types can't be used when building PIC output,
70+
// since they would require absolute symbol addresses at link time.
71+
error(toString(File) + ": relocation " + relocTypeToString(Reloc.Type) +
72+
" cannot be used againt symbol " + toString(*Sym) +
73+
"; recompile with -fPIC");
74+
break;
75+
case R_WASM_TABLE_INDEX_I32:
76+
case R_WASM_MEMORY_ADDR_I32:
77+
// These relocation types are only present in the data section and
78+
// will be converted into code by `generateRelocationCode`. This code
79+
// requires the symbols to have GOT entires.
80+
if (requiresGOTAccess(Sym))
81+
Out.ImportSec->addGOTEntry(Sym);
82+
break;
83+
}
84+
}
85+
}
86+
}

lld/wasm/Relocations.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===- Relocations.h -------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLD_WASM_RELOCATIONS_H
10+
#define LLD_WASM_RELOCATIONS_H
11+
12+
namespace lld {
13+
namespace wasm {
14+
15+
class InputChunk;
16+
17+
void scanRelocations(InputChunk *Chunk);
18+
19+
} // namespace wasm
20+
} // namespace lld
21+
22+
#endif

lld/wasm/Symbols.cpp

+10-12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "InputEvent.h"
1313
#include "InputFiles.h"
1414
#include "InputGlobal.h"
15+
#include "OutputSections.h"
1516
#include "OutputSegment.h"
1617
#include "lld/Common/ErrorHandler.h"
1718
#include "lld/Common/Strings.h"
@@ -41,7 +42,7 @@ WasmSymbolType Symbol::getWasmType() const {
4142
return WASM_SYMBOL_TYPE_GLOBAL;
4243
if (isa<EventSymbol>(this))
4344
return WASM_SYMBOL_TYPE_EVENT;
44-
if (isa<SectionSymbol>(this))
45+
if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
4546
return WASM_SYMBOL_TYPE_SECTION;
4647
llvm_unreachable("invalid symbol kind");
4748
}
@@ -262,17 +263,9 @@ DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
262263
Event ? &Event->Signature : nullptr),
263264
Event(Event) {}
264265

265-
uint32_t SectionSymbol::getOutputSectionIndex() const {
266-
LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
267-
assert(OutputSectionIndex != INVALID_INDEX);
268-
return OutputSectionIndex;
269-
}
270-
271-
void SectionSymbol::setOutputSectionIndex(uint32_t Index) {
272-
LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index
273-
<< "\n");
274-
assert(Index != INVALID_INDEX);
275-
OutputSectionIndex = Index;
266+
const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
267+
assert(Section->OutputSec && Section->OutputSec->SectionSym);
268+
return Section->OutputSec->SectionSym;
276269
}
277270

278271
void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
@@ -308,6 +301,8 @@ std::string lld::toString(wasm::Symbol::Kind Kind) {
308301
return "LazyKind";
309302
case wasm::Symbol::SectionKind:
310303
return "SectionKind";
304+
case wasm::Symbol::OutputSectionKind:
305+
return "OutputSectionKind";
311306
}
312307
llvm_unreachable("invalid symbol kind");
313308
}
@@ -324,3 +319,6 @@ void lld::wasm::printTraceSymbol(Symbol *Sym) {
324319

325320
message(toString(Sym->getFile()) + S + Sym->getName());
326321
}
322+
323+
const char *lld::wasm::DefaultModule = "env";
324+
const char *lld::wasm::FunctionTableName = "__indirect_function_table";

0 commit comments

Comments
 (0)