Skip to content

Commit b685ddf

Browse files
committed
[WebAssembly] Always take into account added when applying runtime relocations
The code we generate for applying data relocations at runtime omitted the symbols with GOT entries. Also refactor the code to reduce duplication. Differential Revision: https://reviews.llvm.org/D61111 llvm-svn: 359207
1 parent a1309a3 commit b685ddf

File tree

3 files changed

+42
-29
lines changed

3 files changed

+42
-29
lines changed

lld/test/wasm/shared.ll

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ target triple = "wasm32-unknown-unknown"
99
@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4
1010
@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4
1111

12+
; Test data relocations
1213
@data_addr = local_unnamed_addr global i32* @data, align 4
14+
; .. against external symbols
1315
@data_addr_external = local_unnamed_addr global i32* @data_external, align 4
16+
; .. including addends
17+
%struct.s = type { i32, i32 }
18+
@extern_struct = external global %struct.s
19+
@extern_struct_internal_ptr = local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @extern_struct, i32 0, i32 1), align 4
1420

1521
define hidden i32 @foo() {
1622
entry:
@@ -46,7 +52,7 @@ declare void @func_external()
4652
; CHECK: Sections:
4753
; CHECK-NEXT: - Type: CUSTOM
4854
; CHECK-NEXT: Name: dylink
49-
; CHECK-NEXT: MemorySize: 20
55+
; CHECK-NEXT: MemorySize: 24
5056
; CHECK-NEXT: MemoryAlignment: 2
5157
; CHECK-NEXT: TableSize: 3
5258
; CHECK-NEXT: TableAlignment: 0
@@ -98,6 +104,11 @@ declare void @func_external()
98104
; CHECK-NEXT: Kind: GLOBAL
99105
; CHECK-NEXT: GlobalType: I32
100106
; CHECK-NEXT: GlobalMutable: true
107+
; CHECK-NEXT: - Module: GOT.mem
108+
; CHECK-NEXT: Field: extern_struct
109+
; CHECK-NEXT: Kind: GLOBAL
110+
; CHECK-NEXT: GlobalType: I32
111+
; CHECK-NEXT: GlobalMutable: true
101112
; CHECK-NEXT: - Type: FUNCTION
102113

103114
; CHECK: - Type: EXPORT
@@ -125,7 +136,7 @@ declare void @func_external()
125136
; CHECK-NEXT: Body: 10020B
126137
; CHECK-NEXT: - Index: 2
127138
; CHECK-NEXT: Locals: []
128-
; CHECK-NEXT: Body: 230141046A230241016A360200230141086A230241026A3602002301410C6A230141006A360200230141106A23033602000B
139+
; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2303360200230141146A230541046A3602000B
129140

130141
; check the data segment initialized with __memory_base global as offset
131142

@@ -136,4 +147,4 @@ declare void @func_external()
136147
; CHECK-NEXT: Offset:
137148
; CHECK-NEXT: Opcode: GLOBAL_GET
138149
; CHECK-NEXT: Index: 1
139-
; CHECK-NEXT: Content: '0200000001000000020000000000000000000000'
150+
; CHECK-NEXT: Content: '020000000100000002000000000000000000000000000000'

lld/wasm/InputChunks.cpp

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -301,49 +301,48 @@ void InputFunction::writeTo(uint8_t *Buf) const {
301301
// This is only called when generating shared libaries (PIC) where address are
302302
// not known at static link time.
303303
void InputSegment::generateRelocationCode(raw_ostream &OS) const {
304+
LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName()
305+
<< " count=" << Relocations.size() << "\n");
306+
307+
// TODO(sbc): Encode the relocations in the data section and write a loop
308+
// here to apply them.
304309
uint32_t SegmentVA = OutputSeg->StartVA + OutputSegmentOffset;
305310
for (const WasmRelocation &Rel : Relocations) {
306311
uint32_t Offset = Rel.Offset - getInputSectionOffset();
307-
uint32_t OutputVA = SegmentVA + Offset;
312+
uint32_t OutputOffset = SegmentVA + Offset;
313+
314+
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(Rel.Type)
315+
<< " addend=" << Rel.Addend << " index=" << Rel.Index
316+
<< " output offset=" << OutputOffset << "\n");
308317

309318
// Get __memory_base
310319
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
311320
writeUleb128(OS, WasmSym::MemoryBase->getGlobalIndex(), "memory_base");
312321

313322
// Add the offset of the relocation
314323
writeU8(OS, WASM_OPCODE_I32_CONST, "I32_CONST");
315-
writeSleb128(OS, OutputVA, "offset");
324+
writeSleb128(OS, OutputOffset, "offset");
316325
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
317326

327+
Symbol *Sym = File->getSymbol(Rel);
318328
// Now figure out what we want to store
319-
switch (Rel.Type) {
320-
case R_WASM_TABLE_INDEX_I32:
321-
// Add the table index to the __table_base
329+
if (Sym->hasGOTIndex()) {
322330
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
323-
writeUleb128(OS, WasmSym::TableBase->getGlobalIndex(), "table_base");
324-
writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
325-
writeSleb128(OS, File->calcNewValue(Rel), "new table index");
326-
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
327-
break;
328-
case R_WASM_MEMORY_ADDR_I32: {
329-
Symbol *Sym = File->getSymbol(Rel);
330-
if (Sym->isLocal() || Sym->isHidden()) {
331-
// Hidden/Local data symbols are accessed via known offset from
332-
// __memory_base
333-
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
334-
writeUleb128(OS, WasmSym::MemoryBase->getGlobalIndex(), "memory_base");
331+
writeUleb128(OS, Sym->getGOTIndex(), "global index");
332+
if (Rel.Addend) {
335333
writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
336-
writeSleb128(OS, File->calcNewValue(Rel), "new memory offset");
334+
writeSleb128(OS, Rel.Addend, "addend");
337335
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
338-
} else {
339-
// Default data symbols are accessed via imported GOT globals
340-
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
341-
writeUleb128(OS, Sym->getGOTIndex(), "global index");
342336
}
343-
break;
344-
}
345-
default:
346-
llvm_unreachable("unexpected relocation type in data segment");
337+
} else {
338+
const GlobalSymbol* BaseSymbol = WasmSym::MemoryBase;
339+
if (Rel.Type == R_WASM_TABLE_INDEX_I32)
340+
BaseSymbol = WasmSym::TableBase;
341+
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
342+
writeUleb128(OS, BaseSymbol->getGlobalIndex(), "base");
343+
writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
344+
writeSleb128(OS, File->calcNewValue(Rel), "offset");
345+
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
347346
}
348347

349348
// Store that value at the virtual address

lld/wasm/Symbols.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ void Symbol::setOutputSymbolIndex(uint32_t Index) {
9797
void Symbol::setGOTIndex(uint32_t Index) {
9898
LLVM_DEBUG(dbgs() << "setGOTIndex " << Name << " -> " << Index << "\n");
9999
assert(GOTIndex == INVALID_INDEX);
100+
// Any symbol that is assigned a GOT entry must be exported othewise the
101+
// dynamic linker won't be able create the entry that contains it.
102+
ForceExport = true;
100103
GOTIndex = Index;
101104
}
102105

0 commit comments

Comments
 (0)