diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -49,17 +49,23 @@ /// section. virtual bool hasValidRelocs() = 0; - /// Checks that the specified variable \p DIE references live code section. - /// Allowed kind of input die: DW_TAG_variable, DW_TAG_constant. - /// \returns true and sets Info.InDebugMap if it is the case. - virtual bool isLiveVariable(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) = 0; - - /// Checks that the specified subprogram \p DIE references live code section. - /// Allowed kind of input die: DW_TAG_subprogram, DW_TAG_label. - /// \returns true and sets Info.InDebugMap if it is the case. - virtual bool isLiveSubprogram(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) = 0; + /// Checks that the specified variable \p DIE references the live code + /// section and returns the relocation adjustment value (to get the linked + /// address this value might be added to the source variable address). + /// Allowed kinds of input DIE: DW_TAG_variable, DW_TAG_constant. + /// \returns relocation adjustment value or std::nullopt if there is no + /// corresponding live address. + virtual std::optional + getVariableRelocAdjustment(const DWARFDie &DIE) = 0; + + /// Checks that the specified subprogram \p DIE references the live code + /// section and returns the relocation adjustment value (to get the linked + /// address this value might be added to the source subprogram address). + /// Allowed kinds of input DIE: DW_TAG_subprogram, DW_TAG_label. + /// \returns relocation adjustment value or std::nullopt if there is no + /// corresponding live address. + virtual std::optional + getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0; /// Apply the valid relocations to the buffer \p Data, taking into /// account that Data is at \p BaseOffset in the .debug_info section. diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -439,9 +439,16 @@ // if the variable has a valid relocation, so that the DIEInfo is filled. // However, we don't want a static variable in a function to force us to keep // the enclosing function, unless requested explicitly. - const bool HasLiveMemoryLocation = RelocMgr.isLiveVariable(DIE, MyInfo); - if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) && - !LLVM_UNLIKELY(Options.KeepFunctionForStatic))) + std::optional RelocAdjustment = + RelocMgr.getVariableRelocAdjustment(DIE); + + if (RelocAdjustment) { + MyInfo.AddrAdjust = *RelocAdjustment; + MyInfo.InDebugMap = true; + } + + if (!RelocAdjustment || ((Flags & TF_InFunctionScope) && + !LLVM_UNLIKELY(Options.KeepFunctionForStatic))) return Flags; if (Options.Verbose) { @@ -468,9 +475,14 @@ return Flags; assert(LowPc && "low_pc attribute is not an address."); - if (!RelocMgr.isLiveSubprogram(DIE, MyInfo)) + std::optional RelocAdjustment = + RelocMgr.getSubprogramRelocAdjustment(DIE); + if (!RelocAdjustment) return Flags; + MyInfo.AddrAdjust = *RelocAdjustment; + MyInfo.InDebugMap = true; + if (Options.Verbose) { outs() << "Keeping subprogram DIE:"; DIDumpOptions DumpOpts; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h @@ -104,8 +104,8 @@ /// \returns resolved value. uint64_t relocate(const ValidReloc &Reloc) const; - /// Fill \p Info with address information for the specified \p Reloc. - void fillDieInfo(const ValidReloc &Reloc, CompileUnit::DIEInfo &Info); + /// \returns value for the specified \p Reloc. + int64_t getRelocValue(const ValidReloc &Reloc); /// Print contents of debug map entry for the specified \p Reloc. void printReloc(const ValidReloc &Reloc); @@ -168,15 +168,15 @@ /// Checks that there is a relocation in the \p Relocs array against a /// debug map entry between \p StartOffset and \p NextOffset. /// - /// \returns true and sets Info.InDebugMap if it is the case. - bool hasValidRelocationAt(const std::vector &Relocs, - uint64_t StartOffset, uint64_t EndOffset, - CompileUnit::DIEInfo &Info); - - bool isLiveVariable(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) override; - bool isLiveSubprogram(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) override; + /// \returns relocation value if relocation exist, otherwise std::nullopt. + std::optional + hasValidRelocationAt(const std::vector &Relocs, + uint64_t StartOffset, uint64_t EndOffset); + + std::optional + getVariableRelocAdjustment(const DWARFDie &DIE) override; + std::optional + getSubprogramRelocAdjustment(const DWARFDie &DIE) override; bool applyValidRelocs(MutableArrayRef Data, uint64_t BaseOffset, bool IsLittleEndian) override; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -933,28 +933,28 @@ uint64_t(Mapping.BinaryAddress)); } -void DwarfLinkerForBinary::AddressManager::fillDieInfo( - const ValidReloc &Reloc, CompileUnit::DIEInfo &Info) { - Info.AddrAdjust = relocate(Reloc); +int64_t +DwarfLinkerForBinary::AddressManager::getRelocValue(const ValidReloc &Reloc) { + int64_t AddrAdjust = relocate(Reloc); if (Reloc.Mapping->getValue().ObjectAddress) - Info.AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress); - Info.InDebugMap = true; + AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress); + return AddrAdjust; } -bool DwarfLinkerForBinary::AddressManager::hasValidRelocationAt( +std::optional +DwarfLinkerForBinary::AddressManager::hasValidRelocationAt( const std::vector &AllRelocs, uint64_t StartOffset, - uint64_t EndOffset, CompileUnit::DIEInfo &Info) { + uint64_t EndOffset) { std::vector Relocs = getRelocations(AllRelocs, StartOffset, EndOffset); if (Relocs.size() == 0) - return false; + return std::nullopt; if (Linker.Options.Verbose) printReloc(Relocs[0]); - fillDieInfo(Relocs[0], Info); - return true; + return getRelocValue(Relocs[0]); } /// Get the starting and ending (exclusive) offset for the @@ -978,14 +978,15 @@ return std::make_pair(Offset, End); } -bool DwarfLinkerForBinary::AddressManager::isLiveVariable( - const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) { +std::optional +DwarfLinkerForBinary::AddressManager::getVariableRelocAdjustment( + const DWARFDie &DIE) { const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); std::optional LocationIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_location); if (!LocationIdx) - return false; + return std::nullopt; uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode()); uint64_t LocationOffset, LocationEndOffset; @@ -994,17 +995,18 @@ // FIXME: Support relocations debug_addr. return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset, - LocationEndOffset, MyInfo); + LocationEndOffset); } -bool DwarfLinkerForBinary::AddressManager::isLiveSubprogram( - const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) { +std::optional +DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment( + const DWARFDie &DIE) { const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); std::optional LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc); if (!LowPcIdx) - return false; + return std::nullopt; dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx); @@ -1015,7 +1017,7 @@ std::tie(LowPcOffset, LowPcEndOffset) = getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit()); return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset, - LowPcEndOffset, MyInfo); + LowPcEndOffset); } case dwarf::DW_FORM_addrx: case dwarf::DW_FORM_addrx1: @@ -1028,15 +1030,14 @@ uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue(); uint64_t EndOffset = StartOffset + DIE.getDwarfUnit()->getAddressByteSize(); - return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset, - MyInfo); + return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset); } Linker.reportWarning("no base offset for address table", SrcFileName); - return false; + return std::nullopt; } default: - return false; + return std::nullopt; } } diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -70,8 +70,8 @@ // should be renamed into has valid address ranges bool hasValidRelocs() override { return !DWARFAddressRanges.empty(); } - bool isLiveSubprogram(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) override { + std::optional + getSubprogramRelocAdjustment(const DWARFDie &DIE) override { assert((DIE.getTag() == dwarf::DW_TAG_subprogram || DIE.getTag() == dwarf::DW_TAG_label) && "Wrong type of input die"); @@ -80,18 +80,16 @@ dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), Opts.Tombstone, - DIE.getDwarfUnit()->getAddressByteSize())) { - Info.AddrAdjust = 0; - Info.InDebugMap = true; - return true; - } + DIE.getDwarfUnit()->getAddressByteSize())) + // Relocation value for the linked binary is 0. + return 0; } - return false; + return std::nullopt; } - bool isLiveVariable(const DWARFDie &DIE, - CompileUnit::DIEInfo &Info) override { + std::optional + getVariableRelocAdjustment(const DWARFDie &DIE) override { assert((DIE.getTag() == dwarf::DW_TAG_variable || DIE.getTag() == dwarf::DW_TAG_constant) && "Wrong type of input die"); @@ -114,11 +112,9 @@ DIE.getDwarfUnit()->getAddressByteSize())); }); - if (HasLiveAddresses) { - Info.AddrAdjust = 0; - Info.InDebugMap = true; - return true; - } + if (HasLiveAddresses) + // Relocation value for the linked binary is 0. + return 0; } } else { // FIXME: missing DW_AT_location is OK here, but other errors should be @@ -126,7 +122,7 @@ consumeError(Loc.takeError()); } - return false; + return std::nullopt; } bool applyValidRelocs(MutableArrayRef, uint64_t, bool) override {