Index: lld/test/wasm/debug-removed-fn.ll =================================================================== --- lld/test/wasm/debug-removed-fn.ll +++ lld/test/wasm/debug-removed-fn.ll @@ -4,11 +4,11 @@ ; CHECK: Address ; CHECK: 0x0000000000000005 -; CHECK: 0x0000000000000000 +; CHECK: 0x00000000ffffffff ; CHECK: .debug_ranges contents: ; CHECK: 00000000 {{[0-9]+}} {{[0-9]+}} -; CHECK: 00000000 {{[0-9]+}} {{[0-9]+}} +; CHECK: 00000000 fffffffe fffffffe ; CHECK: 00000000 ; ModuleID = 't.bc' Index: lld/test/wasm/debuginfo.test =================================================================== --- lld/test/wasm/debuginfo.test +++ lld/test/wasm/debuginfo.test @@ -71,7 +71,7 @@ CHECK-NEXT: DW_AT_external (true) CHECK-NEXT: DW_AT_decl_file ("{{.*}}hi_foo.c") CHECK-NEXT: DW_AT_decl_line (8) -CHECK-NEXT: DW_AT_location (DW_OP_addr 0x0) +CHECK-NEXT: DW_AT_location (DW_OP_addr 0xffffffff) CHECK: DW_TAG_subprogram CHECK-NEXT: DW_AT_low_pc Index: lld/wasm/InputChunks.h =================================================================== --- lld/wasm/InputChunks.h +++ lld/wasm/InputChunks.h @@ -72,6 +72,7 @@ : file(f), live(!config->gcSections), discarded(false), sectionKind(k) {} virtual ~InputChunk() = default; virtual ArrayRef data() const = 0; + virtual uint64_t getTombstone() const { return 0; } // Verifies the existing data at relocation targets matches our expectations. // This is performed only debug builds as an extra sanity check. @@ -206,7 +207,7 @@ class InputSection : public InputChunk { public: InputSection(const WasmSection &s, ObjFile *f) - : InputChunk(f, InputChunk::Section), section(s) { + : InputChunk(f, InputChunk::Section), section(s), tombstone_value(getTombstoneForSection(s.Name)) { assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM); } @@ -222,8 +223,11 @@ // Offset within the input section. This is only zero since this chunk // type represents an entire input section, not part of one. uint32_t getInputSectionOffset() const override { return 0; } + uint64_t getTombstone() const override { return tombstone_value; } + static uint64_t getTombstoneForSection(StringRef name); const WasmSection §ion; + const uint64_t tombstone_value; }; } // namespace wasm Index: lld/wasm/InputChunks.cpp =================================================================== --- lld/wasm/InputChunks.cpp +++ lld/wasm/InputChunks.cpp @@ -128,7 +128,7 @@ for (const WasmRelocation &rel : relocations) { uint8_t *loc = buf + rel.Offset + off; - auto value = file->calcNewValue(rel); + auto value = file->calcNewValue(rel, getTombstone()); LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(rel.Type)); if (rel.Type != R_WASM_TYPE_INDEX_LEB) LLVM_DEBUG(dbgs() << " sym=" << file->getSymbols()[rel.Index]->getName()); @@ -405,5 +405,17 @@ } } +uint64_t InputSection::getTombstoneForSection(StringRef name) { + if (name.startswith(".debug_")) { + if (name.equals(".debug_ranges") || name.equals(".debug_loc")) { + return -2; + } else { + return -1; + } + } else { + return 0; + } +} + } // namespace wasm } // namespace lld Index: lld/wasm/InputFiles.h =================================================================== --- lld/wasm/InputFiles.h +++ lld/wasm/InputFiles.h @@ -103,7 +103,7 @@ void dumpInfo() const; uint32_t calcNewIndex(const WasmRelocation &reloc) const; - uint64_t calcNewValue(const WasmRelocation &reloc) const; + uint64_t calcNewValue(const WasmRelocation &reloc, uint64_t tombstone = 0) const; uint64_t calcNewAddend(const WasmRelocation &reloc) const; uint64_t calcExpectedValue(const WasmRelocation &reloc) const; Symbol *getSymbol(const WasmRelocation &reloc) const { Index: lld/wasm/InputFiles.cpp =================================================================== --- lld/wasm/InputFiles.cpp +++ lld/wasm/InputFiles.cpp @@ -182,17 +182,19 @@ } // Translate from the relocation's index into the final linked output value. -uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc) const { +uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone) 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. We return reloc.Addend because always returning zero - // causes the generation of spurious range-list terminators in the - // .debug_ranges section. - if ((isa(sym) || isa(sym)) && !sym->isLive()) - return reloc.Addend; + // in debug sections. We return a tombstone value in debug symbol sections + // so this will not produce a valid range conflicting with ranges of actual + // code. In other sections we return reloc.Addend. + + if ((isa(sym) || isa(sym)) && !sym->isLive()) { + return tombstone ? tombstone : reloc.Addend; + } } switch (reloc.Type) {