diff --git a/lld/test/wasm/runtime-relocations-himem.s b/lld/test/wasm/runtime-relocations-himem.s new file mode 100644 index 0000000000000..a12a93a6cb933 --- /dev/null +++ b/lld/test/wasm/runtime-relocations-himem.s @@ -0,0 +1,60 @@ +## Verifies runtime relocation code for addresses over 2gb works correctly. +## We have had issues with LEB encoding of address over 2gb in i32.const +## instruction leading to invalid binaries. + +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s +# RUN: wasm-ld --global-base=2147483648 --experimental-pic --unresolved-symbols=import-dynamic -no-gc-sections --shared-memory --no-entry -o %t.wasm %t.o +# XUN: obj2yaml %t.wasm | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s -- + +.globl tls_sym +.globl data_sym +.globl _start +.globaltype __tls_base, i32 + +_start: + .functype _start () -> () + global.get __tls_base + i32.const tls_sym@TLSREL + i32.add + drop + i32.const data_sym + drop + end_function + +.section tls_sec,"T",@ +.p2align 2 +tls_sym: + .int32 0 + .int32 extern_sym + .size tls_sym, 8 + +.section data_sec,"",@ +.p2align 2 +data_sym: + .int32 0 + .int32 extern_sym + .size data_sym, 8 + +.section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 7 + .ascii "atomics" + .int8 43 + .int8 11 + .ascii "bulk-memory" + +# CHECK: <__wasm_apply_data_relocs>: +# CHECK-EMPTY: +# CHECK-NEXT: i32.const -2147483636 +# CHECK-NEXT: global.get 0 +# CHECK-NEXT: i32.store 0 +# CHECK-NEXT: end + +# CHECK: <__wasm_apply_tls_relocs>: +# CHECK-EMPTY: +# CHECK-NEXT: i32.const -2147483644 +# CHECK-NEXT: global.get 0 +# CHECK-NEXT: i32.store 0 +# CHECK-NEXT: end diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 44927e7a432bc..14e02e6009318 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -423,8 +423,6 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { bool is64 = ctx.arg.is64.value_or(false); bool generated = false; - unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST - : WASM_OPCODE_I32_CONST; unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD; @@ -451,8 +449,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { << " output offset=" << offset << "\n"); // Calculate the address at which to apply the relocation - writeU8(os, opcode_ptr_const, "CONST"); - writeSleb128(os, offset, "offset"); + writePtrConst(os, offset, is64, "offset"); // In PIC mode we need to add the __memory_base if (ctx.isPic) { @@ -466,8 +463,6 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { // Now figure out what we want to store at this location bool is64 = relocIs64(rel.Type); - unsigned opcode_reloc_const = - is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST; unsigned opcode_reloc_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD; unsigned opcode_reloc_store = @@ -477,8 +472,7 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); writeUleb128(os, sym->getGOTIndex(), "global index"); if (rel.Addend) { - writeU8(os, opcode_reloc_const, "CONST"); - writeSleb128(os, rel.Addend, "addend"); + writePtrConst(os, rel.Addend, is64, "addend"); writeU8(os, opcode_reloc_add, "ADD"); } } else { @@ -491,8 +485,8 @@ bool InputChunk::generateRelocationCode(raw_ostream &os) const { baseSymbol = ctx.sym.tlsBase; writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); writeUleb128(os, baseSymbol->getGlobalIndex(), "base"); - writeU8(os, opcode_reloc_const, "CONST"); - writeSleb128(os, file->calcNewValue(rel, tombstone, this), "offset"); + writePtrConst(os, file->calcNewValue(rel, tombstone, this), is64, + "offset"); writeU8(os, opcode_reloc_add, "ADD"); } diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index e1192706ea913..399a5084e6595 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -434,8 +434,6 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) { void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const { assert(!ctx.arg.extendedConst); bool is64 = ctx.arg.is64.value_or(false); - unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST - : WASM_OPCODE_I32_CONST; unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD; @@ -452,8 +450,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const { writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base"); // Add the virtual address of the data symbol - writeU8(os, opcode_ptr_const, "CONST"); - writeSleb128(os, d->getVA(), "offset"); + writePtrConst(os, d->getVA(), is64, "offset"); } else if (auto *f = dyn_cast(sym)) { if (f->isStub) continue; @@ -462,8 +459,7 @@ void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const { writeUleb128(os, ctx.sym.tableBase->getGlobalIndex(), "__table_base"); // Add the table index to __table_base - writeU8(os, opcode_ptr_const, "CONST"); - writeSleb128(os, f->getTableIndex(), "offset"); + writePtrConst(os, f->getTableIndex(), is64, "offset"); } else { assert(isa(sym) || isa(sym)); continue;