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,7 +1586,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
15961586 for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
15971587 EntryOr = NI.getEntry (&NextEntryID)) {
15981588
1599- std::optional<uint64_t > CUIndex = EntryOr->getCUIndex ();
1589+ std::optional<uint64_t > CUIndex = EntryOr->getRelatedCUIndex ();
16001590 std::optional<uint64_t > TUIndex = EntryOr->getLocalTUIndex ();
16011591 if (CUIndex && *CUIndex >= NI.getCUCount ()) {
16021592 ErrorCategory.Report (" Name Index entry contains invalid CU index" , [&]() {
@@ -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,10 +1609,28 @@ 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 (CUIndex)
16231613 UnitOffset = NI.getCUOffset (*CUIndex);
1614+ else if (TUIndex) {
1615+ if (*TUIndex >= NumLocalTUs) {
1616+ // Foreign type units must have a valid CU index, either from a
1617+ // DW_IDX_comp_unit attribute value or from the .debug_names table only
1618+ // having a single compile unit. We need the originating compile unit
1619+ // because foreign type units can come from any .dwo file, yet only one
1620+ // copy of the type unit will end up in the .dwp file.
1621+ ErrorCategory.Report (
1622+ " Name Index entry contains foreign TU index with invalid CU index" ,
1623+ [&]() {
1624+ error () << formatv (
1625+ " Name Index @ {0:x}: Entry @ {1:x} contains an "
1626+ " foreign TU index ({2}) with no CU index.\n " ,
1627+ NI.getUnitOffset (), EntryID, *TUIndex);
1628+ });
1629+ ++NumErrors;
1630+ continue ;
1631+ }
1632+ UnitOffset = NI.getLocalTUOffset (*TUIndex);
1633+ }
16241634 if (!UnitOffset)
16251635 continue ;
16261636 // For split DWARF entries we need to make sure we find the non skeleton
@@ -1650,20 +1660,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
16501660 // call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
16511661 // will return the unit DIE of DU if we aren't able to get the .dwo file,
16521662 // but that is what the function currently does.
1663+ DWARFDie UnitDie = DU->getUnitDIE ();
16531664 DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE ();
1654- if (DU->getDWOId () && DU-> getUnitDIE () == NonSkeletonUnitDie) {
1665+ if (DU->getDWOId () && UnitDie == NonSkeletonUnitDie) {
16551666 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);
1667+ error () << formatv (
1668+ " Name Index @ {0:x}: Entry @ {1 :x} unable to load "
1669+ " .dwo file \" {2} \" for DWARF unit @ {3:x}. \n " ,
1670+ NI. getUnitOffset (), EntryID,
1671+ dwarf::toString (UnitDie. find ( {DW_AT_dwo_name, DW_AT_GNU_dwo_name})),
1672+ *UnitOffset);
16621673 });
16631674 ++NumErrors;
16641675 continue ;
16651676 }
1666- DWARFUnit *NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit ();
1677+ DWARFUnit *NonSkeletonUnit = nullptr ;
1678+ if (TUIndex && *TUIndex >= NumLocalTUs) {
1679+ // We have a foreign TU index, which either means we have a .dwo file
1680+ // that has one or more type units, or we have a .dwp file with on or
1681+ // more type units. We need to get the type unit from the DWARFContext
1682+ // of the .dwo. We got the NonSkeletonUnitDie above that has the .dwo
1683+ // or .dwp DWARF context, so we have to get the type unit from that file.
1684+ // We have also verified that NonSkeletonUnitDie points to a DWO file
1685+ // above, so we know we have the right file.
1686+ const uint32_t ForeignTUIdx = *TUIndex - NumLocalTUs;
1687+ const uint64_t TypeSig = NI.getForeignTUSignature (ForeignTUIdx);
1688+ llvm::DWARFContext &SkeletonDCtx =
1689+ NonSkeletonUnitDie.getDwarfUnit ()->getContext ();
1690+ // Now find the type unit from the type signature and then update the
1691+ // NonSkeletonUnitDie to point to the actual type unit in the .dwo/.dwp.
1692+ NonSkeletonUnit =
1693+ SkeletonDCtx.getTypeUnitForHash (TypeSig, /* IsDWO=*/ true );
1694+ NonSkeletonUnitDie = NonSkeletonUnit->getUnitDIE (true );
1695+ // If we have foreign type unit in a DWP file, then we need to ignore
1696+ // any entries from type units that don't match the one that made it into
1697+ // the .dwp file.
1698+ if (SkeletonDCtx.isDWP ()) {
1699+ StringRef DUDwoName = dwarf::toStringRef (
1700+ UnitDie.find ({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1701+ StringRef TUDwoName = dwarf::toStringRef (
1702+ NonSkeletonUnitDie.find ({DW_AT_dwo_name, DW_AT_GNU_dwo_name}));
1703+ if (DUDwoName != TUDwoName)
1704+ continue ; // Skip this TU, it isn't the one in the .dwp file.
1705+ }
1706+ } else {
1707+ NonSkeletonUnit = NonSkeletonUnitDie.getDwarfUnit ();
1708+ }
16671709 uint64_t DIEOffset =
16681710 NonSkeletonUnit->getOffset () + *EntryOr->getDIEUnitOffset ();
16691711 const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset ();
@@ -1920,15 +1962,24 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
19201962 for (const DWARFDebugNames::NameTableEntry &NTE : NI)
19211963 NumErrors += verifyNameIndexEntries (NI, NTE);
19221964
1923- if (NumErrors > 0 )
1924- return NumErrors;
1925-
1926- for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units ()) {
1965+ for (const std::unique_ptr<DWARFUnit> &U : DCtx.info_section_units ()) {
19271966 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);
1967+ AccelTable.getCUOrTUNameIndex (U->getOffset ())) {
1968+ DWARFCompileUnit *CU = cast<DWARFCompileUnit>(U.get ());
1969+ if (CU && CU->getDWOId ()) {
1970+ DWARFDie CUDie = CU->getUnitDIE (true );
1971+ DWARFDie NonSkeletonUnitDie =
1972+ CUDie.getDwarfUnit ()->getNonSkeletonUnitDIE (false );
1973+ if (CUDie != NonSkeletonUnitDie) {
1974+ for (const DWARFDebugInfoEntry &Die :
1975+ NonSkeletonUnitDie.getDwarfUnit ()->dies ())
1976+ NumErrors += verifyNameIndexCompleteness (
1977+ DWARFDie (NonSkeletonUnitDie.getDwarfUnit (), &Die), *NI);
1978+ }
1979+ } else {
1980+ for (const DWARFDebugInfoEntry &Die : CU->dies ())
1981+ NumErrors += verifyNameIndexCompleteness (DWARFDie (CU, &Die), *NI);
1982+ }
19321983 }
19331984 }
19341985 return NumErrors;
0 commit comments