Index: test/wasm/undefined-data.ll =================================================================== --- test/wasm/undefined-data.ll +++ test/wasm/undefined-data.ll @@ -1,6 +1,7 @@ ; 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 --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=BADRELOC +; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=ALLOW +; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED target triple = "wasm32-unknown-unknown" @@ -13,4 +14,5 @@ } ; UNDEF: undefined symbol: data_external -; BADRELOC: undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used againt symbol data_external; recompile with -fPIC +; ALLOW: undefined-data.ll.tmp.o: cannot resolve relocation of type R_WASM_MEMORY_ADDR_LEB against undefined (non-weak) data symbol: data_external +; SHARED: undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used againt symbol data_external; recompile with -fPIC Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -141,6 +141,30 @@ // Translate from the relocation's index into the final linked output value. uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { + const Symbol* Sym = nullptr; + if (Reloc.Type != R_WASM_TYPE_INDEX_LEB) { + Sym = Symbols[Reloc.Index]; + + // We can end up with relocations against non-live symbols. For example + // in debug sections. + if ((isa(Sym) || isa(Sym)) && !Sym->isLive()) + return 0; + + // Special handling for undefined data symbols. Most relocations against + // such symbols cannot be resolved. + if (isa(Sym) && Sym->isUndefined()) { + if (Sym->isWeak() || Config->Relocatable) + return 0; + if (Config->Shared && Reloc.Type == R_WASM_MEMORY_ADDR_I32) + return 0; + if (Reloc.Type != R_WASM_GLOBAL_INDEX_LEB) { + llvm_unreachable( + ("invalid relocation against undefined data symbol: " + toString(*Sym)) + .c_str()); + } + } + } + switch (Reloc.Type) { case R_WASM_TABLE_INDEX_I32: case R_WASM_TABLE_INDEX_SLEB: @@ -150,28 +174,22 @@ case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_REL_SLEB: - if (auto *Sym = dyn_cast(getDataSymbol(Reloc.Index))) - if (Sym->isLive()) - return Sym->getVirtualAddress() + Reloc.Addend; - return 0; + return cast(Sym)->getVirtualAddress() + Reloc.Addend; case R_WASM_TYPE_INDEX_LEB: return TypeMap[Reloc.Index]; case R_WASM_FUNCTION_INDEX_LEB: return getFunctionSymbol(Reloc.Index)->getFunctionIndex(); - case R_WASM_GLOBAL_INDEX_LEB: { - const Symbol* Sym = Symbols[Reloc.Index]; + case R_WASM_GLOBAL_INDEX_LEB: if (auto GS = dyn_cast(Sym)) return GS->getGlobalIndex(); return Sym->getGOTIndex(); - } case R_WASM_EVENT_INDEX_LEB: + case R_WASM_EVENT_INDEX_LEB: return getEventSymbol(Reloc.Index)->getEventIndex(); - case R_WASM_FUNCTION_OFFSET_I32: - if (auto *Sym = dyn_cast(getFunctionSymbol(Reloc.Index))) { - if (Sym->isLive()) - return Sym->Function->OutputOffset + - Sym->Function->getFunctionCodeOffset() + Reloc.Addend; - } - return 0; + case R_WASM_FUNCTION_OFFSET_I32: { + auto *F = cast(Sym); + return F->Function->OutputOffset + F->Function->getFunctionCodeOffset() + + Reloc.Addend; + } case R_WASM_SECTION_OFFSET_I32: return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend; default: Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -1170,6 +1170,20 @@ Sym->setGOTIndex(NumImportedGlobals++); GOTSymbols.push_back(Sym); } + break; + } + case R_WASM_MEMORY_ADDR_SLEB: + case R_WASM_MEMORY_ADDR_LEB: + case R_WASM_MEMORY_ADDR_REL_SLEB: { + if (!Config->Relocatable) { + auto* Sym = File->getSymbols()[Reloc.Index]; + if (Sym->isUndefined() && !Sym->isWeak()) { + error(toString(File) + ": cannot resolve relocation of type " + + relocTypeToString(Reloc.Type) + + " against undefined (non-weak) data symbol: " + toString(*Sym)); + } + } + break; } }