1c33536e9SAlexander Yermolovich //===- bolt/Core/DIEBuilder.cpp -------------------------------------===// 2c33536e9SAlexander Yermolovich // 3c33536e9SAlexander Yermolovich // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c33536e9SAlexander Yermolovich // See https://llvm.org/LICENSE.txt for license information. 5c33536e9SAlexander Yermolovich // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c33536e9SAlexander Yermolovich // 7c33536e9SAlexander Yermolovich //===----------------------------------------------------------------------===// 8c33536e9SAlexander Yermolovich 987fb0ea2SRui Zhong #include "bolt/Core/DIEBuilder.h" 1087fb0ea2SRui Zhong #include "bolt/Core/BinaryContext.h" 1187fb0ea2SRui Zhong #include "bolt/Core/ParallelUtilities.h" 1287fb0ea2SRui Zhong #include "llvm/ADT/StringRef.h" 1387fb0ea2SRui Zhong #include "llvm/BinaryFormat/Dwarf.h" 1487fb0ea2SRui Zhong #include "llvm/CodeGen/DIE.h" 1587fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 1687fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFDie.h" 1787fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 1887fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 1987fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 2087fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 2187fb0ea2SRui Zhong #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 2287fb0ea2SRui Zhong #include "llvm/Support/Casting.h" 2387fb0ea2SRui Zhong #include "llvm/Support/Debug.h" 2487fb0ea2SRui Zhong #include "llvm/Support/ErrorHandling.h" 2599fad7ebSAlexander Yermolovich #include "llvm/Support/FileSystem.h" 2687fb0ea2SRui Zhong #include "llvm/Support/LEB128.h" 2787fb0ea2SRui Zhong 2887fb0ea2SRui Zhong #include <algorithm> 2987fb0ea2SRui Zhong #include <cstdint> 3087fb0ea2SRui Zhong #include <memory> 31dcfa2ab5SAlexander Yermolovich #include <mutex> 326de5fcc7SAlexander Yermolovich #include <optional> 3387fb0ea2SRui Zhong #include <unordered_map> 3487fb0ea2SRui Zhong #include <utility> 35dcfa2ab5SAlexander Yermolovich #include <vector> 3687fb0ea2SRui Zhong 3787fb0ea2SRui Zhong #undef DEBUG_TYPE 3887fb0ea2SRui Zhong #define DEBUG_TYPE "bolt" 392c784f7dSAlexander Yermolovich namespace opts { 402c784f7dSAlexander Yermolovich extern cl::opt<unsigned> Verbosity; 412c784f7dSAlexander Yermolovich } 4287fb0ea2SRui Zhong namespace llvm { 4387fb0ea2SRui Zhong namespace bolt { 4487fb0ea2SRui Zhong 4599fad7ebSAlexander Yermolovich /// Returns DWO Name to be used to update DW_AT_dwo_name/DW_AT_GNU_dwo_name 4699fad7ebSAlexander Yermolovich /// either in CU or TU unit die. Handles case where user specifies output DWO 4799fad7ebSAlexander Yermolovich /// directory, and there are duplicate names. Assumes DWO ID is unique. 4899fad7ebSAlexander Yermolovich static std::string 4999fad7ebSAlexander Yermolovich getDWOName(llvm::DWARFUnit &CU, 5099fad7ebSAlexander Yermolovich std::unordered_map<std::string, uint32_t> &NameToIndexMap, 5199fad7ebSAlexander Yermolovich std::optional<StringRef> &DwarfOutputPath) { 5299fad7ebSAlexander Yermolovich assert(CU.getDWOId() && "DWO ID not found."); 5399fad7ebSAlexander Yermolovich std::string DWOName = dwarf::toString( 5499fad7ebSAlexander Yermolovich CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), 5599fad7ebSAlexander Yermolovich ""); 5699fad7ebSAlexander Yermolovich assert(!DWOName.empty() && 5799fad7ebSAlexander Yermolovich "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exist."); 5899fad7ebSAlexander Yermolovich if (DwarfOutputPath) { 5999fad7ebSAlexander Yermolovich DWOName = std::string(sys::path::filename(DWOName)); 60b192f208SKazu Hirata uint32_t &Index = NameToIndexMap[DWOName]; 61b192f208SKazu Hirata DWOName.append(std::to_string(Index)); 62b192f208SKazu Hirata ++Index; 6399fad7ebSAlexander Yermolovich } 6499fad7ebSAlexander Yermolovich DWOName.append(".dwo"); 6599fad7ebSAlexander Yermolovich return DWOName; 6699fad7ebSAlexander Yermolovich } 6799fad7ebSAlexander Yermolovich 6899fad7ebSAlexander Yermolovich /// Adds a \p Str to .debug_str section. 6999fad7ebSAlexander Yermolovich /// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using 7099fad7ebSAlexander Yermolovich /// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets 7199fad7ebSAlexander Yermolovich /// for this contribution of \p Unit. 7299fad7ebSAlexander Yermolovich static void addStringHelper(DebugStrOffsetsWriter &StrOffstsWriter, 7399fad7ebSAlexander Yermolovich DebugStrWriter &StrWriter, DIEBuilder &DIEBldr, 7499fad7ebSAlexander Yermolovich DIE &Die, const DWARFUnit &Unit, 7599fad7ebSAlexander Yermolovich DIEValue &DIEAttrInfo, StringRef Str) { 7699fad7ebSAlexander Yermolovich uint32_t NewOffset = StrWriter.addString(Str); 7799fad7ebSAlexander Yermolovich if (Unit.getVersion() >= 5) { 7899fad7ebSAlexander Yermolovich StrOffstsWriter.updateAddressMap(DIEAttrInfo.getDIEInteger().getValue(), 799a3e66e3SSayhaan Siddiqui NewOffset, Unit); 8099fad7ebSAlexander Yermolovich return; 8199fad7ebSAlexander Yermolovich } 8299fad7ebSAlexander Yermolovich DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(), 8399fad7ebSAlexander Yermolovich DIEInteger(NewOffset)); 8499fad7ebSAlexander Yermolovich } 8599fad7ebSAlexander Yermolovich 8699fad7ebSAlexander Yermolovich std::string DIEBuilder::updateDWONameCompDir( 8799fad7ebSAlexander Yermolovich DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter, 8899fad7ebSAlexander Yermolovich DWARFUnit &SkeletonCU, std::optional<StringRef> DwarfOutputPath, 8999fad7ebSAlexander Yermolovich std::optional<StringRef> DWONameToUse) { 9099fad7ebSAlexander Yermolovich DIE &UnitDIE = *getUnitDIEbyUnit(SkeletonCU); 9199fad7ebSAlexander Yermolovich DIEValue DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_dwo_name); 9299fad7ebSAlexander Yermolovich if (!DWONameAttrInfo) 9399fad7ebSAlexander Yermolovich DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name); 9499fad7ebSAlexander Yermolovich if (!DWONameAttrInfo) 9599fad7ebSAlexander Yermolovich return ""; 9699fad7ebSAlexander Yermolovich std::string ObjectName; 9799fad7ebSAlexander Yermolovich if (DWONameToUse) 9899fad7ebSAlexander Yermolovich ObjectName = *DWONameToUse; 9999fad7ebSAlexander Yermolovich else 10099fad7ebSAlexander Yermolovich ObjectName = getDWOName(SkeletonCU, NameToIndexMap, DwarfOutputPath); 10199fad7ebSAlexander Yermolovich addStringHelper(StrOffstsWriter, StrWriter, *this, UnitDIE, SkeletonCU, 10299fad7ebSAlexander Yermolovich DWONameAttrInfo, ObjectName); 10399fad7ebSAlexander Yermolovich 10499fad7ebSAlexander Yermolovich DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir); 10599fad7ebSAlexander Yermolovich assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU."); 10699fad7ebSAlexander Yermolovich 10799fad7ebSAlexander Yermolovich if (DwarfOutputPath) { 10899fad7ebSAlexander Yermolovich if (!sys::fs::exists(*DwarfOutputPath)) 10999fad7ebSAlexander Yermolovich sys::fs::create_directory(*DwarfOutputPath); 11099fad7ebSAlexander Yermolovich addStringHelper(StrOffstsWriter, StrWriter, *this, UnitDIE, SkeletonCU, 11199fad7ebSAlexander Yermolovich CompDirAttrInfo, *DwarfOutputPath); 11299fad7ebSAlexander Yermolovich } 11399fad7ebSAlexander Yermolovich return ObjectName; 11499fad7ebSAlexander Yermolovich } 11599fad7ebSAlexander Yermolovich 11699fad7ebSAlexander Yermolovich void DIEBuilder::updateDWONameCompDirForTypes( 11799fad7ebSAlexander Yermolovich DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter, 11899fad7ebSAlexander Yermolovich DWARFUnit &Unit, std::optional<StringRef> DwarfOutputPath, 11999fad7ebSAlexander Yermolovich const StringRef DWOName) { 12099fad7ebSAlexander Yermolovich for (DWARFUnit *DU : getState().DWARF5TUVector) 12199fad7ebSAlexander Yermolovich updateDWONameCompDir(StrOffstsWriter, StrWriter, *DU, DwarfOutputPath, 12299fad7ebSAlexander Yermolovich DWOName); 12399fad7ebSAlexander Yermolovich if (StrOffstsWriter.isStrOffsetsSectionModified()) 12499fad7ebSAlexander Yermolovich StrOffstsWriter.finalizeSection(Unit, *this); 12599fad7ebSAlexander Yermolovich } 12699fad7ebSAlexander Yermolovich 127c33536e9SAlexander Yermolovich void DIEBuilder::updateReferences() { 128dcfa2ab5SAlexander Yermolovich for (auto &[SrcDIEInfo, ReferenceInfo] : getState().AddrReferences) { 12987fb0ea2SRui Zhong DIEInfo *DstDIEInfo = ReferenceInfo.Dst; 130c33536e9SAlexander Yermolovich DWARFUnitInfo &DstUnitInfo = getUnitInfo(DstDIEInfo->UnitId); 13187fb0ea2SRui Zhong dwarf::Attribute Attr = ReferenceInfo.AttrSpec.Attr; 13287fb0ea2SRui Zhong dwarf::Form Form = ReferenceInfo.AttrSpec.Form; 13387fb0ea2SRui Zhong 134c33536e9SAlexander Yermolovich const uint64_t NewAddr = 135c33536e9SAlexander Yermolovich DstDIEInfo->Die->getOffset() + DstUnitInfo.UnitOffset; 136dcfa2ab5SAlexander Yermolovich SrcDIEInfo->Die->replaceValue(getState().DIEAlloc, Attr, Form, 137dcfa2ab5SAlexander Yermolovich DIEInteger(NewAddr)); 13887fb0ea2SRui Zhong } 13987fb0ea2SRui Zhong 140c33536e9SAlexander Yermolovich // Handling referenes in location expressions. 141dcfa2ab5SAlexander Yermolovich for (LocWithReference &LocExpr : getState().LocWithReferencesToProcess) { 142c33536e9SAlexander Yermolovich SmallVector<uint8_t, 32> Buffer; 143c33536e9SAlexander Yermolovich DataExtractor Data(StringRef((const char *)LocExpr.BlockData.data(), 144c33536e9SAlexander Yermolovich LocExpr.BlockData.size()), 145c33536e9SAlexander Yermolovich LocExpr.U.isLittleEndian(), 146c33536e9SAlexander Yermolovich LocExpr.U.getAddressByteSize()); 147c33536e9SAlexander Yermolovich DWARFExpression Expr(Data, LocExpr.U.getAddressByteSize(), 148c33536e9SAlexander Yermolovich LocExpr.U.getFormParams().Format); 149c33536e9SAlexander Yermolovich cloneExpression(Data, Expr, LocExpr.U, Buffer, CloneExpressionStage::PATCH); 150c33536e9SAlexander Yermolovich 151c33536e9SAlexander Yermolovich DIEValueList *AttrVal; 152c33536e9SAlexander Yermolovich if (LocExpr.Form == dwarf::DW_FORM_exprloc) { 153dcfa2ab5SAlexander Yermolovich DIELoc *DL = new (getState().DIEAlloc) DIELoc; 154c33536e9SAlexander Yermolovich DL->setSize(Buffer.size()); 155c33536e9SAlexander Yermolovich AttrVal = static_cast<DIEValueList *>(DL); 156c33536e9SAlexander Yermolovich } else { 157dcfa2ab5SAlexander Yermolovich DIEBlock *DBL = new (getState().DIEAlloc) DIEBlock; 158c33536e9SAlexander Yermolovich DBL->setSize(Buffer.size()); 159c33536e9SAlexander Yermolovich AttrVal = static_cast<DIEValueList *>(DBL); 160c33536e9SAlexander Yermolovich } 161c33536e9SAlexander Yermolovich for (auto Byte : Buffer) 162dcfa2ab5SAlexander Yermolovich AttrVal->addValue(getState().DIEAlloc, static_cast<dwarf::Attribute>(0), 163c33536e9SAlexander Yermolovich dwarf::DW_FORM_data1, DIEInteger(Byte)); 164c33536e9SAlexander Yermolovich 165c33536e9SAlexander Yermolovich DIEValue Value; 166c33536e9SAlexander Yermolovich if (LocExpr.Form == dwarf::DW_FORM_exprloc) 167c33536e9SAlexander Yermolovich Value = 168c33536e9SAlexander Yermolovich DIEValue(dwarf::Attribute(LocExpr.Attr), dwarf::Form(LocExpr.Form), 169c33536e9SAlexander Yermolovich static_cast<DIELoc *>(AttrVal)); 170c33536e9SAlexander Yermolovich else 171c33536e9SAlexander Yermolovich Value = 172c33536e9SAlexander Yermolovich DIEValue(dwarf::Attribute(LocExpr.Attr), dwarf::Form(LocExpr.Form), 173c33536e9SAlexander Yermolovich static_cast<DIEBlock *>(AttrVal)); 174c33536e9SAlexander Yermolovich 175dcfa2ab5SAlexander Yermolovich LocExpr.Die.replaceValue(getState().DIEAlloc, LocExpr.Attr, LocExpr.Form, 176dcfa2ab5SAlexander Yermolovich Value); 17787fb0ea2SRui Zhong } 17887fb0ea2SRui Zhong 17987fb0ea2SRui Zhong return; 18087fb0ea2SRui Zhong } 18187fb0ea2SRui Zhong 182c33536e9SAlexander Yermolovich uint32_t DIEBuilder::allocDIE(const DWARFUnit &DU, const DWARFDie &DDie, 183c33536e9SAlexander Yermolovich BumpPtrAllocator &Alloc, const uint32_t UId) { 184c33536e9SAlexander Yermolovich DWARFUnitInfo &DWARFUnitInfo = getUnitInfo(UId); 185c33536e9SAlexander Yermolovich const uint64_t DDieOffset = DDie.getOffset(); 186c33536e9SAlexander Yermolovich if (DWARFUnitInfo.DIEIDMap.count(DDieOffset)) 187c33536e9SAlexander Yermolovich return DWARFUnitInfo.DIEIDMap[DDieOffset]; 18887fb0ea2SRui Zhong 18987fb0ea2SRui Zhong DIE *Die = DIE::get(Alloc, dwarf::Tag(DDie.getTag())); 1902c784f7dSAlexander Yermolovich // This handles the case where there is a DIE ref which points to 1912c784f7dSAlexander Yermolovich // invalid DIE. This prevents assert when IR is written out. 1922c784f7dSAlexander Yermolovich // Also it makes debugging easier. 1932c784f7dSAlexander Yermolovich // DIE dump is not very useful. 1942c784f7dSAlexander Yermolovich // It's nice to know original offset from which this DIE was constructed. 1952c784f7dSAlexander Yermolovich Die->setOffset(DDie.getOffset()); 1962c784f7dSAlexander Yermolovich if (opts::Verbosity >= 1) 1972c784f7dSAlexander Yermolovich getState().DWARFDieAddressesParsed.insert(DDie.getOffset()); 198c33536e9SAlexander Yermolovich const uint32_t DId = DWARFUnitInfo.DieInfoVector.size(); 199c33536e9SAlexander Yermolovich DWARFUnitInfo.DIEIDMap[DDieOffset] = DId; 200c33536e9SAlexander Yermolovich DWARFUnitInfo.DieInfoVector.emplace_back( 201c33536e9SAlexander Yermolovich std::make_unique<DIEInfo>(DIEInfo{Die, DId, UId})); 20287fb0ea2SRui Zhong return DId; 20387fb0ea2SRui Zhong } 20487fb0ea2SRui Zhong 205dcfa2ab5SAlexander Yermolovich void DIEBuilder::constructFromUnit(DWARFUnit &DU) { 20687fb0ea2SRui Zhong std::optional<uint32_t> UnitId = getUnitId(DU); 207c33536e9SAlexander Yermolovich if (!UnitId) { 20852cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: " 209c33536e9SAlexander Yermolovich << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n"; 21087fb0ea2SRui Zhong return; 21187fb0ea2SRui Zhong } 21287fb0ea2SRui Zhong 21387fb0ea2SRui Zhong const uint32_t UnitHeaderSize = DU.getHeaderSize(); 21487fb0ea2SRui Zhong uint64_t DIEOffset = DU.getOffset() + UnitHeaderSize; 21587fb0ea2SRui Zhong uint64_t NextCUOffset = DU.getNextUnitOffset(); 21687fb0ea2SRui Zhong DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor(); 21787fb0ea2SRui Zhong DWARFDebugInfoEntry DIEEntry; 21887fb0ea2SRui Zhong std::vector<DIE *> CurParentDIEStack; 21987fb0ea2SRui Zhong std::vector<uint32_t> Parents; 22087fb0ea2SRui Zhong uint32_t TUTypeOffset = 0; 22187fb0ea2SRui Zhong 222c33536e9SAlexander Yermolovich if (DWARFTypeUnit *TU = dyn_cast_or_null<DWARFTypeUnit>(&DU)) 22387fb0ea2SRui Zhong TUTypeOffset = TU->getTypeOffset(); 22487fb0ea2SRui Zhong 22587fb0ea2SRui Zhong assert(DebugInfoData.isValidOffset(NextCUOffset - 1)); 22687fb0ea2SRui Zhong Parents.push_back(UINT32_MAX); 22787fb0ea2SRui Zhong do { 228c33536e9SAlexander Yermolovich const bool IsTypeDIE = (TUTypeOffset == DIEOffset - DU.getOffset()); 22987fb0ea2SRui Zhong if (!DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 23087fb0ea2SRui Zhong Parents.back())) 23187fb0ea2SRui Zhong break; 23287fb0ea2SRui Zhong 23387fb0ea2SRui Zhong if (const DWARFAbbreviationDeclaration *AbbrDecl = 23487fb0ea2SRui Zhong DIEEntry.getAbbreviationDeclarationPtr()) { 23587fb0ea2SRui Zhong DWARFDie DDie(&DU, &DIEEntry); 23687fb0ea2SRui Zhong 237dcfa2ab5SAlexander Yermolovich DIE *CurDIE = constructDIEFast(DDie, DU, *UnitId); 238c33536e9SAlexander Yermolovich DWARFUnitInfo &UI = getUnitInfo(*UnitId); 239c33536e9SAlexander Yermolovich // Can't rely on first element in DieVector due to cross CU forward 240c33536e9SAlexander Yermolovich // references. 241c33536e9SAlexander Yermolovich if (!UI.UnitDie) 242c33536e9SAlexander Yermolovich UI.UnitDie = CurDIE; 243c33536e9SAlexander Yermolovich if (IsTypeDIE) 244dcfa2ab5SAlexander Yermolovich getState().TypeDIEMap[&DU] = CurDIE; 24587fb0ea2SRui Zhong 24687fb0ea2SRui Zhong if (!CurParentDIEStack.empty()) 24787fb0ea2SRui Zhong CurParentDIEStack.back()->addChild(CurDIE); 24887fb0ea2SRui Zhong 249c33536e9SAlexander Yermolovich if (AbbrDecl->hasChildren()) 25087fb0ea2SRui Zhong CurParentDIEStack.push_back(CurDIE); 25187fb0ea2SRui Zhong } else { 25287fb0ea2SRui Zhong // NULL DIE: finishes current children scope. 25387fb0ea2SRui Zhong CurParentDIEStack.pop_back(); 25487fb0ea2SRui Zhong } 25587fb0ea2SRui Zhong } while (CurParentDIEStack.size() > 0); 25687fb0ea2SRui Zhong 257dcfa2ab5SAlexander Yermolovich getState().CloneUnitCtxMap[*UnitId].IsConstructed = true; 25887fb0ea2SRui Zhong } 25987fb0ea2SRui Zhong 26052cf0711SAmir Ayupov DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, 2616de5fcc7SAlexander Yermolovich DWARF5AcceleratorTable &DebugNamesTable, 262640e781dSAlexander Yermolovich DWARFUnit *SkeletonCU) 2636de5fcc7SAlexander Yermolovich : BC(BC), DwarfContext(DwarfContext), SkeletonCU(SkeletonCU), 2646de5fcc7SAlexander Yermolovich DebugNamesTable(DebugNamesTable) {} 265dcfa2ab5SAlexander Yermolovich 266dcfa2ab5SAlexander Yermolovich static unsigned int getCUNum(DWARFContext *DwarfContext, bool IsDWO) { 267dcfa2ab5SAlexander Yermolovich unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() 268dcfa2ab5SAlexander Yermolovich : DwarfContext->getNumCompileUnits(); 269dcfa2ab5SAlexander Yermolovich CUNum += IsDWO ? DwarfContext->getNumDWOTypeUnits() 270dcfa2ab5SAlexander Yermolovich : DwarfContext->getNumTypeUnits(); 271dcfa2ab5SAlexander Yermolovich return CUNum; 272dcfa2ab5SAlexander Yermolovich } 273dcfa2ab5SAlexander Yermolovich 274bf2b035eSAlexander Yermolovich void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter *StrOffsetWriter, 275bf2b035eSAlexander Yermolovich const bool Init) { 276dcfa2ab5SAlexander Yermolovich if (Init) 277dcfa2ab5SAlexander Yermolovich BuilderState.reset(new State()); 278dcfa2ab5SAlexander Yermolovich 27987fb0ea2SRui Zhong const DWARFUnitIndex &TUIndex = DwarfContext->getTUIndex(); 28087fb0ea2SRui Zhong if (!TUIndex.getRows().empty()) { 28187fb0ea2SRui Zhong for (auto &Row : TUIndex.getRows()) { 28287fb0ea2SRui Zhong uint64_t Signature = Row.getSignature(); 28387fb0ea2SRui Zhong // manually populate TypeUnit to UnitVector 2846803062eSKazu Hirata DwarfContext->getTypeUnitForHash(Signature, true); 28587fb0ea2SRui Zhong } 28687fb0ea2SRui Zhong } 287640e781dSAlexander Yermolovich const unsigned int CUNum = getCUNum(DwarfContext, isDWO()); 288b47b3beeSAlexander Yermolovich getState().CloneUnitCtxMap.resize(CUNum); 289b47b3beeSAlexander Yermolovich DWARFContext::unit_iterator_range CU4TURanges = 290640e781dSAlexander Yermolovich isDWO() ? DwarfContext->dwo_types_section_units() 291b47b3beeSAlexander Yermolovich : DwarfContext->types_section_units(); 29287fb0ea2SRui Zhong 293dcfa2ab5SAlexander Yermolovich getState().Type = ProcessingType::DWARF4TUs; 294c33536e9SAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) 295dcfa2ab5SAlexander Yermolovich registerUnit(*DU.get(), false); 296dcfa2ab5SAlexander Yermolovich 297dcfa2ab5SAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) 298dcfa2ab5SAlexander Yermolovich constructFromUnit(*DU.get()); 29987fb0ea2SRui Zhong 300c33536e9SAlexander Yermolovich DWARFContext::unit_iterator_range CURanges = 301640e781dSAlexander Yermolovich isDWO() ? DwarfContext->dwo_info_section_units() 302c33536e9SAlexander Yermolovich : DwarfContext->info_section_units(); 303c33536e9SAlexander Yermolovich 304c33536e9SAlexander Yermolovich // This handles DWARF4 CUs and DWARF5 CU/TUs. 305c33536e9SAlexander Yermolovich // Creating a vector so that for reference handling only DWARF5 CU/TUs are 306c33536e9SAlexander Yermolovich // used, and not DWARF4 TUs. 307dcfa2ab5SAlexander Yermolovich getState().Type = ProcessingType::DWARF5TUs; 308c33536e9SAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &DU : CURanges) { 309dcfa2ab5SAlexander Yermolovich if (!DU->isTypeUnit()) 310dcfa2ab5SAlexander Yermolovich continue; 311dcfa2ab5SAlexander Yermolovich registerUnit(*DU.get(), false); 31287fb0ea2SRui Zhong } 31387fb0ea2SRui Zhong 314bf2b035eSAlexander Yermolovich for (DWARFUnit *DU : getState().DWARF5TUVector) { 315dcfa2ab5SAlexander Yermolovich constructFromUnit(*DU); 316bf2b035eSAlexander Yermolovich if (StrOffsetWriter) 317bf2b035eSAlexander Yermolovich StrOffsetWriter->finalizeSection(*DU, *this); 318bf2b035eSAlexander Yermolovich } 319c33536e9SAlexander Yermolovich } 320c33536e9SAlexander Yermolovich 321dcfa2ab5SAlexander Yermolovich void DIEBuilder::buildCompileUnits(const bool Init) { 322dcfa2ab5SAlexander Yermolovich if (Init) 323dcfa2ab5SAlexander Yermolovich BuilderState.reset(new State()); 324dcfa2ab5SAlexander Yermolovich 325640e781dSAlexander Yermolovich unsigned int CUNum = getCUNum(DwarfContext, isDWO()); 326dcfa2ab5SAlexander Yermolovich getState().CloneUnitCtxMap.resize(CUNum); 327dcfa2ab5SAlexander Yermolovich DWARFContext::unit_iterator_range CURanges = 328640e781dSAlexander Yermolovich isDWO() ? DwarfContext->dwo_info_section_units() 329dcfa2ab5SAlexander Yermolovich : DwarfContext->info_section_units(); 330dcfa2ab5SAlexander Yermolovich 331dcfa2ab5SAlexander Yermolovich // This handles DWARF4 CUs and DWARF5 CU/TUs. 332dcfa2ab5SAlexander Yermolovich // Creating a vector so that for reference handling only DWARF5 CU/TUs are 333dcfa2ab5SAlexander Yermolovich // used, and not DWARF4 TUs.getState().DUList 334dcfa2ab5SAlexander Yermolovich getState().Type = ProcessingType::CUs; 335dcfa2ab5SAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &DU : CURanges) { 336dcfa2ab5SAlexander Yermolovich if (DU->isTypeUnit()) 337dcfa2ab5SAlexander Yermolovich continue; 338dcfa2ab5SAlexander Yermolovich registerUnit(*DU.get(), false); 339dcfa2ab5SAlexander Yermolovich } 340dcfa2ab5SAlexander Yermolovich 341dcfa2ab5SAlexander Yermolovich // Using DULIst since it can be modified by cross CU refrence resolution. 342dcfa2ab5SAlexander Yermolovich for (DWARFUnit *DU : getState().DUList) { 343dcfa2ab5SAlexander Yermolovich if (DU->isTypeUnit()) 344dcfa2ab5SAlexander Yermolovich continue; 345dcfa2ab5SAlexander Yermolovich constructFromUnit(*DU); 346dcfa2ab5SAlexander Yermolovich } 347dcfa2ab5SAlexander Yermolovich } 348dcfa2ab5SAlexander Yermolovich void DIEBuilder::buildCompileUnits(const std::vector<DWARFUnit *> &CUs) { 349dcfa2ab5SAlexander Yermolovich BuilderState.reset(new State()); 350ad4cead6SAlexander Yermolovich // Allocating enough for current batch being processed. 351ad4cead6SAlexander Yermolovich // In real use cases we either processing a batch of CUs with no cross 352ad4cead6SAlexander Yermolovich // references, or if they do have them it is due to LTO. With clang they will 353ad4cead6SAlexander Yermolovich // share the same abbrev table. In either case this vector will not grow. 354ad4cead6SAlexander Yermolovich getState().CloneUnitCtxMap.resize(CUs.size()); 355dcfa2ab5SAlexander Yermolovich getState().Type = ProcessingType::CUs; 356dcfa2ab5SAlexander Yermolovich for (DWARFUnit *CU : CUs) 357dcfa2ab5SAlexander Yermolovich registerUnit(*CU, false); 358dcfa2ab5SAlexander Yermolovich 359dcfa2ab5SAlexander Yermolovich for (DWARFUnit *DU : getState().DUList) 360dcfa2ab5SAlexander Yermolovich constructFromUnit(*DU); 361dcfa2ab5SAlexander Yermolovich } 362dcfa2ab5SAlexander Yermolovich 363b47b3beeSAlexander Yermolovich void DIEBuilder::buildDWOUnit(DWARFUnit &U) { 364dcfa2ab5SAlexander Yermolovich BuilderState.release(); 365dcfa2ab5SAlexander Yermolovich BuilderState = std::make_unique<State>(); 366bf2b035eSAlexander Yermolovich buildTypeUnits(nullptr, false); 367b47b3beeSAlexander Yermolovich getState().Type = ProcessingType::CUs; 368b47b3beeSAlexander Yermolovich registerUnit(U, false); 369b47b3beeSAlexander Yermolovich constructFromUnit(U); 370dcfa2ab5SAlexander Yermolovich } 371dcfa2ab5SAlexander Yermolovich 372dcfa2ab5SAlexander Yermolovich DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U, 373dcfa2ab5SAlexander Yermolovich uint32_t UnitId) { 37487fb0ea2SRui Zhong 37587fb0ea2SRui Zhong std::optional<uint32_t> Idx = getAllocDIEId(U, DDie); 376c33536e9SAlexander Yermolovich if (Idx) { 377c33536e9SAlexander Yermolovich DWARFUnitInfo &DWARFUnitInfo = getUnitInfo(UnitId); 37887fb0ea2SRui Zhong DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); 379c33536e9SAlexander Yermolovich if (DWARFUnitInfo.IsConstructed && DieInfo.Die) 38087fb0ea2SRui Zhong return DieInfo.Die; 38187fb0ea2SRui Zhong } else { 382dcfa2ab5SAlexander Yermolovich Idx = allocDIE(U, DDie, getState().DIEAlloc, UnitId); 38387fb0ea2SRui Zhong } 38487fb0ea2SRui Zhong 38587fb0ea2SRui Zhong DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); 38687fb0ea2SRui Zhong 38787fb0ea2SRui Zhong uint64_t Offset = DDie.getOffset(); 38887fb0ea2SRui Zhong uint64_t NextOffset = Offset; 38987fb0ea2SRui Zhong DWARFDataExtractor Data = U.getDebugInfoExtractor(); 39087fb0ea2SRui Zhong DWARFDebugInfoEntry DDIEntry; 39187fb0ea2SRui Zhong 392c33536e9SAlexander Yermolovich if (DDIEntry.extractFast(U, &NextOffset, Data, U.getNextUnitOffset(), 0)) 39387fb0ea2SRui Zhong assert(NextOffset - U.getOffset() <= Data.getData().size() && 39487fb0ea2SRui Zhong "NextOffset OOB"); 39587fb0ea2SRui Zhong 39687fb0ea2SRui Zhong SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); 39787fb0ea2SRui Zhong Data = 39887fb0ea2SRui Zhong DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); 39987fb0ea2SRui Zhong 40087fb0ea2SRui Zhong const DWARFAbbreviationDeclaration *Abbrev = 40187fb0ea2SRui Zhong DDie.getAbbreviationDeclarationPtr(); 402c33536e9SAlexander Yermolovich uint64_t AttrOffset = getULEB128Size(Abbrev->getCode()); 40387fb0ea2SRui Zhong 404c33536e9SAlexander Yermolovich using AttrSpec = DWARFAbbreviationDeclaration::AttributeSpec; 405c33536e9SAlexander Yermolovich for (const AttrSpec &AttrSpec : Abbrev->attributes()) { 40687fb0ea2SRui Zhong DWARFFormValue Val(AttrSpec.Form); 407c33536e9SAlexander Yermolovich Val.extractValue(Data, &AttrOffset, U.getFormParams(), &U); 408dcfa2ab5SAlexander Yermolovich cloneAttribute(*DieInfo.Die, DDie, U, Val, AttrSpec); 40987fb0ea2SRui Zhong } 410c33536e9SAlexander Yermolovich return DieInfo.Die; 41187fb0ea2SRui Zhong } 41287fb0ea2SRui Zhong 413dcfa2ab5SAlexander Yermolovich static DWARFUnit * 414dcfa2ab5SAlexander Yermolovich getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx, 415dcfa2ab5SAlexander Yermolovich const uint64_t Offset, 416dcfa2ab5SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec) { 417dcfa2ab5SAlexander Yermolovich auto findUnit = [&](std::vector<DWARFUnit *> &Units) -> DWARFUnit * { 418dcfa2ab5SAlexander Yermolovich auto CUIter = llvm::upper_bound(Units, Offset, 419dcfa2ab5SAlexander Yermolovich [](uint64_t LHS, const DWARFUnit *RHS) { 42087fb0ea2SRui Zhong return LHS < RHS->getNextUnitOffset(); 42187fb0ea2SRui Zhong }); 422dcfa2ab5SAlexander Yermolovich static std::vector<DWARFUnit *> CUOffsets; 423dcfa2ab5SAlexander Yermolovich static std::once_flag InitVectorFlag; 424dcfa2ab5SAlexander Yermolovich auto initCUVector = [&]() { 425dcfa2ab5SAlexander Yermolovich CUOffsets.reserve(DWCtx.getNumCompileUnits()); 426dcfa2ab5SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : DWCtx.compile_units()) 427dcfa2ab5SAlexander Yermolovich CUOffsets.emplace_back(CU.get()); 428dcfa2ab5SAlexander Yermolovich }; 429dcfa2ab5SAlexander Yermolovich DWARFUnit *CU = CUIter != Units.end() ? *CUIter : nullptr; 430dcfa2ab5SAlexander Yermolovich // Above algorithm breaks when there is only one CU, and reference is 431dcfa2ab5SAlexander Yermolovich // outside of it. Fall through slower path, that searches all the CUs. 432dcfa2ab5SAlexander Yermolovich // For example when src and destination of cross CU references have 433dcfa2ab5SAlexander Yermolovich // different abbrev section. 434dcfa2ab5SAlexander Yermolovich if (!CU || 435dcfa2ab5SAlexander Yermolovich (CU && AttrSpec.Form == dwarf::DW_FORM_ref_addr && 436dcfa2ab5SAlexander Yermolovich !(CU->getOffset() < Offset && CU->getNextUnitOffset() > Offset))) { 437dcfa2ab5SAlexander Yermolovich // This is a work around for XCode clang. There is a build error when we 438dcfa2ab5SAlexander Yermolovich // pass DWCtx.compile_units() to llvm::upper_bound 439dcfa2ab5SAlexander Yermolovich std::call_once(InitVectorFlag, initCUVector); 440dcfa2ab5SAlexander Yermolovich auto CUIter = std::upper_bound(CUOffsets.begin(), CUOffsets.end(), Offset, 441dcfa2ab5SAlexander Yermolovich [](uint64_t LHS, const DWARFUnit *RHS) { 442dcfa2ab5SAlexander Yermolovich return LHS < RHS->getNextUnitOffset(); 443dcfa2ab5SAlexander Yermolovich }); 444dcfa2ab5SAlexander Yermolovich CU = CUIter != CUOffsets.end() ? (*CUIter) : nullptr; 445dcfa2ab5SAlexander Yermolovich } 446dcfa2ab5SAlexander Yermolovich return CU; 447dcfa2ab5SAlexander Yermolovich }; 448dcfa2ab5SAlexander Yermolovich 449dcfa2ab5SAlexander Yermolovich switch (Builder.getCurrentProcessingState()) { 450dcfa2ab5SAlexander Yermolovich case DIEBuilder::ProcessingType::DWARF4TUs: 451dcfa2ab5SAlexander Yermolovich return findUnit(Builder.getDWARF4TUVector()); 452dcfa2ab5SAlexander Yermolovich case DIEBuilder::ProcessingType::DWARF5TUs: 453dcfa2ab5SAlexander Yermolovich return findUnit(Builder.getDWARF5TUVector()); 454dcfa2ab5SAlexander Yermolovich case DIEBuilder::ProcessingType::CUs: 455dcfa2ab5SAlexander Yermolovich return findUnit(Builder.getDWARFCUVector()); 456dcfa2ab5SAlexander Yermolovich }; 457dcfa2ab5SAlexander Yermolovich 458dcfa2ab5SAlexander Yermolovich return nullptr; 45987fb0ea2SRui Zhong } 46087fb0ea2SRui Zhong 461910012e7SSayhaan Siddiqui uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die, 462910012e7SSayhaan Siddiqui uint32_t &CurOffset) { 4632c784f7dSAlexander Yermolovich getState().DWARFDieAddressesParsed.erase(Die.getOffset()); 46487fb0ea2SRui Zhong uint32_t CurSize = 0; 46587fb0ea2SRui Zhong Die.setOffset(CurOffset); 466a4610c71SAlexander Yermolovich // It is possible that an indexed debugging information entry has a parent 467a4610c71SAlexander Yermolovich // that is not indexed (for example, if its parent does not have a name 468a4610c71SAlexander Yermolovich // attribute). In such a case, a parent attribute may point to a nameless 469a4610c71SAlexander Yermolovich // index entry (that is, one that cannot be reached from any entry in the name 470a4610c71SAlexander Yermolovich // table), or it may point to the nearest ancestor that does have an index 471a4610c71SAlexander Yermolovich // entry. 47261589b85SAlexander Yermolovich // Skipping entry is not very useful for LLDB. This follows clang where 47361589b85SAlexander Yermolovich // children of forward declaration won't have DW_IDX_parent. 47461589b85SAlexander Yermolovich // https://github.com/llvm/llvm-project/pull/91808 47561589b85SAlexander Yermolovich 47661589b85SAlexander Yermolovich // If Parent is nullopt and NumberParentsInChain is not zero, then forward 47761589b85SAlexander Yermolovich // declaration was encountered in this DF traversal. Propagating nullopt for 47861589b85SAlexander Yermolovich // Parent to children. 479c33536e9SAlexander Yermolovich for (DIEValue &Val : Die.values()) 48087fb0ea2SRui Zhong CurSize += Val.sizeOf(CU.getFormParams()); 48187fb0ea2SRui Zhong CurSize += getULEB128Size(Die.getAbbrevNumber()); 48287fb0ea2SRui Zhong CurOffset += CurSize; 48387fb0ea2SRui Zhong 48487fb0ea2SRui Zhong for (DIE &Child : Die.children()) { 485910012e7SSayhaan Siddiqui uint32_t ChildSize = finalizeDIEs(CU, Child, CurOffset); 48687fb0ea2SRui Zhong CurSize += ChildSize; 48787fb0ea2SRui Zhong } 48887fb0ea2SRui Zhong // for children end mark. 48987fb0ea2SRui Zhong if (Die.hasChildren()) { 49087fb0ea2SRui Zhong CurSize += sizeof(uint8_t); 49187fb0ea2SRui Zhong CurOffset += sizeof(uint8_t); 49287fb0ea2SRui Zhong } 49387fb0ea2SRui Zhong 49487fb0ea2SRui Zhong Die.setSize(CurSize); 49587fb0ea2SRui Zhong return CurSize; 49687fb0ea2SRui Zhong } 49787fb0ea2SRui Zhong 49887fb0ea2SRui Zhong void DIEBuilder::finish() { 4996de5fcc7SAlexander Yermolovich auto finalizeCU = [&](DWARFUnit &CU, uint64_t &UnitStartOffset) -> void { 500c33536e9SAlexander Yermolovich DIE *UnitDIE = getUnitDIEbyUnit(CU); 501c33536e9SAlexander Yermolovich uint32_t HeaderSize = CU.getHeaderSize(); 50287fb0ea2SRui Zhong uint32_t CurOffset = HeaderSize; 503a4610c71SAlexander Yermolovich std::vector<std::optional<BOLTDWARF5AccelTableData *>> Parents; 504a4610c71SAlexander Yermolovich Parents.push_back(std::nullopt); 505910012e7SSayhaan Siddiqui finalizeDIEs(CU, *UnitDIE, CurOffset); 50687fb0ea2SRui Zhong 507c33536e9SAlexander Yermolovich DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); 50887fb0ea2SRui Zhong CurUnitInfo.UnitOffset = UnitStartOffset; 509c33536e9SAlexander Yermolovich CurUnitInfo.UnitLength = HeaderSize + UnitDIE->getSize(); 510c33536e9SAlexander Yermolovich UnitStartOffset += CurUnitInfo.UnitLength; 511c33536e9SAlexander Yermolovich }; 512c33536e9SAlexander Yermolovich // Computing offsets for .debug_types section. 513c33536e9SAlexander Yermolovich // It's processed first when CU is registered so will be at the begginnig of 514c33536e9SAlexander Yermolovich // the vector. 515dcfa2ab5SAlexander Yermolovich uint64_t TypeUnitStartOffset = 0; 5166de5fcc7SAlexander Yermolovich for (DWARFUnit *CU : getState().DUList) { 517dcfa2ab5SAlexander Yermolovich // We process DWARF$ types first. 518dcfa2ab5SAlexander Yermolovich if (!(CU->getVersion() < 5 && CU->isTypeUnit())) 519c33536e9SAlexander Yermolovich break; 5206de5fcc7SAlexander Yermolovich finalizeCU(*CU, TypeUnitStartOffset); 521c33536e9SAlexander Yermolovich } 522c33536e9SAlexander Yermolovich 5236de5fcc7SAlexander Yermolovich for (DWARFUnit *CU : getState().DUList) { 524dcfa2ab5SAlexander Yermolovich // Skipping DWARF4 types. 525dcfa2ab5SAlexander Yermolovich if (CU->getVersion() < 5 && CU->isTypeUnit()) 526dcfa2ab5SAlexander Yermolovich continue; 5276de5fcc7SAlexander Yermolovich finalizeCU(*CU, UnitSize); 528dcfa2ab5SAlexander Yermolovich } 5292c784f7dSAlexander Yermolovich if (opts::Verbosity >= 1) { 5302c784f7dSAlexander Yermolovich if (!getState().DWARFDieAddressesParsed.empty()) 5312c784f7dSAlexander Yermolovich dbgs() << "Referenced DIE offsets not in .debug_info\n"; 5322c784f7dSAlexander Yermolovich for (const uint64_t Address : getState().DWARFDieAddressesParsed) { 5332c784f7dSAlexander Yermolovich dbgs() << Twine::utohexstr(Address) << "\n"; 5342c784f7dSAlexander Yermolovich } 5352c784f7dSAlexander Yermolovich } 536910012e7SSayhaan Siddiqui } 537910012e7SSayhaan Siddiqui 538910012e7SSayhaan Siddiqui void DIEBuilder::populateDebugNamesTable( 539910012e7SSayhaan Siddiqui DWARFUnit &CU, const DIE &Die, 540910012e7SSayhaan Siddiqui std::optional<BOLTDWARF5AccelTableData *> Parent, 541910012e7SSayhaan Siddiqui uint32_t NumberParentsInChain) { 542910012e7SSayhaan Siddiqui std::optional<BOLTDWARF5AccelTableData *> NameEntry = 543910012e7SSayhaan Siddiqui DebugNamesTable.addAccelTableEntry( 544910012e7SSayhaan Siddiqui CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt, 545910012e7SSayhaan Siddiqui NumberParentsInChain, Parent); 546910012e7SSayhaan Siddiqui if (!Parent && NumberParentsInChain) 547910012e7SSayhaan Siddiqui NameEntry = std::nullopt; 548910012e7SSayhaan Siddiqui if (NameEntry) 549910012e7SSayhaan Siddiqui ++NumberParentsInChain; 550910012e7SSayhaan Siddiqui 551910012e7SSayhaan Siddiqui for (const DIE &Child : Die.children()) 552910012e7SSayhaan Siddiqui populateDebugNamesTable(CU, Child, NameEntry, NumberParentsInChain); 553910012e7SSayhaan Siddiqui } 554910012e7SSayhaan Siddiqui 555910012e7SSayhaan Siddiqui void DIEBuilder::updateDebugNamesTable() { 556910012e7SSayhaan Siddiqui auto finalizeDebugNamesTableForCU = [&](DWARFUnit &CU, 557910012e7SSayhaan Siddiqui uint64_t &UnitStartOffset) -> void { 558910012e7SSayhaan Siddiqui DIE *UnitDIE = getUnitDIEbyUnit(CU); 559910012e7SSayhaan Siddiqui DebugNamesTable.setCurrentUnit(CU, UnitStartOffset); 560910012e7SSayhaan Siddiqui populateDebugNamesTable(CU, *UnitDIE, std::nullopt, 0); 561910012e7SSayhaan Siddiqui 562910012e7SSayhaan Siddiqui DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); 563910012e7SSayhaan Siddiqui UnitStartOffset += CurUnitInfo.UnitLength; 564910012e7SSayhaan Siddiqui }; 565910012e7SSayhaan Siddiqui 566910012e7SSayhaan Siddiqui uint64_t TypeUnitStartOffset = 0; 567910012e7SSayhaan Siddiqui for (DWARFUnit *CU : getState().DUList) { 568910012e7SSayhaan Siddiqui if (!(CU->getVersion() < 5 && CU->isTypeUnit())) 569910012e7SSayhaan Siddiqui break; 570910012e7SSayhaan Siddiqui finalizeDebugNamesTableForCU(*CU, TypeUnitStartOffset); 571910012e7SSayhaan Siddiqui } 572910012e7SSayhaan Siddiqui 573910012e7SSayhaan Siddiqui for (DWARFUnit *CU : getState().DUList) { 574910012e7SSayhaan Siddiqui if (CU->getVersion() < 5 && CU->isTypeUnit()) 575910012e7SSayhaan Siddiqui continue; 576910012e7SSayhaan Siddiqui finalizeDebugNamesTableForCU(*CU, DebugNamesUnitSize); 577910012e7SSayhaan Siddiqui } 578c33536e9SAlexander Yermolovich updateReferences(); 57987fb0ea2SRui Zhong } 58087fb0ea2SRui Zhong 581dcfa2ab5SAlexander Yermolovich DWARFDie DIEBuilder::resolveDIEReference( 582dcfa2ab5SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 583dcfa2ab5SAlexander Yermolovich const uint64_t RefOffset, DWARFUnit *&RefCU, 584dcfa2ab5SAlexander Yermolovich DWARFDebugInfoEntry &DwarfDebugInfoEntry) { 585c33536e9SAlexander Yermolovich uint64_t TmpRefOffset = RefOffset; 586dcfa2ab5SAlexander Yermolovich if ((RefCU = 587dcfa2ab5SAlexander Yermolovich getUnitForOffset(*this, *DwarfContext, TmpRefOffset, AttrSpec))) { 588dcfa2ab5SAlexander Yermolovich /// Trying to add to current working set in case it's cross CU reference. 589dcfa2ab5SAlexander Yermolovich registerUnit(*RefCU, true); 59087fb0ea2SRui Zhong DWARFDataExtractor DebugInfoData = RefCU->getDebugInfoExtractor(); 591c33536e9SAlexander Yermolovich if (DwarfDebugInfoEntry.extractFast(*RefCU, &TmpRefOffset, DebugInfoData, 59287fb0ea2SRui Zhong RefCU->getNextUnitOffset(), 0)) { 59387fb0ea2SRui Zhong // In a file with broken references, an attribute might point to a NULL 59487fb0ea2SRui Zhong // DIE. 59587fb0ea2SRui Zhong DWARFDie RefDie = DWARFDie(RefCU, &DwarfDebugInfoEntry); 59687fb0ea2SRui Zhong if (!RefDie.isNULL()) { 59787fb0ea2SRui Zhong std::optional<uint32_t> UnitId = getUnitId(*RefCU); 59887fb0ea2SRui Zhong 59987fb0ea2SRui Zhong // forward reference 600dcfa2ab5SAlexander Yermolovich if (UnitId && !getState().CloneUnitCtxMap[*UnitId].IsConstructed && 601c33536e9SAlexander Yermolovich !getAllocDIEId(*RefCU, RefDie)) 602dcfa2ab5SAlexander Yermolovich allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId); 60387fb0ea2SRui Zhong return RefDie; 60487fb0ea2SRui Zhong } 60552cf0711SAmir Ayupov BC.errs() 60652cf0711SAmir Ayupov << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE " 6072c784f7dSAlexander Yermolovich "at offset: " 6082c784f7dSAlexander Yermolovich << Twine::utohexstr(RefOffset) << ".\n"; 60987fb0ea2SRui Zhong 6102c784f7dSAlexander Yermolovich } else { 61152cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse " 6122c784f7dSAlexander Yermolovich "referenced DIE at offset: " 6132c784f7dSAlexander Yermolovich << Twine::utohexstr(RefOffset) << ".\n"; 6142c784f7dSAlexander Yermolovich } 6152c784f7dSAlexander Yermolovich } else { 61652cf0711SAmir Ayupov BC.errs() 61752cf0711SAmir Ayupov << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " 6182c784f7dSAlexander Yermolovich "CU. Referenced DIE offset: " 6192c784f7dSAlexander Yermolovich << Twine::utohexstr(RefOffset) << ".\n"; 6202c784f7dSAlexander Yermolovich } 62187fb0ea2SRui Zhong return DWARFDie(); 62287fb0ea2SRui Zhong } 62387fb0ea2SRui Zhong 62409cbb45eSPavel Labath void DIEBuilder::cloneDieOffsetReferenceAttribute( 625*4b825c74SAlexander Yermolovich DIE &Die, DWARFUnit &U, const DWARFDie &InputDIE, 62609cbb45eSPavel Labath const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, uint64_t Ref) { 62787fb0ea2SRui Zhong DIE *NewRefDie = nullptr; 62887fb0ea2SRui Zhong DWARFUnit *RefUnit = nullptr; 62987fb0ea2SRui Zhong 63087fb0ea2SRui Zhong DWARFDebugInfoEntry DDIEntry; 63109cbb45eSPavel Labath const DWARFDie RefDie = resolveDIEReference(AttrSpec, Ref, RefUnit, DDIEntry); 63287fb0ea2SRui Zhong 633c33536e9SAlexander Yermolovich if (!RefDie) 634c33536e9SAlexander Yermolovich return; 63587fb0ea2SRui Zhong 636c33536e9SAlexander Yermolovich const std::optional<uint32_t> UnitId = getUnitId(*RefUnit); 637c33536e9SAlexander Yermolovich const std::optional<uint32_t> IsAllocId = getAllocDIEId(*RefUnit, RefDie); 638c33536e9SAlexander Yermolovich assert(IsAllocId.has_value() && "Encountered unexpected unallocated DIE."); 639c33536e9SAlexander Yermolovich const uint32_t DIEId = *IsAllocId; 64087fb0ea2SRui Zhong DIEInfo &DieInfo = getDIEInfo(*UnitId, DIEId); 64187fb0ea2SRui Zhong 64287fb0ea2SRui Zhong if (!DieInfo.Die) { 64387fb0ea2SRui Zhong assert(Ref > InputDIE.getOffset()); 644e71f9d26SKazu Hirata (void)Ref; 64552cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected " 646c33536e9SAlexander Yermolovich "unallocated DIE. Should be alloc!\n"; 64787fb0ea2SRui Zhong // We haven't cloned this DIE yet. Just create an empty one and 64887fb0ea2SRui Zhong // store it. It'll get really cloned when we process it. 649dcfa2ab5SAlexander Yermolovich DieInfo.Die = DIE::get(getState().DIEAlloc, dwarf::Tag(RefDie.getTag())); 65087fb0ea2SRui Zhong } 65187fb0ea2SRui Zhong NewRefDie = DieInfo.Die; 65287fb0ea2SRui Zhong 65387fb0ea2SRui Zhong if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) { 654f3cfe016SAlexander Yermolovich // Adding referenced DIE to DebugNames to be used when entries are created 655f3cfe016SAlexander Yermolovich // that contain cross cu references. 656f3cfe016SAlexander Yermolovich if (DebugNamesTable.canGenerateEntryWithCrossCUReference(U, Die, AttrSpec)) 657*4b825c74SAlexander Yermolovich DebugNamesTable.addCrossCUDie(&U, DieInfo.Die); 65887fb0ea2SRui Zhong // no matter forward reference or backward reference, we are supposed 65987fb0ea2SRui Zhong // to calculate them in `finish` due to the possible modification of 66087fb0ea2SRui Zhong // the DIE. 66187fb0ea2SRui Zhong DWARFDie CurDie = const_cast<DWARFDie &>(InputDIE); 662c33536e9SAlexander Yermolovich DIEInfo *CurDieInfo = &getDIEInfoByDwarfDie(CurDie); 663dcfa2ab5SAlexander Yermolovich getState().AddrReferences.push_back( 664c33536e9SAlexander Yermolovich std::make_pair(CurDieInfo, AddrReferenceInfo(&DieInfo, AttrSpec))); 66587fb0ea2SRui Zhong 666dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr, 667f3cfe016SAlexander Yermolovich DIEInteger(DieInfo.Die->getOffset())); 668c33536e9SAlexander Yermolovich return; 66987fb0ea2SRui Zhong } 67087fb0ea2SRui Zhong 671dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 672dcfa2ab5SAlexander Yermolovich DIEEntry(*NewRefDie)); 67387fb0ea2SRui Zhong } 67487fb0ea2SRui Zhong 675c33536e9SAlexander Yermolovich void DIEBuilder::cloneStringAttribute( 676c33536e9SAlexander Yermolovich DIE &Die, const DWARFUnit &U, 677c33536e9SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 678c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 67987fb0ea2SRui Zhong if (AttrSpec.Form == dwarf::DW_FORM_string) { 680c33536e9SAlexander Yermolovich Expected<const char *> StrAddr = Val.getAsCString(); 68187fb0ea2SRui Zhong if (!StrAddr) { 68287fb0ea2SRui Zhong consumeError(StrAddr.takeError()); 683c33536e9SAlexander Yermolovich return; 68487fb0ea2SRui Zhong } 685dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_string, 686dcfa2ab5SAlexander Yermolovich new (getState().DIEAlloc) 687dcfa2ab5SAlexander Yermolovich DIEInlineString(StrAddr.get(), getState().DIEAlloc)); 68887fb0ea2SRui Zhong } else { 68987fb0ea2SRui Zhong std::optional<uint64_t> OffsetIndex = Val.getRawUValue(); 690dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 69187fb0ea2SRui Zhong DIEInteger(*OffsetIndex)); 69287fb0ea2SRui Zhong } 69387fb0ea2SRui Zhong } 69487fb0ea2SRui Zhong 695c33536e9SAlexander Yermolovich bool DIEBuilder::cloneExpression(const DataExtractor &Data, 696c33536e9SAlexander Yermolovich const DWARFExpression &Expression, 697c33536e9SAlexander Yermolovich DWARFUnit &U, 698c33536e9SAlexander Yermolovich SmallVectorImpl<uint8_t> &OutputBuffer, 699c33536e9SAlexander Yermolovich const CloneExpressionStage &Stage) { 70087fb0ea2SRui Zhong using Encoding = DWARFExpression::Operation::Encoding; 701c33536e9SAlexander Yermolovich using Descr = DWARFExpression::Operation::Description; 70287fb0ea2SRui Zhong uint64_t OpOffset = 0; 703c33536e9SAlexander Yermolovich bool DoesContainReference = false; 704c33536e9SAlexander Yermolovich for (const DWARFExpression::Operation &Op : Expression) { 705c33536e9SAlexander Yermolovich const Descr &Description = Op.getDescription(); 70687fb0ea2SRui Zhong // DW_OP_const_type is variable-length and has 3 70787fb0ea2SRui Zhong // operands. Thus far we only support 2. 70887fb0ea2SRui Zhong if ((Description.Op.size() == 2 && 70987fb0ea2SRui Zhong Description.Op[0] == Encoding::BaseTypeRef) || 71087fb0ea2SRui Zhong (Description.Op.size() == 2 && 71187fb0ea2SRui Zhong Description.Op[1] == Encoding::BaseTypeRef && 71287fb0ea2SRui Zhong Description.Op[0] != Encoding::Size1)) 71352cf0711SAmir Ayupov BC.outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP " 714c33536e9SAlexander Yermolovich "encoding.\n"; 71587fb0ea2SRui Zhong 71687fb0ea2SRui Zhong if ((Description.Op.size() == 1 && 71787fb0ea2SRui Zhong Description.Op[0] == Encoding::BaseTypeRef) || 71887fb0ea2SRui Zhong (Description.Op.size() == 2 && 71987fb0ea2SRui Zhong Description.Op[1] == Encoding::BaseTypeRef && 72087fb0ea2SRui Zhong Description.Op[0] == Encoding::Size1)) { 72187fb0ea2SRui Zhong // This code assumes that the other non-typeref operand fits into 1 72287fb0ea2SRui Zhong // byte. 72387fb0ea2SRui Zhong assert(OpOffset < Op.getEndOffset()); 724c33536e9SAlexander Yermolovich const uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; 725c33536e9SAlexander Yermolovich (void)ULEBsize; 72687fb0ea2SRui Zhong assert(ULEBsize <= 16); 72787fb0ea2SRui Zhong 72887fb0ea2SRui Zhong // Copy over the operation. 72987fb0ea2SRui Zhong OutputBuffer.push_back(Op.getCode()); 73087fb0ea2SRui Zhong uint64_t RefOffset; 73187fb0ea2SRui Zhong if (Description.Op.size() == 1) { 73287fb0ea2SRui Zhong RefOffset = Op.getRawOperand(0); 73387fb0ea2SRui Zhong } else { 73487fb0ea2SRui Zhong OutputBuffer.push_back(Op.getRawOperand(0)); 73587fb0ea2SRui Zhong RefOffset = Op.getRawOperand(1); 73687fb0ea2SRui Zhong } 73787fb0ea2SRui Zhong uint32_t Offset = 0; 73887fb0ea2SRui Zhong if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) { 739c33536e9SAlexander Yermolovich DoesContainReference = true; 740c33536e9SAlexander Yermolovich std::optional<uint32_t> RefDieID = 741c33536e9SAlexander Yermolovich getAllocDIEId(U, U.getOffset() + RefOffset); 74287fb0ea2SRui Zhong std::optional<uint32_t> RefUnitID = getUnitId(U); 74387fb0ea2SRui Zhong if (RefDieID.has_value() && RefUnitID.has_value()) { 74487fb0ea2SRui Zhong DIEInfo &RefDieInfo = getDIEInfo(*RefUnitID, *RefDieID); 74587fb0ea2SRui Zhong if (DIE *Clone = RefDieInfo.Die) 746c33536e9SAlexander Yermolovich Offset = Stage == CloneExpressionStage::INIT ? RefOffset 747c33536e9SAlexander Yermolovich : Clone->getOffset(); 74887fb0ea2SRui Zhong else 74952cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref " 750c33536e9SAlexander Yermolovich "doesn't point to " 75187fb0ea2SRui Zhong "DW_TAG_base_type.\n"; 75287fb0ea2SRui Zhong } 75387fb0ea2SRui Zhong } 75487fb0ea2SRui Zhong uint8_t ULEB[16]; 755c33536e9SAlexander Yermolovich // Hard coding to max size so size doesn't change when we update the 756c33536e9SAlexander Yermolovich // offset. 757c33536e9SAlexander Yermolovich encodeULEB128(Offset, ULEB, 4); 758c33536e9SAlexander Yermolovich ArrayRef<uint8_t> ULEBbytes(ULEB, 4); 75987fb0ea2SRui Zhong OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end()); 76087fb0ea2SRui Zhong } else { 76187fb0ea2SRui Zhong // Copy over everything else unmodified. 762c33536e9SAlexander Yermolovich const StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); 76387fb0ea2SRui Zhong OutputBuffer.append(Bytes.begin(), Bytes.end()); 76487fb0ea2SRui Zhong } 76587fb0ea2SRui Zhong OpOffset = Op.getEndOffset(); 76687fb0ea2SRui Zhong } 767c33536e9SAlexander Yermolovich return DoesContainReference; 76887fb0ea2SRui Zhong } 76987fb0ea2SRui Zhong 770c33536e9SAlexander Yermolovich void DIEBuilder::cloneBlockAttribute( 77187fb0ea2SRui Zhong DIE &Die, DWARFUnit &U, 772c33536e9SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 773c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 77487fb0ea2SRui Zhong DIEValueList *Attr; 77587fb0ea2SRui Zhong DIEValue Value; 77687fb0ea2SRui Zhong DIELoc *Loc = nullptr; 77787fb0ea2SRui Zhong DIEBlock *Block = nullptr; 77887fb0ea2SRui Zhong 77987fb0ea2SRui Zhong if (AttrSpec.Form == dwarf::DW_FORM_exprloc) { 780dcfa2ab5SAlexander Yermolovich Loc = new (getState().DIEAlloc) DIELoc; 78187fb0ea2SRui Zhong } else if (doesFormBelongToClass(AttrSpec.Form, DWARFFormValue::FC_Block, 78287fb0ea2SRui Zhong U.getVersion())) { 783dcfa2ab5SAlexander Yermolovich Block = new (getState().DIEAlloc) DIEBlock; 78487fb0ea2SRui Zhong } else { 78552cf0711SAmir Ayupov BC.errs() 78652cf0711SAmir Ayupov << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in " 78787fb0ea2SRui Zhong "cloneBlockAttribute\n"; 788c33536e9SAlexander Yermolovich return; 78987fb0ea2SRui Zhong } 79087fb0ea2SRui Zhong Attr = Loc ? static_cast<DIEValueList *>(Loc) 79187fb0ea2SRui Zhong : static_cast<DIEValueList *>(Block); 79287fb0ea2SRui Zhong 79387fb0ea2SRui Zhong SmallVector<uint8_t, 32> Buffer; 79487fb0ea2SRui Zhong ArrayRef<uint8_t> Bytes = *Val.getAsBlock(); 79587fb0ea2SRui Zhong if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && 79687fb0ea2SRui Zhong (Val.isFormClass(DWARFFormValue::FC_Block) || 79787fb0ea2SRui Zhong Val.isFormClass(DWARFFormValue::FC_Exprloc))) { 79887fb0ea2SRui Zhong DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()), 799c33536e9SAlexander Yermolovich U.isLittleEndian(), U.getAddressByteSize()); 80087fb0ea2SRui Zhong DWARFExpression Expr(Data, U.getAddressByteSize(), 80187fb0ea2SRui Zhong U.getFormParams().Format); 802c33536e9SAlexander Yermolovich if (cloneExpression(Data, Expr, U, Buffer, CloneExpressionStage::INIT)) 803dcfa2ab5SAlexander Yermolovich getState().LocWithReferencesToProcess.emplace_back( 804dcfa2ab5SAlexander Yermolovich Bytes.vec(), U, Die, AttrSpec.Form, AttrSpec.Attr); 80587fb0ea2SRui Zhong Bytes = Buffer; 80687fb0ea2SRui Zhong } 80787fb0ea2SRui Zhong for (auto Byte : Bytes) 808dcfa2ab5SAlexander Yermolovich Attr->addValue(getState().DIEAlloc, static_cast<dwarf::Attribute>(0), 80987fb0ea2SRui Zhong dwarf::DW_FORM_data1, DIEInteger(Byte)); 81087fb0ea2SRui Zhong 81187fb0ea2SRui Zhong if (Loc) 81287fb0ea2SRui Zhong Loc->setSize(Bytes.size()); 81387fb0ea2SRui Zhong else 81487fb0ea2SRui Zhong Block->setSize(Bytes.size()); 81587fb0ea2SRui Zhong 816c33536e9SAlexander Yermolovich if (Loc) 817c33536e9SAlexander Yermolovich Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), 818c33536e9SAlexander Yermolovich dwarf::Form(AttrSpec.Form), Loc); 819c33536e9SAlexander Yermolovich else 820c33536e9SAlexander Yermolovich Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), 821c33536e9SAlexander Yermolovich dwarf::Form(AttrSpec.Form), Block); 822dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, Value); 82387fb0ea2SRui Zhong } 82487fb0ea2SRui Zhong 825c33536e9SAlexander Yermolovich void DIEBuilder::cloneAddressAttribute( 826c33536e9SAlexander Yermolovich DIE &Die, const DWARFUnit &U, 827c33536e9SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 828c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 829dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 830c33536e9SAlexander Yermolovich DIEInteger(Val.getRawUValue())); 831c33536e9SAlexander Yermolovich } 832c33536e9SAlexander Yermolovich 833c33536e9SAlexander Yermolovich void DIEBuilder::cloneRefsigAttribute( 83487fb0ea2SRui Zhong DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 835c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 83609cbb45eSPavel Labath const std::optional<uint64_t> SigVal = Val.getAsSignatureReference(); 837dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_sig8, 838c33536e9SAlexander Yermolovich DIEInteger(*SigVal)); 83987fb0ea2SRui Zhong } 84087fb0ea2SRui Zhong 841c33536e9SAlexander Yermolovich void DIEBuilder::cloneScalarAttribute( 84287fb0ea2SRui Zhong DIE &Die, const DWARFDie &InputDIE, 843c33536e9SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 844c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 84587fb0ea2SRui Zhong uint64_t Value; 84687fb0ea2SRui Zhong 84787fb0ea2SRui Zhong if (auto OptionalValue = Val.getAsUnsignedConstant()) 84887fb0ea2SRui Zhong Value = *OptionalValue; 84987fb0ea2SRui Zhong else if (auto OptionalValue = Val.getAsSignedConstant()) 85087fb0ea2SRui Zhong Value = *OptionalValue; 85187fb0ea2SRui Zhong else if (auto OptionalValue = Val.getAsSectionOffset()) 85287fb0ea2SRui Zhong Value = *OptionalValue; 85387fb0ea2SRui Zhong else { 85452cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " 855c33536e9SAlexander Yermolovich "attribute form. Dropping " 85687fb0ea2SRui Zhong "attribute.\n"; 857c33536e9SAlexander Yermolovich return; 85887fb0ea2SRui Zhong } 85987fb0ea2SRui Zhong 860dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 861dcfa2ab5SAlexander Yermolovich DIEInteger(Value)); 86287fb0ea2SRui Zhong } 86387fb0ea2SRui Zhong 864c33536e9SAlexander Yermolovich void DIEBuilder::cloneLoclistAttrubute( 86587fb0ea2SRui Zhong DIE &Die, const DWARFDie &InputDIE, 866c33536e9SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 867c33536e9SAlexander Yermolovich const DWARFFormValue &Val) { 868c33536e9SAlexander Yermolovich std::optional<uint64_t> Value = std::nullopt; 86987fb0ea2SRui Zhong 87087fb0ea2SRui Zhong if (auto OptionalValue = Val.getAsUnsignedConstant()) 871c33536e9SAlexander Yermolovich Value = OptionalValue; 87287fb0ea2SRui Zhong else if (auto OptionalValue = Val.getAsSignedConstant()) 873c33536e9SAlexander Yermolovich Value = OptionalValue; 87487fb0ea2SRui Zhong else if (auto OptionalValue = Val.getAsSectionOffset()) 875c33536e9SAlexander Yermolovich Value = OptionalValue; 876c33536e9SAlexander Yermolovich else 87752cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " 878c33536e9SAlexander Yermolovich "attribute form. Dropping " 87987fb0ea2SRui Zhong "attribute.\n"; 880c33536e9SAlexander Yermolovich 881c33536e9SAlexander Yermolovich if (!Value.has_value()) 882c33536e9SAlexander Yermolovich return; 883c33536e9SAlexander Yermolovich 884dcfa2ab5SAlexander Yermolovich Die.addValue(getState().DIEAlloc, AttrSpec.Attr, AttrSpec.Form, 885dcfa2ab5SAlexander Yermolovich DIELocList(*Value)); 88687fb0ea2SRui Zhong } 88787fb0ea2SRui Zhong 888c33536e9SAlexander Yermolovich void DIEBuilder::cloneAttribute( 88987fb0ea2SRui Zhong DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U, const DWARFFormValue &Val, 890dcfa2ab5SAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec) { 89187fb0ea2SRui Zhong switch (AttrSpec.Form) { 89287fb0ea2SRui Zhong case dwarf::DW_FORM_strp: 89387fb0ea2SRui Zhong case dwarf::DW_FORM_string: 89487fb0ea2SRui Zhong case dwarf::DW_FORM_strx: 89587fb0ea2SRui Zhong case dwarf::DW_FORM_strx1: 89687fb0ea2SRui Zhong case dwarf::DW_FORM_strx2: 89787fb0ea2SRui Zhong case dwarf::DW_FORM_strx3: 89887fb0ea2SRui Zhong case dwarf::DW_FORM_strx4: 89987fb0ea2SRui Zhong case dwarf::DW_FORM_GNU_str_index: 90087fb0ea2SRui Zhong case dwarf::DW_FORM_line_strp: 901c33536e9SAlexander Yermolovich cloneStringAttribute(Die, U, AttrSpec, Val); 902c33536e9SAlexander Yermolovich break; 90387fb0ea2SRui Zhong case dwarf::DW_FORM_ref_addr: 90409cbb45eSPavel Labath cloneDieOffsetReferenceAttribute(Die, U, InputDIE, AttrSpec, 90509cbb45eSPavel Labath *Val.getAsDebugInfoReference()); 90609cbb45eSPavel Labath break; 90787fb0ea2SRui Zhong case dwarf::DW_FORM_ref1: 90887fb0ea2SRui Zhong case dwarf::DW_FORM_ref2: 90987fb0ea2SRui Zhong case dwarf::DW_FORM_ref4: 91087fb0ea2SRui Zhong case dwarf::DW_FORM_ref8: 91109cbb45eSPavel Labath cloneDieOffsetReferenceAttribute(Die, U, InputDIE, AttrSpec, 91209cbb45eSPavel Labath Val.getUnit()->getOffset() + 91309cbb45eSPavel Labath *Val.getAsRelativeReference()); 914c33536e9SAlexander Yermolovich break; 91587fb0ea2SRui Zhong case dwarf::DW_FORM_block: 91687fb0ea2SRui Zhong case dwarf::DW_FORM_block1: 91787fb0ea2SRui Zhong case dwarf::DW_FORM_block2: 91887fb0ea2SRui Zhong case dwarf::DW_FORM_block4: 91987fb0ea2SRui Zhong case dwarf::DW_FORM_exprloc: 920c33536e9SAlexander Yermolovich cloneBlockAttribute(Die, U, AttrSpec, Val); 921c33536e9SAlexander Yermolovich break; 92287fb0ea2SRui Zhong case dwarf::DW_FORM_addr: 92387fb0ea2SRui Zhong case dwarf::DW_FORM_addrx: 92487fb0ea2SRui Zhong case dwarf::DW_FORM_GNU_addr_index: 925c33536e9SAlexander Yermolovich cloneAddressAttribute(Die, U, AttrSpec, Val); 926c33536e9SAlexander Yermolovich break; 92787fb0ea2SRui Zhong case dwarf::DW_FORM_data1: 92887fb0ea2SRui Zhong case dwarf::DW_FORM_data2: 92987fb0ea2SRui Zhong case dwarf::DW_FORM_data4: 93087fb0ea2SRui Zhong case dwarf::DW_FORM_data8: 93187fb0ea2SRui Zhong case dwarf::DW_FORM_udata: 93287fb0ea2SRui Zhong case dwarf::DW_FORM_sdata: 93387fb0ea2SRui Zhong case dwarf::DW_FORM_sec_offset: 93487fb0ea2SRui Zhong case dwarf::DW_FORM_rnglistx: 93587fb0ea2SRui Zhong case dwarf::DW_FORM_flag: 93687fb0ea2SRui Zhong case dwarf::DW_FORM_flag_present: 93787fb0ea2SRui Zhong case dwarf::DW_FORM_implicit_const: 938c33536e9SAlexander Yermolovich cloneScalarAttribute(Die, InputDIE, AttrSpec, Val); 939c33536e9SAlexander Yermolovich break; 94087fb0ea2SRui Zhong case dwarf::DW_FORM_loclistx: 941c33536e9SAlexander Yermolovich cloneLoclistAttrubute(Die, InputDIE, AttrSpec, Val); 942c33536e9SAlexander Yermolovich break; 94387fb0ea2SRui Zhong case dwarf::DW_FORM_ref_sig8: 944c33536e9SAlexander Yermolovich cloneRefsigAttribute(Die, AttrSpec, Val); 945c33536e9SAlexander Yermolovich break; 94687fb0ea2SRui Zhong default: 94752cf0711SAmir Ayupov BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute " 948c33536e9SAlexander Yermolovich "form " + 94987fb0ea2SRui Zhong dwarf::FormEncodingString(AttrSpec.Form).str() + 95087fb0ea2SRui Zhong " in cloneAttribute. Dropping."; 95187fb0ea2SRui Zhong } 95287fb0ea2SRui Zhong } 95387fb0ea2SRui Zhong void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) { 95487fb0ea2SRui Zhong // Check the set for priors. 95587fb0ea2SRui Zhong FoldingSetNodeID ID; 95687fb0ea2SRui Zhong Abbrev.Profile(ID); 95787fb0ea2SRui Zhong void *InsertToken; 95887fb0ea2SRui Zhong DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken); 95987fb0ea2SRui Zhong 96087fb0ea2SRui Zhong // If it's newly added. 96187fb0ea2SRui Zhong if (InSet) { 96287fb0ea2SRui Zhong // Assign existing abbreviation number. 96387fb0ea2SRui Zhong Abbrev.setNumber(InSet->getNumber()); 96487fb0ea2SRui Zhong } else { 96587fb0ea2SRui Zhong // Add to abbreviation list. 96687fb0ea2SRui Zhong Abbreviations.push_back( 96787fb0ea2SRui Zhong std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren())); 96887fb0ea2SRui Zhong for (const auto &Attr : Abbrev.getData()) 96987fb0ea2SRui Zhong Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm()); 97087fb0ea2SRui Zhong AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken); 97187fb0ea2SRui Zhong // Assign the unique abbreviation number. 97287fb0ea2SRui Zhong Abbrev.setNumber(Abbreviations.size()); 97387fb0ea2SRui Zhong Abbreviations.back()->setNumber(Abbreviations.size()); 97487fb0ea2SRui Zhong } 97587fb0ea2SRui Zhong } 97687fb0ea2SRui Zhong 97787fb0ea2SRui Zhong void DIEBuilder::generateAbbrevs() { 978c33536e9SAlexander Yermolovich if (isEmpty()) 97987fb0ea2SRui Zhong return; 98087fb0ea2SRui Zhong 981dcfa2ab5SAlexander Yermolovich for (DWARFUnit *DU : getState().DUList) { 98287fb0ea2SRui Zhong DIE *UnitDIE = getUnitDIEbyUnit(*DU); 98387fb0ea2SRui Zhong generateUnitAbbrevs(UnitDIE); 98487fb0ea2SRui Zhong } 98587fb0ea2SRui Zhong } 98687fb0ea2SRui Zhong 98787fb0ea2SRui Zhong void DIEBuilder::generateUnitAbbrevs(DIE *Die) { 98887fb0ea2SRui Zhong DIEAbbrev NewAbbrev = Die->generateAbbrev(); 98987fb0ea2SRui Zhong 99087fb0ea2SRui Zhong if (Die->hasChildren()) 99187fb0ea2SRui Zhong NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); 99287fb0ea2SRui Zhong assignAbbrev(NewAbbrev); 99387fb0ea2SRui Zhong Die->setAbbrevNumber(NewAbbrev.getNumber()); 99487fb0ea2SRui Zhong 99587fb0ea2SRui Zhong for (auto &Child : Die->children()) { 99687fb0ea2SRui Zhong generateUnitAbbrevs(&Child); 99787fb0ea2SRui Zhong } 99887fb0ea2SRui Zhong } 99987fb0ea2SRui Zhong 1000c33536e9SAlexander Yermolovich static uint64_t getHash(const DWARFUnit &DU) { 1001c33536e9SAlexander Yermolovich // Before DWARF5 TU units are in their own section, so at least one offset, 1002c33536e9SAlexander Yermolovich // first one, will be the same as CUs in .debug_info.dwo section 1003c33536e9SAlexander Yermolovich if (DU.getVersion() < 5 && DU.isTypeUnit()) { 1004f52e61f3SAlexander Yermolovich const uint64_t TypeUnitHash = 1005f52e61f3SAlexander Yermolovich cast_or_null<DWARFTypeUnit>(&DU)->getTypeHash(); 1006f52e61f3SAlexander Yermolovich const uint64_t Offset = DU.getOffset(); 1007f52e61f3SAlexander Yermolovich return llvm::hash_combine(llvm::hash_value(TypeUnitHash), 1008f52e61f3SAlexander Yermolovich llvm::hash_value(Offset)); 1009c33536e9SAlexander Yermolovich } 1010c33536e9SAlexander Yermolovich return DU.getOffset(); 1011c33536e9SAlexander Yermolovich } 1012c33536e9SAlexander Yermolovich 1013dcfa2ab5SAlexander Yermolovich void DIEBuilder::registerUnit(DWARFUnit &DU, bool NeedSort) { 1014dcfa2ab5SAlexander Yermolovich auto IterGlobal = AllProcessed.insert(getHash(DU)); 1015dcfa2ab5SAlexander Yermolovich // If DU is already in a current working set or was already processed we can 1016dcfa2ab5SAlexander Yermolovich // skip it. 1017dcfa2ab5SAlexander Yermolovich if (!IterGlobal.second) 1018dcfa2ab5SAlexander Yermolovich return; 1019dcfa2ab5SAlexander Yermolovich if (getState().Type == ProcessingType::DWARF4TUs) { 1020dcfa2ab5SAlexander Yermolovich getState().DWARF4TUVector.push_back(&DU); 1021dcfa2ab5SAlexander Yermolovich } else if (getState().Type == ProcessingType::DWARF5TUs) { 1022dcfa2ab5SAlexander Yermolovich getState().DWARF5TUVector.push_back(&DU); 1023dcfa2ab5SAlexander Yermolovich } else { 1024dcfa2ab5SAlexander Yermolovich getState().DWARFCUVector.push_back(&DU); 1025dcfa2ab5SAlexander Yermolovich /// Sorting for cross CU reference resolution. 1026dcfa2ab5SAlexander Yermolovich if (NeedSort) 1027dcfa2ab5SAlexander Yermolovich std::sort(getState().DWARFCUVector.begin(), 1028dcfa2ab5SAlexander Yermolovich getState().DWARFCUVector.end(), 1029dcfa2ab5SAlexander Yermolovich [](const DWARFUnit *A, const DWARFUnit *B) { 1030dcfa2ab5SAlexander Yermolovich return A->getOffset() < B->getOffset(); 1031dcfa2ab5SAlexander Yermolovich }); 1032dcfa2ab5SAlexander Yermolovich } 1033dcfa2ab5SAlexander Yermolovich getState().UnitIDMap[getHash(DU)] = getState().DUList.size(); 1034ad4cead6SAlexander Yermolovich // This handles the case where we do have cross cu references, but CUs do not 1035ad4cead6SAlexander Yermolovich // share the same abbrev table. 1036ad4cead6SAlexander Yermolovich if (getState().DUList.size() == getState().CloneUnitCtxMap.size()) 1037ad4cead6SAlexander Yermolovich getState().CloneUnitCtxMap.emplace_back(); 1038dcfa2ab5SAlexander Yermolovich getState().DUList.push_back(&DU); 1039c33536e9SAlexander Yermolovich } 1040c33536e9SAlexander Yermolovich 1041c33536e9SAlexander Yermolovich std::optional<uint32_t> DIEBuilder::getUnitId(const DWARFUnit &DU) { 1042dcfa2ab5SAlexander Yermolovich auto Iter = getState().UnitIDMap.find(getHash(DU)); 1043dcfa2ab5SAlexander Yermolovich if (Iter != getState().UnitIDMap.end()) 1044c33536e9SAlexander Yermolovich return Iter->second; 1045c33536e9SAlexander Yermolovich return std::nullopt; 1046c33536e9SAlexander Yermolovich } 1047c33536e9SAlexander Yermolovich 104887fb0ea2SRui Zhong } // namespace bolt 104987fb0ea2SRui Zhong } // namespace llvm 1050