Index: lib/DebugInfo/DWARFContext.h =================================================================== --- lib/DebugInfo/DWARFContext.h +++ lib/DebugInfo/DWARFContext.h @@ -200,7 +200,7 @@ static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3 || version == 4; } -private: + /// Return the compile unit that includes an offset (relative to .debug_info). DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); Index: lib/DebugInfo/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARFContext.cpp +++ lib/DebugInfo/DWARFContext.cpp @@ -390,28 +390,33 @@ } namespace { - struct OffsetComparator { - - bool operator()(const std::unique_ptr &LHS, - const std::unique_ptr &RHS) const { - return LHS->getOffset() < RHS->getOffset(); - } - bool operator()(const std::unique_ptr &LHS, - uint32_t RHS) const { - return LHS->getOffset() < RHS; - } - bool operator()(uint32_t LHS, - const std::unique_ptr &RHS) const { - return LHS < RHS->getOffset(); - } - }; +template +struct OffsetComparator { + // The beginning offset of a CU is the NextUnitOffset of the + // preceding one. When searching for this particular offset, the + // comparator has to return true so that lower_bound skips the + // CU. Thus the <= comparison. + bool operator()(const std::unique_ptr &LHS, + const std::unique_ptr &RHS) const { + return LHS->getNextUnitOffset() <= RHS->getNextUnitOffset(); + } + bool operator()(const std::unique_ptr &LHS, + uint32_t RHS) const { + return LHS->getNextUnitOffset() <= RHS; + } + bool operator()(uint32_t LHS, + const std::unique_ptr &RHS) const { + return LHS <= RHS->getNextUnitOffset(); + } +}; } DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { parseCompileUnits(); std::unique_ptr *CU = - std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator()); + std::lower_bound(CUs.begin(), CUs.end(), Offset, + OffsetComparator()); if (CU != CUs.end()) { return CU->get(); } Index: lib/DebugInfo/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -99,6 +99,20 @@ formValue.dump(OS, u); } + // We dumped the attribute value potentially as raw data. Add some + // special handling for cases where we want to annotate the raw data + // with something more descriptive. + if (attr == DW_AT_specification || + attr == DW_AT_abstract_origin) { + uint32_t Ref = formValue.getAsReference(u).getValue(); + DWARFDebugInfoEntryMinimal DIE; + if (DIE.extractFast(u, &Ref)) { + const char *Name = DIE.getSubroutineName(u, FunctionNameKind::LinkageName); + if (Name) + OS << '\"' << Name << '\"'; + } + } + OS << ")\n"; } @@ -299,6 +313,13 @@ FunctionNameKind Kind) const { if (!isSubroutineDIE() || Kind == FunctionNameKind::None) return nullptr; + + if (Offset < U->getOffset() || + Offset >= U->getNextUnitOffset()) { + U = U->getContext().getCompileUnitForOffset(Offset); + assert(U && "Invalid DIE referenced."); + } + // Try to get mangled name only if it was asked for. if (Kind == FunctionNameKind::LinkageName) { if (const char *name = Index: test/Linker/type-unique-odr-a.ll =================================================================== --- test/Linker/type-unique-odr-a.ll +++ test/Linker/type-unique-odr-a.ll @@ -41,7 +41,7 @@ ; CHECK: DW_AT_MIPS_linkage_name {{.*}} "_ZL3barv" ; getFoo and A may only appear once. -; CHECK-NOT: {{(getFoo)|("A")}} +; CHECK-NOT: AT_name{{.*(getFoo)|("A")}} ; ModuleID = 'type-unique-odr-a.cpp'