bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; const char *DWOFileName = UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); if (!DWOFileName) return false; const char *CompilationDir = UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); } sys::path::append(AbsolutePath, DWOFileName); DWO = llvm::make_unique<DWOHolder>(AbsolutePath); DWARFUnit *DWOCU = DWO->getUnit(); // Verify that compile unit in .dwo file is valid. if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { DWO.reset(); return false; } // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); return true; }
bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); if (!DWOFileName) return false; auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); SmallString<16> AbsolutePath; if (sys::path::is_relative(*DWOFileName) && CompilationDir && *CompilationDir) { sys::path::append(AbsolutePath, *CompilationDir); } sys::path::append(AbsolutePath, *DWOFileName); auto DWOId = getDWOId(); if (!DWOId) return false; auto DWOContext = Context.getDWOContext(AbsolutePath); if (!DWOContext) return false; DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); return true; }
bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); if (!DWOFileName) return false; auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); SmallString<16> AbsolutePath; if (sys::path::is_relative(*DWOFileName) && CompilationDir && *CompilationDir) { sys::path::append(AbsolutePath, *CompilationDir); } sys::path::append(AbsolutePath, *DWOFileName); auto DWOId = getDWOId(); if (!DWOId) return false; auto DWOContext = Context.getDWOContext(AbsolutePath); if (!DWOContext) return false; DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); if (getVersion() >= 5) { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, isLittleEndian, 0); if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase)) DWO->RngListTable = TableOrError.get(); else WithColor::error() << "parsing a range list table: " << toString(TableOrError.takeError()) << '\n'; if (DWO->RngListTable) DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); } return true; }