24
24
#include " llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
25
25
#include " llvm/DebugInfo/DWARF/DWARFObject.h"
26
26
#include " llvm/DebugInfo/DWARF/DWARFSection.h"
27
+ #include " llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
27
28
#include " llvm/DebugInfo/DWARF/DWARFUnit.h"
28
29
#include " llvm/Object/Error.h"
29
30
#include " llvm/Support/DJB.h"
@@ -1479,13 +1480,6 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(
1479
1480
1480
1481
unsigned
1481
1482
DWARFVerifier::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
-
1489
1483
unsigned NumErrors = 0 ;
1490
1484
for (const auto &Abbrev : NI.getAbbrevs ()) {
1491
1485
StringRef TagName = dwarf::TagString (Abbrev.Tag );
@@ -1573,10 +1567,6 @@ static SmallVector<std::string, 3> getNames(const DWARFDie &DIE,
1573
1567
unsigned DWARFVerifier::verifyNameIndexEntries (
1574
1568
const DWARFDebugNames::NameIndex &NI,
1575
1569
const DWARFDebugNames::NameTableEntry &NTE) {
1576
- // Verifying foreign type unit indexes not supported.
1577
- if (NI.getForeignTUCount () > 0 )
1578
- return 0 ;
1579
-
1580
1570
const char *CStr = NTE.getString ();
1581
1571
if (!CStr) {
1582
1572
ErrorCategory.Report (" Unable to get string associated with name" , [&]() {
@@ -1596,7 +1586,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1596
1586
for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
1597
1587
EntryOr = NI.getEntry (&NextEntryID)) {
1598
1588
1599
- std::optional<uint64_t > CUIndex = EntryOr->getCUIndex ();
1589
+ std::optional<uint64_t > CUIndex = EntryOr->getRelatedCUIndex ();
1600
1590
std::optional<uint64_t > TUIndex = EntryOr->getLocalTUIndex ();
1601
1591
if (CUIndex && *CUIndex >= NI.getCUCount ()) {
1602
1592
ErrorCategory.Report (" Name Index entry contains invalid CU index" , [&]() {
@@ -1607,7 +1597,9 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1607
1597
++NumErrors;
1608
1598
continue ;
1609
1599
}
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)) {
1611
1603
ErrorCategory.Report (" Name Index entry contains invalid TU index" , [&]() {
1612
1604
error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} contains an "
1613
1605
" invalid TU index ({2}).\n " ,
@@ -1617,10 +1609,28 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1617
1609
continue ;
1618
1610
}
1619
1611
std::optional<uint64_t > UnitOffset;
1620
- if (TUIndex)
1621
- UnitOffset = NI.getLocalTUOffset (*TUIndex);
1622
- else if (CUIndex)
1612
+ if (CUIndex)
1623
1613
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
+ }
1624
1634
if (!UnitOffset)
1625
1635
continue ;
1626
1636
// For split DWARF entries we need to make sure we find the non skeleton
@@ -1650,20 +1660,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1650
1660
// call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
1651
1661
// will return the unit DIE of DU if we aren't able to get the .dwo file,
1652
1662
// but that is what the function currently does.
1663
+ DWARFDie UnitDie = DU->getUnitDIE ();
1653
1664
DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE ();
1654
- if (DU->getDWOId () && DU-> getUnitDIE () == NonSkeletonUnitDie) {
1665
+ if (DU->getDWOId () && UnitDie == NonSkeletonUnitDie) {
1655
1666
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);
1662
1673
});
1663
1674
++NumErrors;
1664
1675
continue ;
1665
1676
}
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
+ }
1667
1709
uint64_t DIEOffset =
1668
1710
NonSkeletonUnit->getOffset () + *EntryOr->getDIEUnitOffset ();
1669
1711
const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset ();
@@ -1920,15 +1962,24 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
1920
1962
for (const DWARFDebugNames::NameTableEntry &NTE : NI)
1921
1963
NumErrors += verifyNameIndexEntries (NI, NTE);
1922
1964
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 ()) {
1927
1966
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
+ }
1932
1983
}
1933
1984
}
1934
1985
return NumErrors;
0 commit comments