@@ -496,107 +496,111 @@ void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
496
496
}
497
497
498
498
Error DWARFUnit::tryExtractDIEsIfNeeded (bool CUDieOnly) {
499
- if ((CUDieOnly && !DieArray.empty ()) || DieArray.size () > 1 )
500
- return Error::success (); // Already parsed.
501
-
502
- bool HasCUDie = !DieArray.empty ();
503
- extractDIEsToVector (!HasCUDie, !CUDieOnly, DieArray);
504
-
505
- if (DieArray.empty ())
506
- return Error::success ();
499
+ return Context.doWorkThreadSafely ([&]() -> Error {
500
+ if ((CUDieOnly && !DieArray.empty ()) || DieArray.size () > 1 )
501
+ return Error::success (); // Already parsed.
502
+
503
+ bool HasCUDie = !DieArray.empty ();
504
+ extractDIEsToVector (!HasCUDie, !CUDieOnly, DieArray);
505
+
506
+ if (DieArray.empty ())
507
+ return Error::success ();
508
+
509
+ // If CU DIE was just parsed, copy several attribute values from it.
510
+ if (HasCUDie)
511
+ return Error::success ();
512
+
513
+ DWARFDie UnitDie (this , &DieArray[0 ]);
514
+ if (std::optional<uint64_t > DWOId =
515
+ toUnsigned (UnitDie.find (DW_AT_GNU_dwo_id)))
516
+ Header.setDWOId (*DWOId);
517
+ if (!IsDWO) {
518
+ assert (AddrOffsetSectionBase == std::nullopt);
519
+ assert (RangeSectionBase == 0 );
520
+ assert (LocSectionBase == 0 );
521
+ AddrOffsetSectionBase = toSectionOffset (UnitDie.find (DW_AT_addr_base));
522
+ if (!AddrOffsetSectionBase)
523
+ AddrOffsetSectionBase =
524
+ toSectionOffset (UnitDie.find (DW_AT_GNU_addr_base));
525
+ RangeSectionBase = toSectionOffset (UnitDie.find (DW_AT_rnglists_base), 0 );
526
+ LocSectionBase = toSectionOffset (UnitDie.find (DW_AT_loclists_base), 0 );
527
+ }
507
528
508
- // If CU DIE was just parsed, copy several attribute values from it.
509
- if (HasCUDie)
510
- return Error::success ();
529
+ // In general, in DWARF v5 and beyond we derive the start of the unit's
530
+ // contribution to the string offsets table from the unit DIE's
531
+ // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
532
+ // attribute, so we assume that there is a contribution to the string
533
+ // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
534
+ // In both cases we need to determine the format of the contribution,
535
+ // which may differ from the unit's format.
536
+ DWARFDataExtractor DA (Context.getDWARFObj (), StringOffsetSection,
537
+ IsLittleEndian, 0 );
538
+ if (IsDWO || getVersion () >= 5 ) {
539
+ auto StringOffsetOrError =
540
+ IsDWO ? determineStringOffsetsTableContributionDWO (DA)
541
+ : determineStringOffsetsTableContribution (DA);
542
+ if (!StringOffsetOrError) {
543
+ return createStringError (errc::invalid_argument,
544
+ " invalid reference to or invalid content in "
545
+ " .debug_str_offsets[.dwo]: " +
546
+ toString (StringOffsetOrError.takeError ()));
547
+ }
511
548
512
- DWARFDie UnitDie (this , &DieArray[0 ]);
513
- if (std::optional<uint64_t > DWOId =
514
- toUnsigned (UnitDie.find (DW_AT_GNU_dwo_id)))
515
- Header.setDWOId (*DWOId);
516
- if (!IsDWO) {
517
- assert (AddrOffsetSectionBase == std::nullopt);
518
- assert (RangeSectionBase == 0 );
519
- assert (LocSectionBase == 0 );
520
- AddrOffsetSectionBase = toSectionOffset (UnitDie.find (DW_AT_addr_base));
521
- if (!AddrOffsetSectionBase)
522
- AddrOffsetSectionBase =
523
- toSectionOffset (UnitDie.find (DW_AT_GNU_addr_base));
524
- RangeSectionBase = toSectionOffset (UnitDie.find (DW_AT_rnglists_base), 0 );
525
- LocSectionBase = toSectionOffset (UnitDie.find (DW_AT_loclists_base), 0 );
526
- }
549
+ StringOffsetsTableContribution = *StringOffsetOrError;
550
+ }
527
551
528
- // In general, in DWARF v5 and beyond we derive the start of the unit's
529
- // contribution to the string offsets table from the unit DIE's
530
- // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
531
- // attribute, so we assume that there is a contribution to the string
532
- // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
533
- // In both cases we need to determine the format of the contribution,
534
- // which may differ from the unit's format.
535
- DWARFDataExtractor DA (Context.getDWARFObj (), StringOffsetSection,
536
- IsLittleEndian, 0 );
537
- if (IsDWO || getVersion () >= 5 ) {
538
- auto StringOffsetOrError =
539
- IsDWO ? determineStringOffsetsTableContributionDWO (DA)
540
- : determineStringOffsetsTableContribution (DA);
541
- if (!StringOffsetOrError)
542
- return createStringError (errc::invalid_argument,
543
- " invalid reference to or invalid content in "
544
- " .debug_str_offsets[.dwo]: " +
545
- toString (StringOffsetOrError.takeError ()));
546
-
547
- StringOffsetsTableContribution = *StringOffsetOrError;
548
- }
552
+ // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
553
+ // describe address ranges.
554
+ if (getVersion () >= 5 ) {
555
+ // In case of DWP, the base offset from the index has to be added.
556
+ if (IsDWO) {
557
+ uint64_t ContributionBaseOffset = 0 ;
558
+ if (auto *IndexEntry = Header.getIndexEntry ())
559
+ if (auto *Contrib = IndexEntry->getContribution (DW_SECT_RNGLISTS))
560
+ ContributionBaseOffset = Contrib->getOffset ();
561
+ setRangesSection (
562
+ &Context.getDWARFObj ().getRnglistsDWOSection (),
563
+ ContributionBaseOffset +
564
+ DWARFListTableHeader::getHeaderSize (Header.getFormat ()));
565
+ } else
566
+ setRangesSection (&Context.getDWARFObj ().getRnglistsSection (),
567
+ toSectionOffset (UnitDie.find (DW_AT_rnglists_base),
568
+ DWARFListTableHeader::getHeaderSize (
569
+ Header.getFormat ())));
570
+ }
549
571
550
- // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
551
- // describe address ranges.
552
- if (getVersion () >= 5 ) {
553
- // In case of DWP, the base offset from the index has to be added.
554
572
if (IsDWO) {
555
- uint64_t ContributionBaseOffset = 0 ;
573
+ // If we are reading a package file, we need to adjust the location list
574
+ // data based on the index entries.
575
+ StringRef Data = Header.getVersion () >= 5
576
+ ? Context.getDWARFObj ().getLoclistsDWOSection ().Data
577
+ : Context.getDWARFObj ().getLocDWOSection ().Data ;
556
578
if (auto *IndexEntry = Header.getIndexEntry ())
557
- if (auto *Contrib = IndexEntry->getContribution (DW_SECT_RNGLISTS))
558
- ContributionBaseOffset = Contrib->getOffset ();
559
- setRangesSection (
560
- &Context.getDWARFObj ().getRnglistsDWOSection (),
561
- ContributionBaseOffset +
562
- DWARFListTableHeader::getHeaderSize (Header.getFormat ()));
563
- } else
564
- setRangesSection (&Context.getDWARFObj ().getRnglistsSection (),
565
- toSectionOffset (UnitDie.find (DW_AT_rnglists_base),
566
- DWARFListTableHeader::getHeaderSize (
567
- Header.getFormat ())));
568
- }
579
+ if (const auto *C = IndexEntry->getContribution (
580
+ Header.getVersion () >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
581
+ Data = Data.substr (C->getOffset (), C->getLength ());
582
+
583
+ DWARFDataExtractor DWARFData (Data, IsLittleEndian, getAddressByteSize ());
584
+ LocTable =
585
+ std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion ());
586
+ LocSectionBase = DWARFListTableHeader::getHeaderSize (Header.getFormat ());
587
+ } else if (getVersion () >= 5 ) {
588
+ LocTable = std::make_unique<DWARFDebugLoclists>(
589
+ DWARFDataExtractor (Context.getDWARFObj (),
590
+ Context.getDWARFObj ().getLoclistsSection (),
591
+ IsLittleEndian, getAddressByteSize ()),
592
+ getVersion ());
593
+ } else {
594
+ LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor (
595
+ Context.getDWARFObj (), Context.getDWARFObj ().getLocSection (),
596
+ IsLittleEndian, getAddressByteSize ()));
597
+ }
569
598
570
- if (IsDWO) {
571
- // If we are reading a package file, we need to adjust the location list
572
- // data based on the index entries.
573
- StringRef Data = Header.getVersion () >= 5
574
- ? Context.getDWARFObj ().getLoclistsDWOSection ().Data
575
- : Context.getDWARFObj ().getLocDWOSection ().Data ;
576
- if (auto *IndexEntry = Header.getIndexEntry ())
577
- if (const auto *C = IndexEntry->getContribution (
578
- Header.getVersion () >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
579
- Data = Data.substr (C->getOffset (), C->getLength ());
580
-
581
- DWARFDataExtractor DWARFData (Data, IsLittleEndian, getAddressByteSize ());
582
- LocTable =
583
- std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion ());
584
- LocSectionBase = DWARFListTableHeader::getHeaderSize (Header.getFormat ());
585
- } else if (getVersion () >= 5 ) {
586
- LocTable = std::make_unique<DWARFDebugLoclists>(
587
- DWARFDataExtractor (Context.getDWARFObj (),
588
- Context.getDWARFObj ().getLoclistsSection (),
589
- IsLittleEndian, getAddressByteSize ()),
590
- getVersion ());
591
- } else {
592
- LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor (
593
- Context.getDWARFObj (), Context.getDWARFObj ().getLocSection (),
594
- IsLittleEndian, getAddressByteSize ()));
595
- }
599
+ // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
600
+ // skeleton CU DIE, so that DWARF users not aware of it are not broken.
596
601
597
- // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
598
- // skeleton CU DIE, so that DWARF users not aware of it are not broken.
599
- return Error::success ();
602
+ return Error::success ();
603
+ });
600
604
}
601
605
602
606
bool DWARFUnit::parseDWO (StringRef DWOAlternativeLocation) {
@@ -651,15 +655,21 @@ bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
651
655
return true ;
652
656
}
653
657
654
- void DWARFUnit::clearDIEs (bool KeepCUDie) {
655
- // Do not use resize() + shrink_to_fit() to free memory occupied by dies.
656
- // shrink_to_fit() is a *non-binding* request to reduce capacity() to size().
657
- // It depends on the implementation whether the request is fulfilled.
658
- // Create a new vector with a small capacity and assign it to the DieArray to
659
- // have previous contents freed.
660
- DieArray = (KeepCUDie && !DieArray.empty ())
661
- ? std::vector<DWARFDebugInfoEntry>({DieArray[0 ]})
662
- : std::vector<DWARFDebugInfoEntry>();
658
+ void DWARFUnit::clearDIEs (bool KeepCUDie, bool KeepDWODies) {
659
+ cantFail (Context.doWorkThreadSafely ([&] {
660
+ if (!KeepDWODies && DWO) {
661
+ DWO->clearDIEs (KeepCUDie, KeepDWODies);
662
+ }
663
+ // Do not use resize() + shrink_to_fit() to free memory occupied by dies.
664
+ // shrink_to_fit() is a *non-binding* request to reduce capacity() to
665
+ // size(). It depends on the implementation whether the request is
666
+ // fulfilled. Create a new vector with a small capacity and assign it to the
667
+ // DieArray to have previous contents freed.
668
+ DieArray = (KeepCUDie && !DieArray.empty ())
669
+ ? std::vector<DWARFDebugInfoEntry>({DieArray[0 ]})
670
+ : std::vector<DWARFDebugInfoEntry>();
671
+ return Error::success ();
672
+ }));
663
673
}
664
674
665
675
Expected<DWARFAddressRangesVector>
0 commit comments