Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
std::optional<uint64_t> getForeignTUTypeSignature() const override;
std::optional<dwarf::Tag> getTag() const override { return tag(); }

// Special function that will return the related CU offset needed type
// Special function that will return the related CU offset needed type
// units. This gets used to find the .dwo file that originated the entries
// for a given type unit.
std::optional<uint64_t> getRelatedCUOffset() const;
Expand All @@ -468,12 +468,13 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
/// index for an entry that is a type unit.
std::optional<uint64_t> getRelatedCUIndex() const;

/// Returns the Index into the Local Type Unit list of the owning Name
/// Returns the index of the Type Unit of the owning
/// Name
/// Index or std::nullopt if this Accelerator Entry does not have an
/// associated Type Unit. It is up to the user to verify that the
/// returned Index is valid in the owning NameIndex (or use
/// returned Index is a valid index in the owning NameIndex (or use
/// getLocalTUOffset(), which will handle that check itself).
std::optional<uint64_t> getLocalTUIndex() const;
std::optional<uint64_t> getTUIndex() const;

/// .debug_names-specific getter, which always succeeds (DWARF v5 index
/// entries always have a tag).
Expand Down Expand Up @@ -803,7 +804,7 @@ class DWARFDebugNames : public DWARFAcceleratorTable {

private:
SmallVector<NameIndex, 0> NameIndices;
DenseMap<uint64_t, const NameIndex *> CUToNameIndex;
DenseMap<uint64_t, const NameIndex *> UnitOffsetToNameIndex;

public:
DWARFDebugNames(const DWARFDataExtractor &AccelSection,
Expand All @@ -820,9 +821,9 @@ class DWARFDebugNames : public DWARFAcceleratorTable {
const_iterator begin() const { return NameIndices.begin(); }
const_iterator end() const { return NameIndices.end(); }

/// Return the Name Index covering the compile unit at CUOffset, or nullptr if
/// there is no Name Index covering that unit.
const NameIndex *getCUNameIndex(uint64_t CUOffset);
/// Return the Name Index covering the compile unit or local type unit at
/// UnitOffset, or nullptr if there is no Name Index covering that unit.
const NameIndex *getCUOrTUNameIndex(uint64_t UnitOffset);
};

/// Calculates the starting offsets for various sections within the
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ class DWARFContext : public DIContext {
return State->getDWOUnits();
}

/// Return true of this DWARF context is a DWP file.
bool isDWP() const;

/// Get units from .debug_types.dwo in the DWO context.
unit_iterator_range dwo_types_section_units() {
DWARFUnitVector &DWOUnits = State->getDWOUnits();
Expand Down Expand Up @@ -262,7 +265,7 @@ class DWARFContext : public DIContext {
}

DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO);
DWARFTypeUnit *getTypeUnitForHash(uint64_t Hash, bool IsDWO);

/// Return the DWARF unit that includes an offset (relative to .debug_info).
DWARFUnit *getUnitForOffset(uint64_t Offset);
Expand Down
18 changes: 10 additions & 8 deletions llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUIndex() const {
if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_compile_unit))
return Off->getAsUnsignedConstant();
// In a per-CU index, the entries without a DW_IDX_compile_unit attribute
// implicitly refer to the single CU.
// implicitly refer to the single CU.
if (NameIdx->getCUCount() == 1)
return 0;
return std::nullopt;
Expand Down Expand Up @@ -665,15 +665,15 @@ std::optional<uint64_t> DWARFDebugNames::Entry::getRelatedCUOffset() const {
}

std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUOffset() const {
std::optional<uint64_t> Index = getLocalTUIndex();
std::optional<uint64_t> Index = getTUIndex();
if (!Index || *Index >= NameIdx->getLocalTUCount())
return std::nullopt;
return NameIdx->getLocalTUOffset(*Index);
}

std::optional<uint64_t>
DWARFDebugNames::Entry::getForeignTUTypeSignature() const {
std::optional<uint64_t> Index = getLocalTUIndex();
std::optional<uint64_t> Index = getTUIndex();
const uint32_t NumLocalTUs = NameIdx->getLocalTUCount();
if (!Index || *Index < NumLocalTUs)
return std::nullopt; // Invalid TU index or TU index is for a local TU
Expand All @@ -684,7 +684,7 @@ DWARFDebugNames::Entry::getForeignTUTypeSignature() const {
return NameIdx->getForeignTUSignature(ForeignTUIndex);
}

std::optional<uint64_t> DWARFDebugNames::Entry::getLocalTUIndex() const {
std::optional<uint64_t> DWARFDebugNames::Entry::getTUIndex() const {
if (std::optional<DWARFFormValue> Off = lookup(dwarf::DW_IDX_type_unit))
return Off->getAsUnsignedConstant();
return std::nullopt;
Expand Down Expand Up @@ -1061,14 +1061,16 @@ DWARFDebugNames::equal_range(StringRef Key) const {
}

const DWARFDebugNames::NameIndex *
DWARFDebugNames::getCUNameIndex(uint64_t CUOffset) {
if (CUToNameIndex.size() == 0 && NameIndices.size() > 0) {
DWARFDebugNames::getCUOrTUNameIndex(uint64_t UnitOffset) {
if (UnitOffsetToNameIndex.size() == 0 && NameIndices.size() > 0) {
for (const auto &NI : *this) {
for (uint32_t CU = 0; CU < NI.getCUCount(); ++CU)
CUToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
UnitOffsetToNameIndex.try_emplace(NI.getCUOffset(CU), &NI);
for (uint32_t TU = 0; TU < NI.getLocalTUCount(); ++TU)
UnitOffsetToNameIndex.try_emplace(NI.getLocalTUOffset(TU), &NI);
}
}
return CUToNameIndex.lookup(CUOffset);
return UnitOffsetToNameIndex.lookup(UnitOffset);
}

static bool isObjCSelector(StringRef Name) {
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,8 +1345,7 @@ void DWARFContext::dump(
getDebugNames().dump(OS);
}

DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,
bool IsDWO) {
DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint64_t Hash, bool IsDWO) {
DWARFUnitVector &DWOUnits = State->getDWOUnits();
if (const auto &TUI = getTUIndex()) {
if (const auto *R = TUI.getFromHash(Hash))
Expand Down Expand Up @@ -2478,3 +2477,5 @@ uint8_t DWARFContext::getCUAddrSize() {
auto CUs = compile_units();
return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
}

bool DWARFContext::isDWP() const { return !DObj->getCUIndexSection().empty(); }
8 changes: 4 additions & 4 deletions llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
if (DWARFUnit *SpecUnit = U->getUnitVector().getUnitForOffset(*Offset))
Result = SpecUnit->getDIEForOffset(*Offset);
} else if (std::optional<uint64_t> Sig = V.getAsSignatureReference()) {
if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
U->getVersion(), *Sig, U->isDWOUnit()))
if (DWARFTypeUnit *TU =
U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))
Result = TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
}
return Result;
Expand All @@ -329,8 +329,8 @@ DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
DWARFDie DWARFDie::resolveTypeUnitReference() const {
if (auto Attr = find(DW_AT_signature)) {
if (std::optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
if (DWARFTypeUnit *TU = U->getContext().getTypeUnitForHash(
U->getVersion(), *Sig, U->isDWOUnit()))
if (DWARFTypeUnit *TU =
U->getContext().getTypeUnitForHash(*Sig, U->isDWOUnit()))
return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
}
}
Expand Down
117 changes: 84 additions & 33 deletions llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/DJB.h"
Expand Down Expand Up @@ -1479,13 +1480,6 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(

unsigned
DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
if (NI.getForeignTUCount() > 0) {
warn() << formatv("Name Index @ {0:x}: Verifying indexes of foreign type "
"units is not currently supported.\n",
NI.getUnitOffset());
return 0;
}

unsigned NumErrors = 0;
for (const auto &Abbrev : NI.getAbbrevs()) {
StringRef TagName = dwarf::TagString(Abbrev.Tag);
Expand Down Expand Up @@ -1573,10 +1567,6 @@ static SmallVector<std::string, 3> getNames(const DWARFDie &DIE,
unsigned DWARFVerifier::verifyNameIndexEntries(
const DWARFDebugNames::NameIndex &NI,
const DWARFDebugNames::NameTableEntry &NTE) {
// Verifying foreign type unit indexes not supported.
if (NI.getForeignTUCount() > 0)
return 0;

const char *CStr = NTE.getString();
if (!CStr) {
ErrorCategory.Report("Unable to get string associated with name", [&]() {
Expand All @@ -1596,8 +1586,8 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
EntryOr = NI.getEntry(&NextEntryID)) {

std::optional<uint64_t> CUIndex = EntryOr->getCUIndex();
std::optional<uint64_t> TUIndex = EntryOr->getLocalTUIndex();
std::optional<uint64_t> CUIndex = EntryOr->getRelatedCUIndex();
std::optional<uint64_t> TUIndex = EntryOr->getTUIndex();
if (CUIndex && *CUIndex >= NI.getCUCount()) {
ErrorCategory.Report("Name Index entry contains invalid CU index", [&]() {
error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
Expand All @@ -1607,7 +1597,9 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
++NumErrors;
continue;
}
if (TUIndex && *TUIndex >= NI.getLocalTUCount()) {
const uint32_t NumLocalTUs = NI.getLocalTUCount();
const uint32_t NumForeignTUs = NI.getForeignTUCount();
if (TUIndex && *TUIndex >= (NumLocalTUs + NumForeignTUs)) {
ErrorCategory.Report("Name Index entry contains invalid TU index", [&]() {
error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
"invalid TU index ({2}).\n",
Expand All @@ -1617,10 +1609,28 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
continue;
}
std::optional<uint64_t> UnitOffset;
if (TUIndex)
UnitOffset = NI.getLocalTUOffset(*TUIndex);
else if (CUIndex)
if (CUIndex)
UnitOffset = NI.getCUOffset(*CUIndex);
else if (TUIndex) {
if (*TUIndex >= NumLocalTUs) {
// Foreign type units must have a valid CU index, either from a
// DW_IDX_comp_unit attribute value or from the .debug_names table only
// having a single compile unit. We need the originating compile unit
// because foreign type units can come from any .dwo file, yet only one
// copy of the type unit will end up in the .dwp file.
ErrorCategory.Report(
"Name Index entry contains foreign TU index with invalid CU index",
[&]() {
error() << formatv(
"Name Index @ {0:x}: Entry @ {1:x} contains an "
"foreign TU index ({2}) with no CU index.\n",
NI.getUnitOffset(), EntryID, *TUIndex);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment does not seem to align with the code?
From the comment, I was expecting, we try to get DW_IDX_compile_unit attribute value from the Entry, then check it against NumCUCount. That is not what the logic here.

++NumErrors;
continue;
}
UnitOffset = NI.getLocalTUOffset(*TUIndex);
}
if (!UnitOffset)
continue;
// For split DWARF entries we need to make sure we find the non skeleton
Expand Down Expand Up @@ -1650,20 +1660,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
// call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
// will return the unit DIE of DU if we aren't able to get the .dwo file,
// but that is what the function currently does.
DWARFDie UnitDie = DU->getUnitDIE();
DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE();
if (DU->getDWOId() && DU->getUnitDIE() == NonSkeletonUnitDie) {
if (DU->getDWOId() && UnitDie == NonSkeletonUnitDie) {
ErrorCategory.Report("Unable to get load .dwo file", [&]() {
error() << formatv("Name Index @ {0:x}: Entry @ {1:x} unable to load "
".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
NI.getUnitOffset(), EntryID,
dwarf::toString(DU->getUnitDIE().find(
{DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
*UnitOffset);
error() << formatv(
"Name Index @ {0:x}: Entry @ {1:x} unable to load "
".dwo file \"{2}\" for DWARF unit @ {3:x}.\n",
NI.getUnitOffset(), EntryID,
dwarf::toString(UnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
*UnitOffset);
});
++NumErrors;
continue;
}
DWARFUnit *NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit();
DWARFUnit *NonSkeletonUnit = nullptr;
if (TUIndex && *TUIndex >= NumLocalTUs) {
// We have a foreign TU index, which either means we have a .dwo file
// that has one or more type units, or we have a .dwp file with one or
// more type units. We need to get the type unit from the DWARFContext
// of the .dwo. We got the NonSkeletonUnitDie above that has the .dwo
// or .dwp DWARF context, so we have to get the type unit from that file.
// We have also verified that NonSkeletonUnitDie points to a DWO file
// above, so we know we have the right file.
const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
const uint64_t TypeSig = NI.getForeignTUSignature(ForeignTUIdx);
llvm::DWARFContext &SkeletonDCtx =
NonSkeletonUnitDie.getDwarfUnit()->getContext();
// Now find the type unit from the type signature and then update the
// NonSkeletonUnitDie to point to the actual type unit in the .dwo/.dwp.
NonSkeletonUnit =
SkeletonDCtx.getTypeUnitForHash(TypeSig, /*IsDWO=*/true);
NonSkeletonUnitDie = NonSkeletonUnit->getUnitDIE(true);
// If we have foreign type unit in a DWP file, then we need to ignore
// any entries from type units that don't match the one that made it into
// the .dwp file.
if (SkeletonDCtx.isDWP()) {
StringRef DUDwoName = dwarf::toStringRef(
UnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
StringRef TUDwoName = dwarf::toStringRef(
NonSkeletonUnitDie.find({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
if (DUDwoName != TUDwoName)
continue; // Skip this TU, it isn't the one in the .dwp file.
}
} else {
NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit();
}
uint64_t DIEOffset =
NonSkeletonUnit->getOffset() + *EntryOr->getDIEUnitOffset();
const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset();
Expand Down Expand Up @@ -1920,15 +1962,24 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
for (const DWARFDebugNames::NameTableEntry &NTE : NI)
NumErrors += verifyNameIndexEntries(NI, NTE);

if (NumErrors > 0)
return NumErrors;

for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) {
for (const std::unique_ptr<DWARFUnit> &U : DCtx.info_section_units()) {
if (const DWARFDebugNames::NameIndex *NI =
AccelTable.getCUNameIndex(U->getOffset())) {
auto *CU = cast<DWARFCompileUnit>(U.get());
for (const DWARFDebugInfoEntry &Die : CU->dies())
NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
AccelTable.getCUOrTUNameIndex(U->getOffset())) {
DWARFCompileUnit *CU = cast<DWARFCompileUnit>(U.get());
if (CU && CU->getDWOId()) {
DWARFDie CUDie = CU->getUnitDIE(true);
DWARFDie NonSkeletonUnitDie =
CUDie.getDwarfUnit()->getNonSkeletonUnitDIE(false);
if (CUDie != NonSkeletonUnitDie) {
for (const DWARFDebugInfoEntry &Die :
NonSkeletonUnitDie.getDwarfUnit()->dies())
NumErrors += verifyNameIndexCompleteness(
DWARFDie(NonSkeletonUnitDie.getDwarfUnit(), &Die), *NI);
}
} else {
for (const DWARFDebugInfoEntry &Die : CU->dies())
NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
}
}
}
return NumErrors;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
SectionHeaderStringTable: .strtab
Sections:
- Name: .debug_info.dwo
Type: SHT_PROGBITS
Flags: [ SHF_EXCLUDE ]
AddressAlign: 0x1
Content: 3A0000000500060800000000F25C0974DC2049EF210000000121000304000000000205070400020305300000000004000439000000060003000501050400320000000500060800000000F111DEDB09E62F8A2100000001210003040000000002050A0400070309310000000008000005010504005300000005000508000000004F3AF08A9CD57502060B21000C04070021000000015600000B400000000802917802000C440000000802917408000D4D000000000501050409F25C0974DC2049EF09F111DEDB09E62F8A00
- Name: .debug_str_offsets.dwo
Type: SHT_PROGBITS
Flags: [ SHF_EXCLUDE ]
AddressAlign: 0x1
Content: 38000000050000000000000005000000090000000B0000000D0000001600000018000000240000002F00000034000000360000003F000000AF000000
- Name: .debug_str.dwo
Type: SHT_PROGBITS
Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x1
EntSize: 0x1
Content: 6D61696E00696E740063002E006D61696E2E64776F007800496E74656765725479706500437573746F6D547970650063617270006100436172705479706500636C616E672076657273696F6E2032302E302E30676974202868747470733A2F2F6769746875622E636F6D2F636C6179626F72672F6C6C766D2D70726F6A6563742E676974203937383833363863333763333139623131656239613331616630663130616163363262613466373229006D61696E2E63707000
- Name: .debug_abbrev.dwo
Type: SHT_PROGBITS
Flags: [ SHF_EXCLUDE ]
AddressAlign: 0x1
Content: 01410113051B25762510170000021301360B03250B0B3A0B3B0B0000030D00032549133A0B3B0B380B0000041600491303253A0B3B0B000005240003253E0B0B0B000006110125251305032576250000072E01111B1206401803253A0B3B0B49133F190000083400021803253A0B3B0B491300000913003C196920000000
- Name: .debug_line.dwo
Type: SHT_PROGBITS
Flags: [ SHF_EXCLUDE ]
AddressAlign: 0x1
Content: 36000000050008002E000000010101FB0E01010108012E00030108020F051E016D61696E2E6370700000D76E37CBD0032FAB59BE5997238B5EB3
- Type: SectionHeaderTable
Sections:
- Name: .strtab
- Name: .debug_info.dwo
- Name: .debug_str_offsets.dwo
- Name: .debug_str.dwo
- Name: .debug_abbrev.dwo
- Name: .debug_line.dwo
...

Loading
Loading