diff options
Diffstat (limited to 'tools/dsymutil/DwarfLinker.cpp')
-rw-r--r-- | tools/dsymutil/DwarfLinker.cpp | 115 |
1 files changed, 50 insertions, 65 deletions
diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index f1ec8a622671..25f1a0f27122 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -197,30 +197,34 @@ public: CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName) - : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(), - OrigUnit.getAddressByteSize(), - OrigUnit.getUnitDIE().getTag()), - LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc), - ClangModuleName(ClangModuleName) { + : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), + Ranges(RangeAlloc), ClangModuleName(ClangModuleName) { Info.resize(OrigUnit.getNumDIEs()); auto CUDie = OrigUnit.getUnitDIE(false); - unsigned Lang = - CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_language) - .getValueOr(0); - HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus || - Lang == dwarf::DW_LANG_C_plus_plus_03 || - Lang == dwarf::DW_LANG_C_plus_plus_11 || - Lang == dwarf::DW_LANG_C_plus_plus_14 || - Lang == dwarf::DW_LANG_ObjC_plus_plus); + if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language))) + HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus || + *Lang == dwarf::DW_LANG_C_plus_plus_03 || + *Lang == dwarf::DW_LANG_C_plus_plus_11 || + *Lang == dwarf::DW_LANG_C_plus_plus_14 || + *Lang == dwarf::DW_LANG_ObjC_plus_plus); + else + HasODR = false; } DWARFUnit &getOrigUnit() const { return OrigUnit; } unsigned getUniqueID() const { return ID; } + void createOutputDIE() { + NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(), + OrigUnit.getUnitDIE().getTag()); + } + DIE *getOutputUnitDIE() const { - return &const_cast<DIEUnit &>(NewUnit).getUnitDie(); + if (NewUnit) + return &const_cast<DIEUnit &>(*NewUnit).getUnitDie(); + return nullptr; } bool hasODR() const { return HasODR; } @@ -329,7 +333,7 @@ private: DWARFUnit &OrigUnit; unsigned ID; std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index. - DIEUnit NewUnit; + Optional<DIEUnit> NewUnit; uint64_t StartOffset; uint64_t NextUnitOffset; @@ -359,7 +363,7 @@ private: Optional<PatchLocation> UnitRangeAttribute; /// @} - /// \brief Location attributes that need to be transfered from th + /// \brief Location attributes that need to be transferred from the /// original debug_loc section to the liked one. They are stored /// along with the PC offset that is to be applied to their /// function's address. @@ -397,7 +401,8 @@ uint64_t CompileUnit::computeNextUnitOffset() { // The root DIE might be null, meaning that the Unit had nothing to // contribute to the linked output. In that case, we will emit the // unit header without any actual DIE. - NextUnitOffset += NewUnit.getUnitDie().getSize(); + if (NewUnit) + NextUnitOffset += NewUnit->getUnitDie().getSize(); return NextUnitOffset; } @@ -843,8 +848,7 @@ void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit, DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); int64_t UnitPcOffset = 0; - auto OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); - if (OrigLowPc) + if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc(); for (const auto &Attr : Attributes) { @@ -1080,7 +1084,7 @@ void DwarfStreamer::emitCIE(StringRef CIEBytes) { /// \brief Emit a FDE into the debug_frame section. \p FDEBytes /// contains the FDE data without the length, CIE offset and address -/// which will be replaced with the paramter values. +/// which will be replaced with the parameter values. void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint32_t Address, StringRef FDEBytes) { MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); @@ -1558,8 +1562,7 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext( // Do not unique anything inside CU local functions. if ((Context.getTag() == dwarf::DW_TAG_namespace || Context.getTag() == dwarf::DW_TAG_compile_unit) && - !DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_external) - .getValueOr(0)) + !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0)) return PointerIntPair<DeclContext *, 1>(nullptr); LLVM_FALLTHROUGH; case dwarf::DW_TAG_member: @@ -1573,8 +1576,7 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext( // created on demand. For example implicitely defined constructors // are ambiguous because of the way we identify contexts, and they // won't be generated everytime everywhere. - if (DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_artificial) - .getValueOr(0)) + if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0)) return PointerIntPair<DeclContext *, 1>(nullptr); break; } @@ -1614,12 +1616,9 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext( // namespaces, use these additional data points to make the process // safer. This is disabled for clang modules, because forward // declarations of module-defined types do not have a file and line. - ByteSize = DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_byte_size) - .getValueOr(UINT64_MAX); + ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), UINT64_MAX); if (Tag != dwarf::DW_TAG_namespace || !Name) { - if (unsigned FileNum = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_file) - .getValueOr(0)) { + if (unsigned FileNum = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) { if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( &U.getOrigUnit())) { // FIXME: dsymutil-classic compatibility. I'd rather not @@ -1632,9 +1631,7 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext( // instead of "" would allow more uniquing, but for now, do // it this way to match dsymutil-classic. if (LT->hasFileAtIndex(FileNum)) { - Line = - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_line) - .getValueOr(0); + Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0); // Cache the resolved paths, because calling realpath is expansive. StringRef ResolvedPath = U.getResolvedPath(FileNum); if (!ResolvedPath.empty()) { @@ -1782,8 +1779,7 @@ static bool analyzeContextInfo(const DWARFDie &DIE, // // We treat non-C++ modules like namespaces for this reason. if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && - DIE.getAttributeValueAsString(dwarf::DW_AT_name, - "") != CU.getClangModuleName()) { + dwarf::toString(DIE.find(dwarf::DW_AT_name), "") != CU.getClangModuleName()) { InImportedModule = true; } @@ -1811,8 +1807,7 @@ static bool analyzeContextInfo(const DWARFDie &DIE, // forward declarations. Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) || - DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_declaration) - .getValueOr(0); + dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0); // Don't prune it if there is no definition for the DIE. Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); @@ -2129,7 +2124,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE( std::tie(LowPcOffset, LowPcEndOffset) = getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit); - auto LowPc = DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc); + auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); assert(LowPc.hasValue() && "low_pc attribute is not an address."); if (!LowPc || !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) @@ -2746,14 +2741,11 @@ DIE *DwarfLinker::DIECloner::cloneDIE( // file might be start address of another function which got moved // independantly by the linker). The computation of the actual // high_pc value is done in cloneAddressAttribute(). - AttrInfo.OrigHighPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_high_pc).getValueOr(0); + AttrInfo.OrigHighPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0); // Also store the low_pc. It might get relocated in an // inline_subprogram that happens at the beginning of its // inlining function. - AttrInfo.OrigLowPc = - InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(UINT64_MAX); + AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), UINT64_MAX); } // Reset the Offset to 0 as we will be working on the local copy of @@ -2872,9 +2864,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); auto OrigUnitDie = OrigUnit.getUnitDIE(false); - uint64_t OrigLowPc = - OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc) - .getValueOr(-1ULL); + uint64_t OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL); // Ranges addresses are based on the unit's low_pc. Compute the // offset we need to apply to adapt to the new unit's low_pc. int64_t UnitPcOffset = 0; @@ -2969,7 +2959,7 @@ static void patchStmtList(DIE &Die, DIEInteger Offset) { void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf) { DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); - auto StmtList = CUDie.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list); + auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); if (!StmtList) return; @@ -3081,7 +3071,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, if (LineTable.Prologue.Version != 2 || LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT || LineTable.Prologue.OpcodeBase > 13) - reportWarning("line table paramters mismatch. Cannot emit."); + reportWarning("line table parameters mismatch. Cannot emit."); else { MCDwarfLineTableParams Params; Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; @@ -3201,10 +3191,8 @@ void DwarfLinker::DIECloner::copyAbbrev( static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { - auto DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id); - if (DwoId) - return *DwoId; - DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id); + auto DwoId = dwarf::toUnsigned(CUDie.find({dwarf::DW_AT_dwo_id, + dwarf::DW_AT_GNU_dwo_id})); if (DwoId) return *DwoId; return 0; @@ -3214,20 +3202,16 @@ bool DwarfLinker::registerModuleReference( const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, unsigned Indent) { std::string PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_dwo_name, ""); - if (PCMfile.empty()) - PCMfile = - CUDie.getAttributeValueAsString(dwarf::DW_AT_GNU_dwo_name, ""); + dwarf::toString(CUDie.find({dwarf::DW_AT_dwo_name, + dwarf::DW_AT_GNU_dwo_name}), ""); if (PCMfile.empty()) return false; // Clang module DWARF skeleton CUs abuse this for the path to the module. - std::string PCMpath = - CUDie.getAttributeValueAsString(dwarf::DW_AT_comp_dir, ""); + std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), ""); uint64_t DwoId = getDwoId(CUDie, Unit); - std::string Name = - CUDie.getAttributeValueAsString(dwarf::DW_AT_name, ""); + std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); if (Name.empty()) { reportWarning("Anonymous module skeleton CU for " + PCMfile); return true; @@ -3378,12 +3362,13 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits( for (auto &CurrentUnit : CompileUnits) { auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize); - // Clonse the InputDIE into your Unit DIE in our compile unit since it - // already has a DIE inside of it. - if (!cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */, - 11 /* Unit Header size */, 0, - CurrentUnit->getOutputUnitDIE())) - continue; + if (CurrentUnit->getInfo(0).Keep) { + // Clone the InputDIE into your Unit DIE in our compile unit since it + // already has a DIE inside of it. + CurrentUnit->createOutputDIE(); + cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */, + 11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE()); + } Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); if (Linker.Options.NoOutput) continue; |