diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -13,10 +13,12 @@ ; To ensure we use __stack_pointer %ptr = alloca i32 %0 = load i32, i32* @data, align 4 - %1 = load i32, i32* @data_external, align 4 - %2 = load i32 ()*, i32 ()** @indirect_func, align 4 - call i32 %2() - ret i32 %1 + ; TODO(sbc): Re-enable once the codegen supports generating the correct + ; relocation type when referencing external data in shared libraries. + ; %1 = load i32, i32* @data_external, align 4 + %1 = load i32 ()*, i32 ()** @indirect_func, align 4 + call i32 %1() + ret i32 %0 } declare void @func_external() @@ -29,7 +31,7 @@ ; CHECK: Sections: ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: dylink -; CHECK-NEXT: MemorySize: 8 +; CHECK-NEXT: MemorySize: 12 ; CHECK-NEXT: MemoryAlignment: 2 ; CHECK-NEXT: TableSize: 2 ; CHECK-NEXT: TableAlignment: 0 @@ -60,11 +62,11 @@ ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 ; CHECK-NEXT: GlobalMutable: false -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: data_external -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 -; CHECK-NEXT: GlobalMutable: true +; XCHECK-NEXT: - Module: env +; XCHECK-NEXT: Field: data_external +; XCHECK-NEXT: Kind: GLOBAL +; XCHECK-NEXT: GlobalType: I32 +; XCHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: func_external ; CHECK-NEXT: Kind: FUNCTION @@ -88,4 +90,4 @@ ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Content: '0000000001000000' +; CHECK-NEXT: Content: '020000000000000001000000' diff --git a/lld/test/wasm/undefined-data.ll b/lld/test/wasm/undefined-data.ll new file mode 100644 --- /dev/null +++ b/lld/test/wasm/undefined-data.ll @@ -0,0 +1,16 @@ +; RUN: llc -filetype=obj %s -o %t.o +; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF +; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=BADRELOC + +target triple = "wasm32-unknown-unknown" + +@data_external = external global i32 + +define i32 @_start() { +entry: + %0 = load i32, i32* @data_external, align 4 + ret i32 %0 +} + +; UNDEF: undefined symbol: data_external +; BADRELOC: undefined-data.ll.tmp.o: relocation of type R_WASM_MEMORY_ADDR_* against undefined data symbol: data_external diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1041,17 +1041,33 @@ ObjFile *File = Chunk->File; ArrayRef Types = File->getWasmObj()->types(); for (const WasmRelocation &Reloc : Chunk->getRelocations()) { - if (Reloc.Type == R_WASM_TABLE_INDEX_I32 || - Reloc.Type == R_WASM_TABLE_INDEX_SLEB) { + switch (Reloc.Type) { + case R_WASM_TABLE_INDEX_I32: + case R_WASM_TABLE_INDEX_SLEB: { FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); if (Sym->hasTableIndex() || !Sym->hasFunctionIndex()) continue; Sym->setTableIndex(TableIndex++); IndirectFunctions.emplace_back(Sym); - } else if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) { + break; + } + case R_WASM_TYPE_INDEX_LEB: // Mark target type as live File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); File->TypeIsUsed[Reloc.Index] = true; + break; + case R_WASM_MEMORY_ADDR_SLEB: + case R_WASM_MEMORY_ADDR_I32: + case R_WASM_MEMORY_ADDR_LEB: { + DataSymbol *DataSym = File->getDataSymbol(Reloc.Index); + if (!Config->Relocatable && !isa(DataSym) && + !DataSym->isWeak()) + error(File->getName() + + ": relocation of type R_WASM_MEMORY_ADDR_* " + "against undefined data symbol: " + + DataSym->getName()); + break; + } } } };