xref: /llvm-project/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp (revision 2357e899cb11e05312c54b689ebd0355487be6bc)
1*2357e899Savl-llvm //===- DWARFLinkerCompileUnit.cpp -----------------------------------------===//
2*2357e899Savl-llvm //
3*2357e899Savl-llvm // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2357e899Savl-llvm // See https://llvm.org/LICENSE.txt for license information.
5*2357e899Savl-llvm // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*2357e899Savl-llvm //
7*2357e899Savl-llvm //===----------------------------------------------------------------------===//
8*2357e899Savl-llvm 
9*2357e899Savl-llvm #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
10*2357e899Savl-llvm #include "llvm/ADT/StringExtras.h"
11*2357e899Savl-llvm #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h"
12*2357e899Savl-llvm #include "llvm/DebugInfo/DWARF/DWARFContext.h"
13*2357e899Savl-llvm #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
14*2357e899Savl-llvm #include "llvm/Support/FormatVariadic.h"
15*2357e899Savl-llvm 
16*2357e899Savl-llvm namespace llvm {
17*2357e899Savl-llvm 
18*2357e899Savl-llvm using namespace dwarf_linker;
19*2357e899Savl-llvm using namespace dwarf_linker::classic;
20*2357e899Savl-llvm 
21*2357e899Savl-llvm #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()22*2357e899Savl-llvm LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
23*2357e899Savl-llvm   llvm::errs() << "{\n";
24*2357e899Savl-llvm   llvm::errs() << "  AddrAdjust: " << AddrAdjust << '\n';
25*2357e899Savl-llvm   llvm::errs() << "  Ctxt: " << formatv("{0:x}", Ctxt) << '\n';
26*2357e899Savl-llvm   llvm::errs() << "  Clone: " << formatv("{0:x}", Clone) << '\n';
27*2357e899Savl-llvm   llvm::errs() << "  ParentIdx: " << ParentIdx << '\n';
28*2357e899Savl-llvm   llvm::errs() << "  Keep: " << Keep << '\n';
29*2357e899Savl-llvm   llvm::errs() << "  InDebugMap: " << InDebugMap << '\n';
30*2357e899Savl-llvm   llvm::errs() << "  Prune: " << Prune << '\n';
31*2357e899Savl-llvm   llvm::errs() << "  Incomplete: " << Incomplete << '\n';
32*2357e899Savl-llvm   llvm::errs() << "  InModuleScope: " << InModuleScope << '\n';
33*2357e899Savl-llvm   llvm::errs() << "  ODRMarkingDone: " << ODRMarkingDone << '\n';
34*2357e899Savl-llvm   llvm::errs() << "  UnclonedReference: " << UnclonedReference << '\n';
35*2357e899Savl-llvm   llvm::errs() << "}\n";
36*2357e899Savl-llvm }
37*2357e899Savl-llvm #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
38*2357e899Savl-llvm 
39*2357e899Savl-llvm /// Check if the DIE at \p Idx is in the scope of a function.
inFunctionScope(CompileUnit & U,unsigned Idx)40*2357e899Savl-llvm static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
41*2357e899Savl-llvm   while (Idx) {
42*2357e899Savl-llvm     if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
43*2357e899Savl-llvm       return true;
44*2357e899Savl-llvm     Idx = U.getInfo(Idx).ParentIdx;
45*2357e899Savl-llvm   }
46*2357e899Savl-llvm   return false;
47*2357e899Savl-llvm }
48*2357e899Savl-llvm 
getLanguage()49*2357e899Savl-llvm uint16_t CompileUnit::getLanguage() {
50*2357e899Savl-llvm   if (!Language) {
51*2357e899Savl-llvm     DWARFDie CU = getOrigUnit().getUnitDIE();
52*2357e899Savl-llvm     Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
53*2357e899Savl-llvm   }
54*2357e899Savl-llvm   return Language;
55*2357e899Savl-llvm }
56*2357e899Savl-llvm 
getSysRoot()57*2357e899Savl-llvm StringRef CompileUnit::getSysRoot() {
58*2357e899Savl-llvm   if (SysRoot.empty()) {
59*2357e899Savl-llvm     DWARFDie CU = getOrigUnit().getUnitDIE();
60*2357e899Savl-llvm     SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
61*2357e899Savl-llvm   }
62*2357e899Savl-llvm   return SysRoot;
63*2357e899Savl-llvm }
64*2357e899Savl-llvm 
markEverythingAsKept()65*2357e899Savl-llvm void CompileUnit::markEverythingAsKept() {
66*2357e899Savl-llvm   unsigned Idx = 0;
67*2357e899Savl-llvm 
68*2357e899Savl-llvm   for (auto &I : Info) {
69*2357e899Savl-llvm     // Mark everything that wasn't explicit marked for pruning.
70*2357e899Savl-llvm     I.Keep = !I.Prune;
71*2357e899Savl-llvm     auto DIE = OrigUnit.getDIEAtIndex(Idx++);
72*2357e899Savl-llvm     DWARFUnit *U = DIE.getDwarfUnit();
73*2357e899Savl-llvm 
74*2357e899Savl-llvm     // Try to guess which DIEs must go to the accelerator tables. We do that
75*2357e899Savl-llvm     // just for variables, because functions will be handled depending on
76*2357e899Savl-llvm     // whether they carry a DW_AT_low_pc attribute or not.
77*2357e899Savl-llvm     if (DIE.getTag() != dwarf::DW_TAG_variable &&
78*2357e899Savl-llvm         DIE.getTag() != dwarf::DW_TAG_constant)
79*2357e899Savl-llvm       continue;
80*2357e899Savl-llvm 
81*2357e899Savl-llvm     std::optional<DWARFFormValue> Value;
82*2357e899Savl-llvm     if (!(Value = DIE.find(dwarf::DW_AT_location))) {
83*2357e899Savl-llvm       if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
84*2357e899Savl-llvm           !inFunctionScope(*this, I.ParentIdx))
85*2357e899Savl-llvm         I.InDebugMap = true;
86*2357e899Savl-llvm       continue;
87*2357e899Savl-llvm     }
88*2357e899Savl-llvm 
89*2357e899Savl-llvm     if (auto ExprLockBlock = Value->getAsBlock()) {
90*2357e899Savl-llvm       // Parse 'exprloc' expression.
91*2357e899Savl-llvm       DataExtractor Data(toStringRef(*ExprLockBlock),
92*2357e899Savl-llvm                          U->getContext().isLittleEndian(),
93*2357e899Savl-llvm                          U->getAddressByteSize());
94*2357e899Savl-llvm       DWARFExpression Expression(Data, U->getAddressByteSize(),
95*2357e899Savl-llvm                                  U->getFormParams().Format);
96*2357e899Savl-llvm 
97*2357e899Savl-llvm       for (DWARFExpression::iterator It = Expression.begin();
98*2357e899Savl-llvm            (It != Expression.end()) && !I.InDebugMap; ++It) {
99*2357e899Savl-llvm         DWARFExpression::iterator NextIt = It;
100*2357e899Savl-llvm         ++NextIt;
101*2357e899Savl-llvm 
102*2357e899Savl-llvm         switch (It->getCode()) {
103*2357e899Savl-llvm         case dwarf::DW_OP_const2u:
104*2357e899Savl-llvm         case dwarf::DW_OP_const4u:
105*2357e899Savl-llvm         case dwarf::DW_OP_const8u:
106*2357e899Savl-llvm         case dwarf::DW_OP_const2s:
107*2357e899Savl-llvm         case dwarf::DW_OP_const4s:
108*2357e899Savl-llvm         case dwarf::DW_OP_const8s:
109*2357e899Savl-llvm           if (NextIt == Expression.end() ||
110*2357e899Savl-llvm               NextIt->getCode() != dwarf::DW_OP_form_tls_address)
111*2357e899Savl-llvm             break;
112*2357e899Savl-llvm           [[fallthrough]];
113*2357e899Savl-llvm         case dwarf::DW_OP_constx:
114*2357e899Savl-llvm         case dwarf::DW_OP_addr:
115*2357e899Savl-llvm         case dwarf::DW_OP_addrx:
116*2357e899Savl-llvm           I.InDebugMap = true;
117*2357e899Savl-llvm           break;
118*2357e899Savl-llvm         default:
119*2357e899Savl-llvm           // Nothing to do.
120*2357e899Savl-llvm           break;
121*2357e899Savl-llvm         }
122*2357e899Savl-llvm       }
123*2357e899Savl-llvm     }
124*2357e899Savl-llvm   }
125*2357e899Savl-llvm }
126*2357e899Savl-llvm 
computeNextUnitOffset(uint16_t DwarfVersion)127*2357e899Savl-llvm uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
128*2357e899Savl-llvm   NextUnitOffset = StartOffset;
129*2357e899Savl-llvm   if (NewUnit) {
130*2357e899Savl-llvm     NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; // Header size
131*2357e899Savl-llvm     NextUnitOffset += NewUnit->getUnitDie().getSize();
132*2357e899Savl-llvm   }
133*2357e899Savl-llvm   return NextUnitOffset;
134*2357e899Savl-llvm }
135*2357e899Savl-llvm 
136*2357e899Savl-llvm /// Keep track of a forward cross-cu reference from this unit
137*2357e899Savl-llvm /// to \p Die that lives in \p RefUnit.
noteForwardReference(DIE * Die,const CompileUnit * RefUnit,DeclContext * Ctxt,PatchLocation Attr)138*2357e899Savl-llvm void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
139*2357e899Savl-llvm                                        DeclContext *Ctxt, PatchLocation Attr) {
140*2357e899Savl-llvm   ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
141*2357e899Savl-llvm }
142*2357e899Savl-llvm 
fixupForwardReferences()143*2357e899Savl-llvm void CompileUnit::fixupForwardReferences() {
144*2357e899Savl-llvm   for (const auto &Ref : ForwardDIEReferences) {
145*2357e899Savl-llvm     DIE *RefDie;
146*2357e899Savl-llvm     const CompileUnit *RefUnit;
147*2357e899Savl-llvm     PatchLocation Attr;
148*2357e899Savl-llvm     DeclContext *Ctxt;
149*2357e899Savl-llvm     std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
150*2357e899Savl-llvm     if (Ctxt && Ctxt->hasCanonicalDIE()) {
151*2357e899Savl-llvm       assert(Ctxt->getCanonicalDIEOffset() &&
152*2357e899Savl-llvm              "Canonical die offset is not set");
153*2357e899Savl-llvm       Attr.set(Ctxt->getCanonicalDIEOffset());
154*2357e899Savl-llvm     } else {
155*2357e899Savl-llvm       assert(RefDie->getOffset() && "Referenced die offset is not set");
156*2357e899Savl-llvm       Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
157*2357e899Savl-llvm     }
158*2357e899Savl-llvm   }
159*2357e899Savl-llvm }
160*2357e899Savl-llvm 
addLabelLowPc(uint64_t LabelLowPc,int64_t PcOffset)161*2357e899Savl-llvm void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
162*2357e899Savl-llvm   Labels.insert({LabelLowPc, PcOffset});
163*2357e899Savl-llvm }
164*2357e899Savl-llvm 
addFunctionRange(uint64_t FuncLowPc,uint64_t FuncHighPc,int64_t PcOffset)165*2357e899Savl-llvm void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
166*2357e899Savl-llvm                                    int64_t PcOffset) {
167*2357e899Savl-llvm   Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
168*2357e899Savl-llvm   if (LowPc)
169*2357e899Savl-llvm     LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
170*2357e899Savl-llvm   else
171*2357e899Savl-llvm     LowPc = FuncLowPc + PcOffset;
172*2357e899Savl-llvm   this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
173*2357e899Savl-llvm }
174*2357e899Savl-llvm 
noteRangeAttribute(const DIE & Die,PatchLocation Attr)175*2357e899Savl-llvm void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
176*2357e899Savl-llvm   if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
177*2357e899Savl-llvm     UnitRangeAttribute = Attr;
178*2357e899Savl-llvm     return;
179*2357e899Savl-llvm   }
180*2357e899Savl-llvm 
181*2357e899Savl-llvm   RangeAttributes.emplace_back(Attr);
182*2357e899Savl-llvm }
183*2357e899Savl-llvm 
noteLocationAttribute(PatchLocation Attr)184*2357e899Savl-llvm void CompileUnit::noteLocationAttribute(PatchLocation Attr) {
185*2357e899Savl-llvm   LocationAttributes.emplace_back(Attr);
186*2357e899Savl-llvm }
187*2357e899Savl-llvm 
addNamespaceAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name)188*2357e899Savl-llvm void CompileUnit::addNamespaceAccelerator(const DIE *Die,
189*2357e899Savl-llvm                                           DwarfStringPoolEntryRef Name) {
190*2357e899Savl-llvm   Namespaces.emplace_back(Name, Die);
191*2357e899Savl-llvm }
192*2357e899Savl-llvm 
addObjCAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool SkipPubSection)193*2357e899Savl-llvm void CompileUnit::addObjCAccelerator(const DIE *Die,
194*2357e899Savl-llvm                                      DwarfStringPoolEntryRef Name,
195*2357e899Savl-llvm                                      bool SkipPubSection) {
196*2357e899Savl-llvm   ObjC.emplace_back(Name, Die, SkipPubSection);
197*2357e899Savl-llvm }
198*2357e899Savl-llvm 
addNameAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool SkipPubSection)199*2357e899Savl-llvm void CompileUnit::addNameAccelerator(const DIE *Die,
200*2357e899Savl-llvm                                      DwarfStringPoolEntryRef Name,
201*2357e899Savl-llvm                                      bool SkipPubSection) {
202*2357e899Savl-llvm   Pubnames.emplace_back(Name, Die, SkipPubSection);
203*2357e899Savl-llvm }
204*2357e899Savl-llvm 
addTypeAccelerator(const DIE * Die,DwarfStringPoolEntryRef Name,bool ObjcClassImplementation,uint32_t QualifiedNameHash)205*2357e899Savl-llvm void CompileUnit::addTypeAccelerator(const DIE *Die,
206*2357e899Savl-llvm                                      DwarfStringPoolEntryRef Name,
207*2357e899Savl-llvm                                      bool ObjcClassImplementation,
208*2357e899Savl-llvm                                      uint32_t QualifiedNameHash) {
209*2357e899Savl-llvm   Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
210*2357e899Savl-llvm }
211*2357e899Savl-llvm 
212*2357e899Savl-llvm } // namespace llvm
213