From a59b17c8adde34e26b0f101fc2942637b945e1e5 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Mon, 3 Mar 2025 16:08:56 -0800 Subject: [PATCH] [lld][WebAssembly] Do not emit relocs against dead symbols (#129346) When emitting relocs with linked output (i.e. --emit-relocs) skip relocs against dead symbols (which do not appear in the output) and do not emit them. --- lld/test/wasm/emit-relocs.s | 15 +++++++++++++++ lld/wasm/InputChunks.cpp | 14 ++++++++++++++ lld/wasm/InputChunks.h | 1 + lld/wasm/OutputSections.cpp | 2 +- lld/wasm/OutputSections.h | 1 + lld/wasm/Symbols.cpp | 2 +- 6 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lld/test/wasm/emit-relocs.s b/lld/test/wasm/emit-relocs.s index bd136ba810b5..385344cb2332 100644 --- a/lld/test/wasm/emit-relocs.s +++ b/lld/test/wasm/emit-relocs.s @@ -27,6 +27,12 @@ foo: .int32 0 .size foo, 4 +.section .debug_info,"",@ +.p2align 2 +.int32 unused_function +.int32 _start +.int32 0 + # CHECK: - Type: CODE # CHECK-NEXT: Relocations: # CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB @@ -42,6 +48,15 @@ foo: # CHECK-NEXT: Value: 1024 # CHECK-NEXT: Content: '00000000' +# There should be a single relocation in this section (just the live symbol) +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Relocations: +# CHECK-NEXT: - Type: R_WASM_FUNCTION_OFFSET_I32 +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Offset: 0x4 +# CHECK-NEXT: Name: .debug_info +# CHECK-NEXT: Payload: FFFFFFFF0200000000000000 + # CHECK: - Type: CUSTOM # CHECK-NEXT: Name: linking # CHECK-NEXT: Version: 2 diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index ccdc92f5c8d7..366869738223 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -14,6 +14,7 @@ #include "lld/Common/LLVM.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/xxhash.h" +#include #define DEBUG_TYPE "lld" @@ -167,6 +168,17 @@ void InputChunk::relocate(uint8_t *buf) const { } } +static bool relocIsLive(const WasmRelocation &rel, ObjFile *file) { + return rel.Type == R_WASM_TYPE_INDEX_LEB || + file->getSymbol(rel.Index)->isLive(); +} + +size_t InputChunk::getNumLiveRelocations() const { + return std::count_if( + relocations.begin(), relocations.end(), + [this](const WasmRelocation &rel) { return relocIsLive(rel, file); }); +} + // Copy relocation entries to a given output stream. // This function is used only when a user passes "-r". For a regular link, // we consume relocations instead of copying them to an output file. @@ -179,6 +191,8 @@ void InputChunk::writeRelocations(raw_ostream &os) const { << " offset=" << Twine(off) << "\n"); for (const WasmRelocation &rel : relocations) { + if (!relocIsLive(rel, file)) + continue; writeUleb128(os, rel.Type, "reloc type"); writeUleb128(os, rel.Offset + off, "reloc offset"); writeUleb128(os, file->calcNewIndex(rel), "reloc index"); diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h index f545449e1246..1fe78d76631f 100644 --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -77,6 +77,7 @@ public: uint32_t getInputSectionOffset() const { return inputSectionOffset; } size_t getNumRelocations() const { return relocations.size(); } + size_t getNumLiveRelocations() const; void writeRelocations(llvm::raw_ostream &os) const; bool generateRelocationCode(raw_ostream &os) const; diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp index d679d1e67647..5038cd8ea965 100644 --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -274,7 +274,7 @@ void CustomSection::writeTo(uint8_t *buf) { uint32_t CustomSection::getNumRelocations() const { uint32_t count = 0; for (const InputChunk *inputSect : inputSections) - count += inputSect->getNumRelocations(); + count += inputSect->getNumLiveRelocations(); return count; } diff --git a/lld/wasm/OutputSections.h b/lld/wasm/OutputSections.h index fcc8cf45dc73..4b0329dd16cf 100644 --- a/lld/wasm/OutputSections.h +++ b/lld/wasm/OutputSections.h @@ -41,6 +41,7 @@ public: virtual void writeTo(uint8_t *buf) = 0; virtual void finalizeContents() = 0; virtual uint32_t getNumRelocations() const { return 0; } + virtual uint32_t getNumLiveRelocations() const { return getNumRelocations(); } virtual void writeRelocations(raw_ostream &os) const {} std::string header; diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index a687fd6d6c4e..09f110d0885f 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -183,7 +183,7 @@ void Symbol::markLive() { } uint32_t Symbol::getOutputSymbolIndex() const { - assert(outputSymbolIndex != INVALID_INDEX); + assert(outputSymbolIndex != INVALID_INDEX || !isLive()); return outputSymbolIndex; }