@@ -496,108 +496,112 @@ void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
496496}
497497
498498Error 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+ }
508529
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+ }
512549
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+ }
528552
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+ }
550572
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.
555573 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 ;
557579 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+ }
570599
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.
597602
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+ });
601605}
602606
603607bool DWARFUnit::parseDWO (StringRef DWOAlternativeLocation) {
@@ -652,15 +656,21 @@ bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
652656 return true ;
653657}
654658
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+ }));
664674}
665675
666676Expected<DWARFAddressRangesVector>
0 commit comments