diff options
| -rw-r--r-- | llvm/tools/dsymutil/DwarfLinker.cpp | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index a75643530ca..10abfd34237 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -10,6 +10,7 @@ #include "BinaryHolder.h" #include "DebugMap.h" #include "dsymutil.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" @@ -47,6 +48,11 @@ bool error(const Twine &Error, const Twine &Context) { return false; } +template <typename KeyT, typename ValT> +using HalfOpenIntervalMap = + IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize, + IntervalMapHalfOpenInfo<KeyT>>; + /// \brief Stores all information relating to a compile unit, be it in /// its original instance in the object file to its brand new cloned /// and linked DIE tree. @@ -61,15 +67,19 @@ public: bool InDebugMap; ///< Was this DIE's entity found in the map? }; - CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) { + CompileUnit(DWARFUnit &OrigUnit) + : OrigUnit(OrigUnit), RangeAlloc(), Ranges(RangeAlloc) { Info.resize(OrigUnit.getNumDIEs()); } - // Workaround MSVC not supporting implicit move ops CompileUnit(CompileUnit &&RHS) : OrigUnit(RHS.OrigUnit), Info(std::move(RHS.Info)), CUDie(std::move(RHS.CUDie)), StartOffset(RHS.StartOffset), - NextUnitOffset(RHS.NextUnitOffset) {} + NextUnitOffset(RHS.NextUnitOffset), RangeAlloc(), Ranges(RangeAlloc) { + // The CompileUnit container has been 'reserve()'d with the right + // size. We cannot move the IntervalMap anyway. + llvm_unreachable("CompileUnits should not be moved."); + } DWARFUnit &getOrigUnit() const { return OrigUnit; } @@ -98,6 +108,10 @@ public: /// \brief Apply all fixups recored by noteForwardReference(). void fixupForwardReferences(); + /// \brief Add a function range [\p LowPC, \p HighPC) that is + /// relocatad by applying offset \p PCOffset. + void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset); + private: DWARFUnit &OrigUnit; std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index. @@ -113,6 +127,12 @@ private: /// cloning because for forward refences the target DIE's offset isn't /// known you emit the reference attribute. std::vector<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences; + + HalfOpenIntervalMap<uint64_t, int64_t>::Allocator RangeAlloc; + /// \brief The ranges in that interval map are the PC ranges for + /// functions in this unit, associated with the PC offset to apply + /// to the addresses to get the linked address. + HalfOpenIntervalMap<uint64_t, int64_t> Ranges; }; uint64_t CompileUnit::computeNextUnitOffset() { @@ -136,6 +156,11 @@ void CompileUnit::fixupForwardReferences() { Ref.second->setValue(Ref.first->getOffset() + getStartOffset()); } +void CompileUnit::addFunctionRange(uint64_t LowPC, uint64_t HighPC, + int64_t PCOffset) { + Ranges.insert(LowPC, HighPC, PCOffset); +} + /// \brief A string table that doesn't need relocations. /// /// We are doing a final link, no need for a string table that @@ -942,7 +967,25 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE( if (Options.Verbose) DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */); - return Flags | TF_Keep; + Flags |= TF_Keep; + + DWARFFormValue HighPcValue; + if (!DIE.getAttributeValue(&OrigUnit, dwarf::DW_AT_high_pc, HighPcValue)) { + reportWarning("Function without high_pc. Range will be discarded.\n", + &OrigUnit, &DIE); + return Flags; + } + + uint64_t HighPc; + if (HighPcValue.isFormClass(DWARFFormValue::FC_Address)) { + HighPc = *HighPcValue.getAsAddress(&OrigUnit); + } else { + assert(HighPcValue.isFormClass(DWARFFormValue::FC_Constant)); + HighPc = LowPc + *HighPcValue.getAsUnsignedConstant(); + } + + Unit.addFunctionRange(LowPc, HighPc, MyInfo.AddrAdjust); + return Flags; } /// \brief Check if a DIE should be kept. |

