@@ -496,107 +496,111 @@ void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
496496}
497497
498498Error 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+ }
507528
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+ }
511548
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+ }
527551
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+ }
549571
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.
554572 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 ;
556578 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+ }
569598
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.
596601
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+ });
600604}
601605
602606bool DWARFUnit::parseDWO (StringRef DWOAlternativeLocation) {
@@ -651,15 +655,21 @@ bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
651655 return true ;
652656}
653657
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+ }));
663673}
664674
665675Expected<DWARFAddressRangesVector>
0 commit comments