summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/shared.ll17
-rw-r--r--lld/wasm/InputChunks.cpp51
-rw-r--r--lld/wasm/Symbols.cpp3
3 files changed, 42 insertions, 29 deletions
diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll
index 678d62881d4..50a4c8b4a2e 100644
--- a/lld/test/wasm/shared.ll
+++ b/lld/test/wasm/shared.ll
@@ -9,8 +9,14 @@ target triple = "wasm32-unknown-unknown"
@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4
@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4
+; Test data relocations
@data_addr = local_unnamed_addr global i32* @data, align 4
+; .. against external symbols
@data_addr_external = local_unnamed_addr global i32* @data_external, align 4
+; .. including addends
+%struct.s = type { i32, i32 }
+@extern_struct = external global %struct.s
+@extern_struct_internal_ptr = local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @extern_struct, i32 0, i32 1), align 4
define hidden i32 @foo() {
entry:
@@ -46,7 +52,7 @@ declare void @func_external()
; CHECK: Sections:
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: dylink
-; CHECK-NEXT: MemorySize: 20
+; CHECK-NEXT: MemorySize: 24
; CHECK-NEXT: MemoryAlignment: 2
; CHECK-NEXT: TableSize: 3
; CHECK-NEXT: TableAlignment: 0
@@ -98,6 +104,11 @@ declare void @func_external()
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: GlobalType: I32
; CHECK-NEXT: GlobalMutable: true
+; CHECK-NEXT: - Module: GOT.mem
+; CHECK-NEXT: Field: extern_struct
+; CHECK-NEXT: Kind: GLOBAL
+; CHECK-NEXT: GlobalType: I32
+; CHECK-NEXT: GlobalMutable: true
; CHECK-NEXT: - Type: FUNCTION
; CHECK: - Type: EXPORT
@@ -125,7 +136,7 @@ declare void @func_external()
; CHECK-NEXT: Body: 10020B
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Locals: []
-; CHECK-NEXT: Body: 230141046A230241016A360200230141086A230241026A3602002301410C6A230141006A360200230141106A23033602000B
+; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2303360200230141146A230541046A3602000B
; check the data segment initialized with __memory_base global as offset
@@ -136,4 +147,4 @@ declare void @func_external()
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: GLOBAL_GET
; CHECK-NEXT: Index: 1
-; CHECK-NEXT: Content: '0200000001000000020000000000000000000000'
+; CHECK-NEXT: Content: '020000000100000002000000000000000000000000000000'
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index b60906972c6..735eb77ae1b 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -301,10 +301,19 @@ void InputFunction::writeTo(uint8_t *Buf) const {
// This is only called when generating shared libaries (PIC) where address are
// not known at static link time.
void InputSegment::generateRelocationCode(raw_ostream &OS) const {
+ LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName()
+ << " count=" << Relocations.size() << "\n");
+
+ // TODO(sbc): Encode the relocations in the data section and write a loop
+ // here to apply them.
uint32_t SegmentVA = OutputSeg->StartVA + OutputSegmentOffset;
for (const WasmRelocation &Rel : Relocations) {
uint32_t Offset = Rel.Offset - getInputSectionOffset();
- uint32_t OutputVA = SegmentVA + Offset;
+ uint32_t OutputOffset = SegmentVA + Offset;
+
+ LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(Rel.Type)
+ << " addend=" << Rel.Addend << " index=" << Rel.Index
+ << " output offset=" << OutputOffset << "\n");
// Get __memory_base
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
@@ -312,38 +321,28 @@ void InputSegment::generateRelocationCode(raw_ostream &OS) const {
// Add the offset of the relocation
writeU8(OS, WASM_OPCODE_I32_CONST, "I32_CONST");
- writeSleb128(OS, OutputVA, "offset");
+ writeSleb128(OS, OutputOffset, "offset");
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
+ Symbol *Sym = File->getSymbol(Rel);
// Now figure out what we want to store
- switch (Rel.Type) {
- case R_WASM_TABLE_INDEX_I32:
- // Add the table index to the __table_base
+ if (Sym->hasGOTIndex()) {
writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
- writeUleb128(OS, WasmSym::TableBase->getGlobalIndex(), "table_base");
- writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
- writeSleb128(OS, File->calcNewValue(Rel), "new table index");
- writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
- break;
- case R_WASM_MEMORY_ADDR_I32: {
- Symbol *Sym = File->getSymbol(Rel);
- if (Sym->isLocal() || Sym->isHidden()) {
- // Hidden/Local data symbols are accessed via known offset from
- // __memory_base
- writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
- writeUleb128(OS, WasmSym::MemoryBase->getGlobalIndex(), "memory_base");
+ writeUleb128(OS, Sym->getGOTIndex(), "global index");
+ if (Rel.Addend) {
writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
- writeSleb128(OS, File->calcNewValue(Rel), "new memory offset");
+ writeSleb128(OS, Rel.Addend, "addend");
writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
- } else {
- // Default data symbols are accessed via imported GOT globals
- writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
- writeUleb128(OS, Sym->getGOTIndex(), "global index");
}
- break;
- }
- default:
- llvm_unreachable("unexpected relocation type in data segment");
+ } else {
+ const GlobalSymbol* BaseSymbol = WasmSym::MemoryBase;
+ if (Rel.Type == R_WASM_TABLE_INDEX_I32)
+ BaseSymbol = WasmSym::TableBase;
+ writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
+ writeUleb128(OS, BaseSymbol->getGlobalIndex(), "base");
+ writeU8(OS, WASM_OPCODE_I32_CONST, "CONST");
+ writeSleb128(OS, File->calcNewValue(Rel), "offset");
+ writeU8(OS, WASM_OPCODE_I32_ADD, "ADD");
}
// Store that value at the virtual address
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index c2bd0030c22..74fa72365a6 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -97,6 +97,9 @@ void Symbol::setOutputSymbolIndex(uint32_t Index) {
void Symbol::setGOTIndex(uint32_t Index) {
LLVM_DEBUG(dbgs() << "setGOTIndex " << Name << " -> " << Index << "\n");
assert(GOTIndex == INVALID_INDEX);
+ // Any symbol that is assigned a GOT entry must be exported othewise the
+ // dynamic linker won't be able create the entry that contains it.
+ ForceExport = true;
GOTIndex = Index;
}
OpenPOWER on IntegriCloud