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,8 +1586,8 @@ 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 ();
1600
- std::optional<uint64_t > TUIndex = EntryOr->getLocalTUIndex ();
1589
+ std::optional<uint64_t > CUIndex = EntryOr->getRelatedCUIndex ();
1590
+ std::optional<uint64_t > TUIndex = EntryOr->getTUIndex ();
1601
1591
if (CUIndex && *CUIndex >= NI.getCUCount ()) {
1602
1592
ErrorCategory.Report (" Name Index entry contains invalid CU index" , [&]() {
1603
1593
error () << formatv (" Name Index @ {0:x}: Entry @ {1:x} contains an "
@@ -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,11 +1609,44 @@ 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 (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.
1623
1645
UnitOffset = NI.getCUOffset (*CUIndex);
1624
- if (!UnitOffset)
1646
+ }
1647
+
1648
+ // Watch for tombstoned type unit entries.
1649
+ if (!UnitOffset || UnitOffset == UINT32_MAX)
1625
1650
continue ;
1626
1651
// For split DWARF entries we need to make sure we find the non skeleton
1627
1652
// DWARF unit that is needed and use that's DWARF unit offset as the
@@ -1633,7 +1658,7 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1633
1658
ErrorCategory.Report (
1634
1659
" Name Index entry contains invalid CU or TU offset" , [&]() {
1635
1660
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 " ,
1637
1662
NI.getUnitOffset (), EntryID, *UnitOffset);
1638
1663
});
1639
1664
++NumErrors;
@@ -1650,20 +1675,52 @@ unsigned DWARFVerifier::verifyNameIndexEntries(
1650
1675
// call to properly deal with it. It isn't clear that getNonSkeletonUnitDIE
1651
1676
// will return the unit DIE of DU if we aren't able to get the .dwo file,
1652
1677
// but that is what the function currently does.
1678
+ DWARFDie UnitDie = DU->getUnitDIE ();
1653
1679
DWARFDie NonSkeletonUnitDie = DU->getNonSkeletonUnitDIE ();
1654
- if (DU->getDWOId () && DU-> getUnitDIE () == NonSkeletonUnitDie) {
1680
+ if (DU->getDWOId () && UnitDie == NonSkeletonUnitDie) {
1655
1681
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);
1662
1688
});
1663
1689
++NumErrors;
1664
1690
continue ;
1665
1691
}
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
+ }
1667
1724
uint64_t DIEOffset =
1668
1725
NonSkeletonUnit->getOffset () + *EntryOr->getDIEUnitOffset ();
1669
1726
const uint64_t NextUnitOffset = NonSkeletonUnit->getNextUnitOffset ();
@@ -1920,15 +1977,26 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
1920
1977
for (const DWARFDebugNames::NameTableEntry &NTE : NI)
1921
1978
NumErrors += verifyNameIndexEntries (NI, NTE);
1922
1979
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 ()) {
1927
1981
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
+ }
1932
2000
}
1933
2001
}
1934
2002
return NumErrors;
0 commit comments