; 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()
; 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
; 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
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: GLOBAL_GET
; CHECK-NEXT: Index: 1
-; CHECK-NEXT: Content: '0000000001000000'
+; CHECK-NEXT: Content: '020000000000000001000000'
--- /dev/null
+; 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
void createCtorFunction();
void calculateInitFunctions();
+ void processRelocations(InputChunk *Chunk);
void assignIndexes();
void calculateImports();
void calculateExports();
registerType(E->Signature);
}
+void Writer::processRelocations(InputChunk *Chunk) {
+ if (!Chunk->Live)
+ return;
+ ObjFile *File = Chunk->File;
+ ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
+ for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
+ 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(TableBase + IndirectFunctions.size());
+ IndirectFunctions.emplace_back(Sym);
+ 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<DefinedData>(DataSym) &&
+ !DataSym->isWeak())
+ error(File->getName() +
+ ": relocation of type R_WASM_MEMORY_ADDR_* "
+ "against undefined data symbol: " +
+ DataSym->getName());
+ break;
+ }
+ }
+ }
+}
+
void Writer::assignIndexes() {
assert(InputFunctions.empty());
uint32_t FunctionIndex = NumImportedFunctions;
AddDefinedFunction(Func);
}
- uint32_t TableIndex = TableBase;
- auto HandleRelocs = [&](InputChunk *Chunk) {
- if (!Chunk->Live)
- return;
- ObjFile *File = Chunk->File;
- ArrayRef<WasmSignature> 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) {
- 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) {
- // Mark target type as live
- File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]);
- File->TypeIsUsed[Reloc.Index] = true;
- }
- }
- };
-
for (ObjFile *File : Symtab->ObjectFiles) {
LLVM_DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n");
for (InputChunk *Chunk : File->Functions)
- HandleRelocs(Chunk);
+ processRelocations(Chunk);
for (InputChunk *Chunk : File->Segments)
- HandleRelocs(Chunk);
+ processRelocations(Chunk);
for (auto &P : File->CustomSections)
- HandleRelocs(P);
+ processRelocations(P);
}
assert(InputGlobals.empty());