2424#include " llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
2525#include " llvm/DebugInfo/DWARF/DWARFObject.h"
2626#include " llvm/DebugInfo/DWARF/DWARFSection.h"
27+ #include " llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
2728#include " llvm/DebugInfo/DWARF/DWARFUnit.h"
2829#include " llvm/Object/Error.h"
2930#include " llvm/Support/DJB.h"
@@ -1479,13 +1480,6 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(
14791480
14801481unsigned
14811482DWARFVerifier::verifyNameIndexAbbrevs (const DWARFDebugNames::NameIndex &NI) {
1482- if (NI.getForeignTUCount () > 0 ) {
1483- warn () << formatv (" Name Index @ {0:x}: Verifying indexes of foreign type "
1484- " units is not currently supported.\n " ,
1485- NI.getUnitOffset ());
1486- return 0 ;
1487- }
1488-
14891483 unsigned NumErrors = 0 ;
14901484 for (const auto &Abbrev : NI.getAbbrevs ()) {
14911485 StringRef TagName = dwarf::TagString (Abbrev.Tag );
@@ -1573,10 +1567,6 @@ static SmallVector<std::string, 3> getNames(const DWARFDie &DIE,
15731567unsigned DWARFVerifier::verifyNameIndexEntries (
15741568 const DWARFDebugNames::NameIndex &NI,
15751569 const DWARFDebugNames::NameTableEntry &NTE) {
1576- // Verifying foreign type unit indexes not supported.
1577- if (NI.getForeignTUCount () > 0 )
1578- return 0 ;
1579-
15801570 const char *CStr = NTE.getString ();
15811571 if (!CStr) {
15821572 ErrorCategory.Report (" Unable to get string associated with name" , [&]() {
@@ -1596,8 +1586,8 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
15961586 for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
15971587 EntryOr = NI.getEntry (&NextEntryID)) {
15981588
1599- std::optional<uint64_t > CUIndex = EntryOr->getCUIndex ();
1600- std::optional<uint64_t > TUIndex = EntryOr->getLocalTUIndex ();
1589+ std::optional<uint64_t > CUIndex = EntryOr->getRelatedCUIndex ();
1590+ std::optional<uint64_t > TUIndex = EntryOr->getTUIndex ();
16011591 if (CUIndex && *CUIndex >= NI.getCUCount ()) {
16021592 ErrorCategory.Report (" Name Index entry contains invalid CU index" , [&]() {
16031593 error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} contains an "
@@ -1607,7 +1597,9 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
16071597 ++NumErrors;
16081598 continue ;
16091599 }
1610- if (TUIndex && *TUIndex >= NI.getLocalTUCount ()) {
1600+ const uint32_t NumLocalTUs = NI.getLocalTUCount ();
1601+ const uint32_t NumForeignTUs = NI.getForeignTUCount ();
1602+ if (TUIndex && *TUIndex >= (NumLocalTUs + NumForeignTUs)) {
16111603 ErrorCategory.Report (" Name Index entry contains invalid TU index" , [&]() {
16121604 error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} contains an "
16131605 " invalid TU index ({2}).\n " ,
@@ -1617,11 +1609,44 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
16171609 continue ;
16181610 }
16191611 std::optional<uint64_t > UnitOffset;
1620- if (TUIndex)
1621- UnitOffset = NI.getLocalTUOffset (*TUIndex);
1622- else if (CUIndex)
1612+ if (TUIndex) {
1613+ // We have a local or foreign type unit.
1614+ if (*TUIndex >= NumLocalTUs) {
1615+ // This is a foreign type unit, we will find the right type unit by
1616+ // type unit signature later in this function.
1617+
1618+ // Foreign type units must have a valid CU index, either from a
1619+ // DW_IDX_comp_unit attribute value or from the .debug_names table only
1620+ // having a single compile unit. We need the originating compile unit
1621+ // because foreign type units can come from any .dwo file, yet only one
1622+ // copy of the type unit will end up in the .dwp file.
1623+ if (CUIndex) {
1624+ // We need the local skeleton unit offset for the code below.
1625+ UnitOffset = NI.getCUOffset (*CUIndex);
1626+ } else {
1627+ ErrorCategory.Report (
1628+ " Name Index entry contains foreign TU index with invalid CU "
1629+ " index" ,
1630+ [&]() {
1631+ error () << formatv (
1632+ " Name Index @ {0:x}: Entry @ {1:x} contains an "
1633+ " foreign TU index ({2}) with no CU index.\n " ,
1634+ NI.getUnitOffset (), EntryID, *TUIndex);
1635+ });
1636+ ++NumErrors;
1637+ continue ;
1638+ }
1639+ } else {
1640+ // Local type unit, get the DWARF unit offset for the type unit.
1641+ UnitOffset = NI.getLocalTUOffset (*TUIndex);
1642+ }
1643+ } else if (CUIndex) {
1644+ // Local CU entry, get the DWARF unit offset for the CU.
16231645 UnitOffset = NI.getCUOffset (*CUIndex);
1624- if (!UnitOffset)
1646+ }
1647+
1648+ // Watch for tombstoned type unit entries.
1649+ if (!UnitOffset || UnitOffset == UINT32_MAX)
16251650 continue ;
16261651 // For split DWARF entries we need to make sure we find the non skeleton
16271652 // DWARF unit that is needed and use that's DWARF unit offset as the
@@ -1633,7 +1658,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
16331658 ErrorCategory.Report (
16341659 " Name Index entry contains invalid CU or TU offset" , [&]() {
16351660 error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} contains an "
1636- " invalid CU or TU offset {1 :x}.\n " ,
1661+ " invalid CU or TU offset {2 :x}.\n " ,
16371662 NI.getUnitOffset (), EntryID, *UnitOffset);
16381663 });
16391664 ++NumErrors;
@@ -1650,20 +1675,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
16501675 // call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
16511676 // will return the unit DIE of DU if we aren't able to get the .dwo file,
16521677 // but that is what the function currently does.
1678+ DWARFDie UnitDie = DU->getUnitDIE ();
16531679 DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE ();
1654- if (DU->getDWOId () && DU-> getUnitDIE () == NonSkeletonUnitDie) {
1680+ if (DU->getDWOId () && UnitDie == NonSkeletonUnitDie) {
16551681 ErrorCategory.Report (" Unable to get load .dwo file" , [&]() {
1656- error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} unable to load "
1657- " .dwo file \" {2} \" for DWARF unit @ {3 :x}. \n " ,
1658- NI. getUnitOffset (), EntryID ,
1659- dwarf::toString (DU-> getUnitDIE (). find (
1660- {DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
1661- *UnitOffset);
1682+ error () << formatv (
1683+ " Name Index @ {0:x}: Entry @ {1 :x} unable to load "
1684+ " .dwo file \" {2} \" for DWARF unit @ {3:x}. \n " ,
1685+ NI. getUnitOffset (), EntryID,
1686+ dwarf::toString (UnitDie. find ( {DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
1687+ *UnitOffset);
16621688 });
16631689 ++NumErrors;
16641690 continue ;
16651691 }
1666- DWARFUnit *NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit ();
1692+ DWARFUnit *NonSkeletonUnit = nullptr ;
1693+ if (TUIndex && *TUIndex >= NumLocalTUs) {
1694+ // We have a foreign TU index, which either means we have a .dwo file
1695+ // that has one or more type units, or we have a .dwp file with one or
1696+ // more type units. We need to get the type unit from the DWARFContext
1697+ // of the .dwo. We got the NonSkeletonUnitDie above that has the .dwo
1698+ // or .dwp DWARF context, so we have to get the type unit from that file.
1699+ // We have also verified that NonSkeletonUnitDie points to a DWO file
1700+ // above, so we know we have the right file.
1701+ const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
1702+ const uint64_t TypeSig = NI.getForeignTUSignature (ForeignTUIdx);
1703+ llvm::DWARFContext &SkeletonDCtx =
1704+ NonSkeletonUnitDie.getDwarfUnit ()->getContext ();
1705+ // Now find the type unit from the type signature and then update the
1706+ // NonSkeletonUnitDie to point to the actual type unit in the .dwo/.dwp.
1707+ NonSkeletonUnit =
1708+ SkeletonDCtx.getTypeUnitForHash (TypeSig, /* IsDWO=*/ true );
1709+ NonSkeletonUnitDie = NonSkeletonUnit->getUnitDIE (true );
1710+ // If we have foreign type unit in a DWP file, then we need to ignore
1711+ // any entries from type units that don't match the one that made it into
1712+ // the .dwp file.
1713+ if (SkeletonDCtx.isDWP ()) {
1714+ StringRef DUDwoName = dwarf::toStringRef (
1715+ UnitDie.find ({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1716+ StringRef TUDwoName = dwarf::toStringRef (
1717+ NonSkeletonUnitDie.find ({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1718+ if (DUDwoName != TUDwoName)
1719+ continue ; // Skip this TU, it isn't the one in the .dwp file.
1720+ }
1721+ } else {
1722+ NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit ();
1723+ }
16671724 uint64_t DIEOffset =
16681725 NonSkeletonUnit->getOffset () + *EntryOr->getDIEUnitOffset ();
16691726 const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset ();
@@ -1920,15 +1977,26 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
19201977 for (const DWARFDebugNames::NameTableEntry &NTE : NI)
19211978 NumErrors += verifyNameIndexEntries (NI, NTE);
19221979
1923- if (NumErrors > 0 )
1924- return NumErrors;
1925-
1926- for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units ()) {
1980+ for (const std::unique_ptr<DWARFUnit> &U : DCtx.info_section_units ()) {
19271981 if (const DWARFDebugNames::NameIndex *NI =
1928- AccelTable.getCUNameIndex (U->getOffset ())) {
1929- auto *CU = cast<DWARFCompileUnit>(U.get ());
1930- for (const DWARFDebugInfoEntry &Die : CU->dies ())
1931- NumErrors += verifyNameIndexCompleteness (DWARFDie (CU, &Die), *NI);
1982+ AccelTable.getCUOrTUNameIndex (U->getOffset ())) {
1983+ DWARFCompileUnit *CU = dyn_cast<DWARFCompileUnit>(U.get ());
1984+ if (CU) {
1985+ if (CU->getDWOId ()) {
1986+ DWARFDie CUDie = CU->getUnitDIE (true );
1987+ DWARFDie NonSkeletonUnitDie =
1988+ CUDie.getDwarfUnit ()->getNonSkeletonUnitDIE (false );
1989+ if (CUDie != NonSkeletonUnitDie) {
1990+ for (const DWARFDebugInfoEntry &Die :
1991+ NonSkeletonUnitDie.getDwarfUnit ()->dies ())
1992+ NumErrors += verifyNameIndexCompleteness (
1993+ DWARFDie (NonSkeletonUnitDie.getDwarfUnit (), &Die), *NI);
1994+ }
1995+ } else {
1996+ for (const DWARFDebugInfoEntry &Die : CU->dies ())
1997+ NumErrors += verifyNameIndexCompleteness (DWARFDie (CU, &Die), *NI);
1998+ }
1999+ }
19322000 }
19332001 }
19342002 return NumErrors;
0 commit comments