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