xref: /llvm-project/bolt/lib/Core/DIEBuilder.cpp (revision 4b825c7417f72ee88ee3e4316d0c01ed463f1241)
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