xref: /llvm-project/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp (revision c4fbb6500a557fec592af8b9c398169591cdcc5d)
1c1ccf078SCarlos Alberto Enciso //===-- LVDWARFReader.cpp -------------------------------------------------===//
2c1ccf078SCarlos Alberto Enciso //
3c1ccf078SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c1ccf078SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information.
5c1ccf078SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c1ccf078SCarlos Alberto Enciso //
7c1ccf078SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
8c1ccf078SCarlos Alberto Enciso //
9c1ccf078SCarlos Alberto Enciso // This implements the LVDWARFReader class.
10c1ccf078SCarlos Alberto Enciso // It supports ELF, Mach-O and Wasm binary formats.
11c1ccf078SCarlos Alberto Enciso //
12c1ccf078SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
13c1ccf078SCarlos Alberto Enciso 
14c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h"
15c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/DIContext.h"
16c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
17c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
18c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
19c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
20c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
21c1ccf078SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
22c1ccf078SCarlos Alberto Enciso #include "llvm/Object/MachO.h"
23c1ccf078SCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h"
24c1ccf078SCarlos Alberto Enciso 
25c1ccf078SCarlos Alberto Enciso using namespace llvm;
26c1ccf078SCarlos Alberto Enciso using namespace llvm::object;
27c1ccf078SCarlos Alberto Enciso using namespace llvm::logicalview;
28c1ccf078SCarlos Alberto Enciso 
29c1ccf078SCarlos Alberto Enciso #define DEBUG_TYPE "DWARFReader"
30c1ccf078SCarlos Alberto Enciso 
31c1ccf078SCarlos Alberto Enciso LVElement *LVDWARFReader::createElement(dwarf::Tag Tag) {
32c1ccf078SCarlos Alberto Enciso   CurrentScope = nullptr;
33c1ccf078SCarlos Alberto Enciso   CurrentSymbol = nullptr;
34c1ccf078SCarlos Alberto Enciso   CurrentType = nullptr;
35c1ccf078SCarlos Alberto Enciso   CurrentRanges.clear();
36c1ccf078SCarlos Alberto Enciso 
37c1ccf078SCarlos Alberto Enciso   if (!options().getPrintSymbols()) {
38c1ccf078SCarlos Alberto Enciso     switch (Tag) {
39c1ccf078SCarlos Alberto Enciso     // As the command line options did not specify a request to print
40c1ccf078SCarlos Alberto Enciso     // logical symbols (--print=symbols or --print=all or --print=elements),
41c1ccf078SCarlos Alberto Enciso     // skip its creation.
42c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_formal_parameter:
43c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_unspecified_parameters:
44c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_member:
45c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_variable:
46c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_inheritance:
47c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_constant:
48c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_call_site_parameter:
49c1ccf078SCarlos Alberto Enciso     case dwarf::DW_TAG_GNU_call_site_parameter:
50c1ccf078SCarlos Alberto Enciso       return nullptr;
51c1ccf078SCarlos Alberto Enciso     default:
52c1ccf078SCarlos Alberto Enciso       break;
53c1ccf078SCarlos Alberto Enciso     }
54c1ccf078SCarlos Alberto Enciso   }
55c1ccf078SCarlos Alberto Enciso 
56c1ccf078SCarlos Alberto Enciso   switch (Tag) {
57c1ccf078SCarlos Alberto Enciso   // Types.
58c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_base_type:
59c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
60c1ccf078SCarlos Alberto Enciso     CurrentType->setIsBase();
61c1ccf078SCarlos Alberto Enciso     if (options().getAttributeBase())
62c1ccf078SCarlos Alberto Enciso       CurrentType->setIncludeInPrint();
63c1ccf078SCarlos Alberto Enciso     return CurrentType;
64c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_const_type:
65c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
66c1ccf078SCarlos Alberto Enciso     CurrentType->setIsConst();
67c1ccf078SCarlos Alberto Enciso     CurrentType->setName("const");
68c1ccf078SCarlos Alberto Enciso     return CurrentType;
69c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_enumerator:
70c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeEnumerator();
71c1ccf078SCarlos Alberto Enciso     return CurrentType;
72c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_imported_declaration:
73c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeImport();
74c1ccf078SCarlos Alberto Enciso     CurrentType->setIsImportDeclaration();
75c1ccf078SCarlos Alberto Enciso     return CurrentType;
76c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_imported_module:
77c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeImport();
78c1ccf078SCarlos Alberto Enciso     CurrentType->setIsImportModule();
79c1ccf078SCarlos Alberto Enciso     return CurrentType;
80c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_pointer_type:
81c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
82c1ccf078SCarlos Alberto Enciso     CurrentType->setIsPointer();
83c1ccf078SCarlos Alberto Enciso     CurrentType->setName("*");
84c1ccf078SCarlos Alberto Enciso     return CurrentType;
85c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_ptr_to_member_type:
86c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
87c1ccf078SCarlos Alberto Enciso     CurrentType->setIsPointerMember();
88c1ccf078SCarlos Alberto Enciso     CurrentType->setName("*");
89c1ccf078SCarlos Alberto Enciso     return CurrentType;
90c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_reference_type:
91c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
92c1ccf078SCarlos Alberto Enciso     CurrentType->setIsReference();
93c1ccf078SCarlos Alberto Enciso     CurrentType->setName("&");
94c1ccf078SCarlos Alberto Enciso     return CurrentType;
95c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_restrict_type:
96c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
97c1ccf078SCarlos Alberto Enciso     CurrentType->setIsRestrict();
98c1ccf078SCarlos Alberto Enciso     CurrentType->setName("restrict");
99c1ccf078SCarlos Alberto Enciso     return CurrentType;
100c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_rvalue_reference_type:
101c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
102c1ccf078SCarlos Alberto Enciso     CurrentType->setIsRvalueReference();
103c1ccf078SCarlos Alberto Enciso     CurrentType->setName("&&");
104c1ccf078SCarlos Alberto Enciso     return CurrentType;
105c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_subrange_type:
106c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeSubrange();
107c1ccf078SCarlos Alberto Enciso     return CurrentType;
108c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_template_value_parameter:
109c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeParam();
110c1ccf078SCarlos Alberto Enciso     CurrentType->setIsTemplateValueParam();
111c1ccf078SCarlos Alberto Enciso     return CurrentType;
112c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_template_type_parameter:
113c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeParam();
114c1ccf078SCarlos Alberto Enciso     CurrentType->setIsTemplateTypeParam();
115c1ccf078SCarlos Alberto Enciso     return CurrentType;
116c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_GNU_template_template_param:
117c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeParam();
118c1ccf078SCarlos Alberto Enciso     CurrentType->setIsTemplateTemplateParam();
119c1ccf078SCarlos Alberto Enciso     return CurrentType;
120c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_typedef:
121c1ccf078SCarlos Alberto Enciso     CurrentType = createTypeDefinition();
122c1ccf078SCarlos Alberto Enciso     return CurrentType;
123c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_unspecified_type:
124c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
125c1ccf078SCarlos Alberto Enciso     CurrentType->setIsUnspecified();
126c1ccf078SCarlos Alberto Enciso     return CurrentType;
127c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_volatile_type:
128c1ccf078SCarlos Alberto Enciso     CurrentType = createType();
129c1ccf078SCarlos Alberto Enciso     CurrentType->setIsVolatile();
130c1ccf078SCarlos Alberto Enciso     CurrentType->setName("volatile");
131c1ccf078SCarlos Alberto Enciso     return CurrentType;
132c1ccf078SCarlos Alberto Enciso 
133c1ccf078SCarlos Alberto Enciso   // Symbols.
134c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_formal_parameter:
135c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
136c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsParameter();
137c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
138c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_unspecified_parameters:
139c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
140c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsUnspecified();
141c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setName("...");
142c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
143c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_member:
144c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
145c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsMember();
146c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
147c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_variable:
148c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
149c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsVariable();
150c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
151c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_inheritance:
152c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
153c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsInheritance();
154c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
155c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_call_site_parameter:
156c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_GNU_call_site_parameter:
157c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
158c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsCallSiteParameter();
159c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
160c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_constant:
161c1ccf078SCarlos Alberto Enciso     CurrentSymbol = createSymbol();
162c1ccf078SCarlos Alberto Enciso     CurrentSymbol->setIsConstant();
163c1ccf078SCarlos Alberto Enciso     return CurrentSymbol;
164c1ccf078SCarlos Alberto Enciso 
165c1ccf078SCarlos Alberto Enciso   // Scopes.
166c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_catch_block:
167c1ccf078SCarlos Alberto Enciso     CurrentScope = createScope();
168c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsCatchBlock();
169c1ccf078SCarlos Alberto Enciso     return CurrentScope;
170c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_lexical_block:
171c1ccf078SCarlos Alberto Enciso     CurrentScope = createScope();
172c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsLexicalBlock();
173c1ccf078SCarlos Alberto Enciso     return CurrentScope;
174c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_try_block:
175c1ccf078SCarlos Alberto Enciso     CurrentScope = createScope();
176c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsTryBlock();
177c1ccf078SCarlos Alberto Enciso     return CurrentScope;
178c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_compile_unit:
179c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_skeleton_unit:
180c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeCompileUnit();
181c1ccf078SCarlos Alberto Enciso     CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope);
182c1ccf078SCarlos Alberto Enciso     return CurrentScope;
183c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_inlined_subroutine:
184c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunctionInlined();
185c1ccf078SCarlos Alberto Enciso     return CurrentScope;
186c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_namespace:
187c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeNamespace();
188c1ccf078SCarlos Alberto Enciso     return CurrentScope;
189c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_template_alias:
190c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeAlias();
191c1ccf078SCarlos Alberto Enciso     return CurrentScope;
192c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_array_type:
193c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeArray();
194c1ccf078SCarlos Alberto Enciso     return CurrentScope;
195c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_call_site:
196c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_GNU_call_site:
197c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunction();
198c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsCallSite();
199c1ccf078SCarlos Alberto Enciso     return CurrentScope;
200c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_entry_point:
201c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunction();
202c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsEntryPoint();
203c1ccf078SCarlos Alberto Enciso     return CurrentScope;
204c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_subprogram:
205c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunction();
206c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsSubprogram();
207c1ccf078SCarlos Alberto Enciso     return CurrentScope;
208c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_subroutine_type:
209c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunctionType();
210c1ccf078SCarlos Alberto Enciso     return CurrentScope;
211c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_label:
212c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFunction();
213c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsLabel();
214c1ccf078SCarlos Alberto Enciso     return CurrentScope;
215c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_class_type:
216c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeAggregate();
217c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsClass();
218c1ccf078SCarlos Alberto Enciso     return CurrentScope;
219c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_structure_type:
220c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeAggregate();
221c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsStructure();
222c1ccf078SCarlos Alberto Enciso     return CurrentScope;
223c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_union_type:
224c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeAggregate();
225c1ccf078SCarlos Alberto Enciso     CurrentScope->setIsUnion();
226c1ccf078SCarlos Alberto Enciso     return CurrentScope;
227c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_enumeration_type:
228c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeEnumeration();
229c1ccf078SCarlos Alberto Enciso     return CurrentScope;
230c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_GNU_formal_parameter_pack:
231c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeFormalPack();
232c1ccf078SCarlos Alberto Enciso     return CurrentScope;
233c1ccf078SCarlos Alberto Enciso   case dwarf::DW_TAG_GNU_template_parameter_pack:
234c1ccf078SCarlos Alberto Enciso     CurrentScope = createScopeTemplatePack();
235c1ccf078SCarlos Alberto Enciso     return CurrentScope;
236c1ccf078SCarlos Alberto Enciso   default:
237c1ccf078SCarlos Alberto Enciso     // Collect TAGs not implemented.
238c1ccf078SCarlos Alberto Enciso     if (options().getInternalTag() && Tag)
239c1ccf078SCarlos Alberto Enciso       CompileUnit->addDebugTag(Tag, CurrentOffset);
240c1ccf078SCarlos Alberto Enciso     break;
241c1ccf078SCarlos Alberto Enciso   }
242c1ccf078SCarlos Alberto Enciso   return nullptr;
243c1ccf078SCarlos Alberto Enciso }
244c1ccf078SCarlos Alberto Enciso 
245c1ccf078SCarlos Alberto Enciso void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
246c1ccf078SCarlos Alberto Enciso                                         LVOffset *OffsetPtr,
247c1ccf078SCarlos Alberto Enciso                                         const AttributeSpec &AttrSpec) {
248c1ccf078SCarlos Alberto Enciso   uint64_t OffsetOnEntry = *OffsetPtr;
249c1ccf078SCarlos Alberto Enciso   DWARFUnit *U = Die.getDwarfUnit();
250c1ccf078SCarlos Alberto Enciso   const DWARFFormValue &FormValue =
251c1ccf078SCarlos Alberto Enciso       DWARFFormValue::createFromUnit(AttrSpec.Form, U, OffsetPtr);
252c1ccf078SCarlos Alberto Enciso 
253c1ccf078SCarlos Alberto Enciso   // We are processing .debug_info section, implicit_const attribute
254c1ccf078SCarlos Alberto Enciso   // values are not really stored here, but in .debug_abbrev section.
255c1ccf078SCarlos Alberto Enciso   auto GetAsUnsignedConstant = [&]() -> int64_t {
256fb376595SCarlos Alberto Enciso     if (AttrSpec.isImplicitConst())
257fb376595SCarlos Alberto Enciso       return AttrSpec.getImplicitConstValue();
258fb376595SCarlos Alberto Enciso     if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
259fb376595SCarlos Alberto Enciso       return *Val;
260fb376595SCarlos Alberto Enciso     return 0;
261c1ccf078SCarlos Alberto Enciso   };
262c1ccf078SCarlos Alberto Enciso 
263c1ccf078SCarlos Alberto Enciso   auto GetFlag = [](const DWARFFormValue &FormValue) -> bool {
264c1ccf078SCarlos Alberto Enciso     return FormValue.isFormClass(DWARFFormValue::FC_Flag);
265c1ccf078SCarlos Alberto Enciso   };
266c1ccf078SCarlos Alberto Enciso 
267fb376595SCarlos Alberto Enciso   auto GetBoundValue = [&AttrSpec](const DWARFFormValue &FormValue) -> int64_t {
268c1ccf078SCarlos Alberto Enciso     switch (FormValue.getForm()) {
269c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref_addr:
270c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref1:
271c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref2:
272c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref4:
273c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref8:
274c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref_udata:
275c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref_sig8:
276c1ccf078SCarlos Alberto Enciso       return *FormValue.getAsReferenceUVal();
277c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_data1:
278c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_flag:
279c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_data2:
280c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_data4:
281c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_data8:
282c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_udata:
283c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref_sup4:
284c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_ref_sup8:
285c1ccf078SCarlos Alberto Enciso       return *FormValue.getAsUnsignedConstant();
286c1ccf078SCarlos Alberto Enciso     case dwarf::DW_FORM_sdata:
287c1ccf078SCarlos Alberto Enciso       return *FormValue.getAsSignedConstant();
288fb376595SCarlos Alberto Enciso     case dwarf::DW_FORM_implicit_const:
289fb376595SCarlos Alberto Enciso       return AttrSpec.getImplicitConstValue();
290c1ccf078SCarlos Alberto Enciso     default:
291c1ccf078SCarlos Alberto Enciso       return 0;
292c1ccf078SCarlos Alberto Enciso     }
293c1ccf078SCarlos Alberto Enciso   };
294c1ccf078SCarlos Alberto Enciso 
295c1ccf078SCarlos Alberto Enciso   LLVM_DEBUG({
296c1ccf078SCarlos Alberto Enciso     dbgs() << "     " << hexValue(OffsetOnEntry)
297c1ccf078SCarlos Alberto Enciso            << formatv(" {0}", AttrSpec.Attr) << "\n";
298c1ccf078SCarlos Alberto Enciso   });
299c1ccf078SCarlos Alberto Enciso 
300c1ccf078SCarlos Alberto Enciso   switch (AttrSpec.Attr) {
301c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_accessibility:
302fb376595SCarlos Alberto Enciso     CurrentElement->setAccessibilityCode(GetAsUnsignedConstant());
303c1ccf078SCarlos Alberto Enciso     break;
304c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_artificial:
305c1ccf078SCarlos Alberto Enciso     CurrentElement->setIsArtificial();
306c1ccf078SCarlos Alberto Enciso     break;
307c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_bit_size:
308fb376595SCarlos Alberto Enciso     CurrentElement->setBitSize(GetAsUnsignedConstant());
309c1ccf078SCarlos Alberto Enciso     break;
310c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_call_file:
3115e7662efSCarlos Alberto Enciso     CurrentElement->setCallFilenameIndex(IncrementFileIndex
312c1ccf078SCarlos Alberto Enciso                                              ? GetAsUnsignedConstant() + 1
313c1ccf078SCarlos Alberto Enciso                                              : GetAsUnsignedConstant());
314c1ccf078SCarlos Alberto Enciso     break;
3155e7662efSCarlos Alberto Enciso   case dwarf::DW_AT_call_line:
3165e7662efSCarlos Alberto Enciso     CurrentElement->setCallLineNumber(GetAsUnsignedConstant());
3175e7662efSCarlos Alberto Enciso     break;
318c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_comp_dir:
319c1ccf078SCarlos Alberto Enciso     CompileUnit->setCompilationDirectory(dwarf::toStringRef(FormValue));
320c1ccf078SCarlos Alberto Enciso     break;
321c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_const_value:
322c1ccf078SCarlos Alberto Enciso     if (FormValue.isFormClass(DWARFFormValue::FC_Block)) {
323c1ccf078SCarlos Alberto Enciso       ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
324c1ccf078SCarlos Alberto Enciso       // Store the expression as a hexadecimal string.
325c1ccf078SCarlos Alberto Enciso       CurrentElement->setValue(
326c1ccf078SCarlos Alberto Enciso           llvm::toHex(llvm::toStringRef(Expr), /*LowerCase=*/true));
327c1ccf078SCarlos Alberto Enciso     } else if (FormValue.isFormClass(DWARFFormValue::FC_Constant)) {
328c1ccf078SCarlos Alberto Enciso       // In the case of negative values, generate the string representation
329c1ccf078SCarlos Alberto Enciso       // for a positive value prefixed with the negative sign.
330c1ccf078SCarlos Alberto Enciso       if (FormValue.getForm() == dwarf::DW_FORM_sdata) {
331c1ccf078SCarlos Alberto Enciso         std::stringstream Stream;
332c1ccf078SCarlos Alberto Enciso         int64_t Value = *FormValue.getAsSignedConstant();
333c1ccf078SCarlos Alberto Enciso         if (Value < 0) {
334c1ccf078SCarlos Alberto Enciso           Stream << "-";
335c1ccf078SCarlos Alberto Enciso           Value = std::abs(Value);
336c1ccf078SCarlos Alberto Enciso         }
337c1ccf078SCarlos Alberto Enciso         Stream << hexString(Value, 2);
338c1ccf078SCarlos Alberto Enciso         CurrentElement->setValue(Stream.str());
339c1ccf078SCarlos Alberto Enciso       } else
340fb376595SCarlos Alberto Enciso         CurrentElement->setValue(hexString(GetAsUnsignedConstant(), 2));
341c1ccf078SCarlos Alberto Enciso     } else
342c1ccf078SCarlos Alberto Enciso       CurrentElement->setValue(dwarf::toStringRef(FormValue));
343c1ccf078SCarlos Alberto Enciso     break;
344c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_count:
345fb376595SCarlos Alberto Enciso     CurrentElement->setCount(GetAsUnsignedConstant());
346c1ccf078SCarlos Alberto Enciso     break;
347c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_decl_line:
348c1ccf078SCarlos Alberto Enciso     CurrentElement->setLineNumber(GetAsUnsignedConstant());
349c1ccf078SCarlos Alberto Enciso     break;
350c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_decl_file:
351c1ccf078SCarlos Alberto Enciso     CurrentElement->setFilenameIndex(IncrementFileIndex
352c1ccf078SCarlos Alberto Enciso                                          ? GetAsUnsignedConstant() + 1
353c1ccf078SCarlos Alberto Enciso                                          : GetAsUnsignedConstant());
354c1ccf078SCarlos Alberto Enciso     break;
355c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_enum_class:
356c1ccf078SCarlos Alberto Enciso     if (GetFlag(FormValue))
357c1ccf078SCarlos Alberto Enciso       CurrentElement->setIsEnumClass();
358c1ccf078SCarlos Alberto Enciso     break;
359c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_external:
360c1ccf078SCarlos Alberto Enciso     if (GetFlag(FormValue))
361c1ccf078SCarlos Alberto Enciso       CurrentElement->setIsExternal();
362c1ccf078SCarlos Alberto Enciso     break;
363c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_GNU_discriminator:
364fb376595SCarlos Alberto Enciso     CurrentElement->setDiscriminator(GetAsUnsignedConstant());
365c1ccf078SCarlos Alberto Enciso     break;
366c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_inline:
367fb376595SCarlos Alberto Enciso     CurrentElement->setInlineCode(GetAsUnsignedConstant());
368c1ccf078SCarlos Alberto Enciso     break;
369c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_lower_bound:
370c1ccf078SCarlos Alberto Enciso     CurrentElement->setLowerBound(GetBoundValue(FormValue));
371c1ccf078SCarlos Alberto Enciso     break;
372c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_name:
373c1ccf078SCarlos Alberto Enciso     CurrentElement->setName(dwarf::toStringRef(FormValue));
374c1ccf078SCarlos Alberto Enciso     break;
375*c4fbb650SCarlos Alberto Enciso   case dwarf::DW_AT_GNU_template_name:
376*c4fbb650SCarlos Alberto Enciso     CurrentElement->setValue(dwarf::toStringRef(FormValue));
377*c4fbb650SCarlos Alberto Enciso     break;
378c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_linkage_name:
379c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_MIPS_linkage_name:
380c1ccf078SCarlos Alberto Enciso     CurrentElement->setLinkageName(dwarf::toStringRef(FormValue));
381c1ccf078SCarlos Alberto Enciso     break;
382c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_producer:
383c1ccf078SCarlos Alberto Enciso     if (options().getAttributeProducer())
384c1ccf078SCarlos Alberto Enciso       CurrentElement->setProducer(dwarf::toStringRef(FormValue));
385c1ccf078SCarlos Alberto Enciso     break;
386c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_upper_bound:
387c1ccf078SCarlos Alberto Enciso     CurrentElement->setUpperBound(GetBoundValue(FormValue));
388c1ccf078SCarlos Alberto Enciso     break;
389c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_virtuality:
390fb376595SCarlos Alberto Enciso     CurrentElement->setVirtualityCode(GetAsUnsignedConstant());
391c1ccf078SCarlos Alberto Enciso     break;
392c1ccf078SCarlos Alberto Enciso 
393c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_abstract_origin:
394c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_call_origin:
395c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_extension:
396c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_import:
397c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_specification:
398c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_type:
399c1ccf078SCarlos Alberto Enciso     updateReference(AttrSpec.Attr, FormValue);
400c1ccf078SCarlos Alberto Enciso     break;
401c1ccf078SCarlos Alberto Enciso 
402c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_low_pc:
403c1ccf078SCarlos Alberto Enciso     if (options().getGeneralCollectRanges()) {
404c1ccf078SCarlos Alberto Enciso       FoundLowPC = true;
405c1ccf078SCarlos Alberto Enciso       // For toolchains that support the removal of unused code, the linker
406c1ccf078SCarlos Alberto Enciso       // marks functions that have been removed, by setting the value for the
407c1ccf078SCarlos Alberto Enciso       // low_pc to the max address.
408c1ccf078SCarlos Alberto Enciso       if (std::optional<uint64_t> Value = FormValue.getAsAddress()) {
409c1ccf078SCarlos Alberto Enciso         CurrentLowPC = *Value;
410c1ccf078SCarlos Alberto Enciso       } else {
411c1ccf078SCarlos Alberto Enciso         uint64_t UValue = FormValue.getRawUValue();
412c1ccf078SCarlos Alberto Enciso         if (U->getAddrOffsetSectionItem(UValue)) {
413c1ccf078SCarlos Alberto Enciso           CurrentLowPC = *FormValue.getAsAddress();
414c1ccf078SCarlos Alberto Enciso         } else {
415c1ccf078SCarlos Alberto Enciso           FoundLowPC = false;
416c1ccf078SCarlos Alberto Enciso           // We are dealing with an index into the .debug_addr section.
417c1ccf078SCarlos Alberto Enciso           LLVM_DEBUG({
418c1ccf078SCarlos Alberto Enciso             dbgs() << format("indexed (%8.8x) address = ", (uint32_t)UValue);
419c1ccf078SCarlos Alberto Enciso           });
420c1ccf078SCarlos Alberto Enciso         }
421c1ccf078SCarlos Alberto Enciso       }
422c1ccf078SCarlos Alberto Enciso       if (FoundLowPC) {
423c1ccf078SCarlos Alberto Enciso         if (CurrentLowPC == MaxAddress)
424c1ccf078SCarlos Alberto Enciso           CurrentElement->setIsDiscarded();
425c1ccf078SCarlos Alberto Enciso         // Consider the case of WebAssembly.
426c1ccf078SCarlos Alberto Enciso         CurrentLowPC += WasmCodeSectionOffset;
427c1ccf078SCarlos Alberto Enciso         if (CurrentElement->isCompileUnit())
428c1ccf078SCarlos Alberto Enciso           setCUBaseAddress(CurrentLowPC);
429c1ccf078SCarlos Alberto Enciso       }
430c1ccf078SCarlos Alberto Enciso     }
431c1ccf078SCarlos Alberto Enciso     break;
432c1ccf078SCarlos Alberto Enciso 
433c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_high_pc:
434c1ccf078SCarlos Alberto Enciso     if (options().getGeneralCollectRanges()) {
435c1ccf078SCarlos Alberto Enciso       FoundHighPC = true;
436c1ccf078SCarlos Alberto Enciso       if (std::optional<uint64_t> Address = FormValue.getAsAddress())
437c1ccf078SCarlos Alberto Enciso         // High PC is an address.
438c1ccf078SCarlos Alberto Enciso         CurrentHighPC = *Address;
439c1ccf078SCarlos Alberto Enciso       if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant())
440c1ccf078SCarlos Alberto Enciso         // High PC is an offset from LowPC.
441c1ccf078SCarlos Alberto Enciso         // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as
442c1ccf078SCarlos Alberto Enciso         // the CurrentLowPC has already that offset added. Basically, use the
443c1ccf078SCarlos Alberto Enciso         // original DW_AT_loc_pc value.
444c1ccf078SCarlos Alberto Enciso         CurrentHighPC =
445c1ccf078SCarlos Alberto Enciso             (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) +
446c1ccf078SCarlos Alberto Enciso             *Offset;
447c1ccf078SCarlos Alberto Enciso       // Store the real upper limit for the address range.
448c1ccf078SCarlos Alberto Enciso       if (UpdateHighAddress && CurrentHighPC > 0)
449c1ccf078SCarlos Alberto Enciso         --CurrentHighPC;
450c1ccf078SCarlos Alberto Enciso       // Consider the case of WebAssembly.
451c1ccf078SCarlos Alberto Enciso       CurrentHighPC += WasmCodeSectionOffset;
452c1ccf078SCarlos Alberto Enciso       if (CurrentElement->isCompileUnit())
453c1ccf078SCarlos Alberto Enciso         setCUHighAddress(CurrentHighPC);
454c1ccf078SCarlos Alberto Enciso     }
455c1ccf078SCarlos Alberto Enciso     break;
456c1ccf078SCarlos Alberto Enciso 
457c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_ranges:
458c1ccf078SCarlos Alberto Enciso     if (RangesDataAvailable && options().getGeneralCollectRanges()) {
459c1ccf078SCarlos Alberto Enciso       auto GetRanges = [](const DWARFFormValue &FormValue,
460c1ccf078SCarlos Alberto Enciso                           DWARFUnit *U) -> Expected<DWARFAddressRangesVector> {
461c1ccf078SCarlos Alberto Enciso         if (FormValue.getForm() == dwarf::DW_FORM_rnglistx)
462c1ccf078SCarlos Alberto Enciso           return U->findRnglistFromIndex(*FormValue.getAsSectionOffset());
463c1ccf078SCarlos Alberto Enciso         return U->findRnglistFromOffset(*FormValue.getAsSectionOffset());
464c1ccf078SCarlos Alberto Enciso       };
465c1ccf078SCarlos Alberto Enciso       Expected<DWARFAddressRangesVector> RangesOrError =
466c1ccf078SCarlos Alberto Enciso           GetRanges(FormValue, U);
467c1ccf078SCarlos Alberto Enciso       if (!RangesOrError) {
468c1ccf078SCarlos Alberto Enciso         LLVM_DEBUG({
469c1ccf078SCarlos Alberto Enciso           std::string TheError(toString(RangesOrError.takeError()));
470c1ccf078SCarlos Alberto Enciso           dbgs() << format("error decoding address ranges = ",
471c1ccf078SCarlos Alberto Enciso                            TheError.c_str());
472c1ccf078SCarlos Alberto Enciso         });
473c1ccf078SCarlos Alberto Enciso         consumeError(RangesOrError.takeError());
474c1ccf078SCarlos Alberto Enciso         break;
475c1ccf078SCarlos Alberto Enciso       }
476c1ccf078SCarlos Alberto Enciso       // The address ranges are absolute. There is no need to add any addend.
477c1ccf078SCarlos Alberto Enciso       DWARFAddressRangesVector Ranges = RangesOrError.get();
478c1ccf078SCarlos Alberto Enciso       for (DWARFAddressRange &Range : Ranges) {
479c1ccf078SCarlos Alberto Enciso         // This seems to be a tombstone for empty ranges.
480c1ccf078SCarlos Alberto Enciso         if (Range.LowPC == Range.HighPC)
481c1ccf078SCarlos Alberto Enciso           continue;
482c1ccf078SCarlos Alberto Enciso         // Store the real upper limit for the address range.
483c1ccf078SCarlos Alberto Enciso         if (UpdateHighAddress && Range.HighPC > 0)
484c1ccf078SCarlos Alberto Enciso           --Range.HighPC;
485c1ccf078SCarlos Alberto Enciso         // Consider the case of WebAssembly.
486c1ccf078SCarlos Alberto Enciso         Range.LowPC += WasmCodeSectionOffset;
487c1ccf078SCarlos Alberto Enciso         Range.HighPC += WasmCodeSectionOffset;
488c1ccf078SCarlos Alberto Enciso         // Add the pair of addresses.
489c1ccf078SCarlos Alberto Enciso         CurrentScope->addObject(Range.LowPC, Range.HighPC);
490c1ccf078SCarlos Alberto Enciso         // If the scope is the CU, do not update the ranges set.
491c1ccf078SCarlos Alberto Enciso         if (!CurrentElement->isCompileUnit())
492c1ccf078SCarlos Alberto Enciso           CurrentRanges.emplace_back(Range.LowPC, Range.HighPC);
493c1ccf078SCarlos Alberto Enciso       }
494c1ccf078SCarlos Alberto Enciso     }
495c1ccf078SCarlos Alberto Enciso     break;
496c1ccf078SCarlos Alberto Enciso 
497c1ccf078SCarlos Alberto Enciso   // Get the location list for the symbol.
498c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_data_member_location:
499c1ccf078SCarlos Alberto Enciso     if (options().getAttributeAnyLocation())
500c1ccf078SCarlos Alberto Enciso       processLocationMember(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);
501c1ccf078SCarlos Alberto Enciso     break;
502c1ccf078SCarlos Alberto Enciso 
503c1ccf078SCarlos Alberto Enciso   // Get the location list for the symbol.
504c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_location:
505c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_string_length:
506c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_use_location:
507c1ccf078SCarlos Alberto Enciso     if (options().getAttributeAnyLocation() && CurrentSymbol)
508c1ccf078SCarlos Alberto Enciso       processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry);
509c1ccf078SCarlos Alberto Enciso     break;
510c1ccf078SCarlos Alberto Enciso 
511c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_call_data_value:
512c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_call_value:
513c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_GNU_call_site_data_value:
514c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_GNU_call_site_value:
515c1ccf078SCarlos Alberto Enciso     if (options().getAttributeAnyLocation() && CurrentSymbol)
516c1ccf078SCarlos Alberto Enciso       processLocationList(AttrSpec.Attr, FormValue, Die, OffsetOnEntry,
517c1ccf078SCarlos Alberto Enciso                           /*CallSiteLocation=*/true);
518c1ccf078SCarlos Alberto Enciso     break;
519c1ccf078SCarlos Alberto Enciso 
520c1ccf078SCarlos Alberto Enciso   default:
521c1ccf078SCarlos Alberto Enciso     break;
522c1ccf078SCarlos Alberto Enciso   }
523c1ccf078SCarlos Alberto Enciso }
524c1ccf078SCarlos Alberto Enciso 
525c1ccf078SCarlos Alberto Enciso LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent,
526c1ccf078SCarlos Alberto Enciso                                       DWARFDie &SkeletonDie) {
527c1ccf078SCarlos Alberto Enciso   // If the input DIE corresponds to the compile unit, it can be:
528c1ccf078SCarlos Alberto Enciso   // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty).
529c1ccf078SCarlos Alberto Enciso   // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE
530c1ccf078SCarlos Alberto Enciso   //    for the skeleton DWARF. Process both DIEs.
531c1ccf078SCarlos Alberto Enciso   const DWARFDie &DIE = SkeletonDie.isValid() ? SkeletonDie : InputDIE;
532c1ccf078SCarlos Alberto Enciso   DWARFDataExtractor DebugInfoData =
533c1ccf078SCarlos Alberto Enciso       DIE.getDwarfUnit()->getDebugInfoExtractor();
534c1ccf078SCarlos Alberto Enciso   LVOffset Offset = DIE.getOffset();
535c1ccf078SCarlos Alberto Enciso 
536c1ccf078SCarlos Alberto Enciso   // Reset values for the current DIE.
537c1ccf078SCarlos Alberto Enciso   CurrentLowPC = 0;
538c1ccf078SCarlos Alberto Enciso   CurrentHighPC = 0;
539c1ccf078SCarlos Alberto Enciso   CurrentOffset = Offset;
540c1ccf078SCarlos Alberto Enciso   CurrentEndOffset = 0;
541c1ccf078SCarlos Alberto Enciso   FoundLowPC = false;
542c1ccf078SCarlos Alberto Enciso   FoundHighPC = false;
543c1ccf078SCarlos Alberto Enciso 
544c1ccf078SCarlos Alberto Enciso   // Process supported attributes.
545c1ccf078SCarlos Alberto Enciso   if (DebugInfoData.isValidOffset(Offset)) {
546c1ccf078SCarlos Alberto Enciso 
547c1ccf078SCarlos Alberto Enciso     LLVM_DEBUG({
548c1ccf078SCarlos Alberto Enciso       dbgs() << "DIE: " << hexValue(Offset) << formatv(" {0}", DIE.getTag())
549c1ccf078SCarlos Alberto Enciso              << "\n";
550c1ccf078SCarlos Alberto Enciso     });
551c1ccf078SCarlos Alberto Enciso 
552c1ccf078SCarlos Alberto Enciso     // Create the logical view element for the current DIE.
553c1ccf078SCarlos Alberto Enciso     dwarf::Tag Tag = DIE.getTag();
554c1ccf078SCarlos Alberto Enciso     CurrentElement = createElement(Tag);
555c1ccf078SCarlos Alberto Enciso     if (!CurrentElement)
556c1ccf078SCarlos Alberto Enciso       return CurrentScope;
557c1ccf078SCarlos Alberto Enciso 
558c1ccf078SCarlos Alberto Enciso     CurrentElement->setTag(Tag);
559c1ccf078SCarlos Alberto Enciso     CurrentElement->setOffset(Offset);
560c1ccf078SCarlos Alberto Enciso 
561c1ccf078SCarlos Alberto Enciso     if (options().getAttributeAnySource() && CurrentElement->isCompileUnit())
562c1ccf078SCarlos Alberto Enciso       addCompileUnitOffset(Offset,
563c1ccf078SCarlos Alberto Enciso                            static_cast<LVScopeCompileUnit *>(CurrentElement));
564c1ccf078SCarlos Alberto Enciso 
565c1ccf078SCarlos Alberto Enciso     // Insert the newly created element into the element symbol table. If the
566c1ccf078SCarlos Alberto Enciso     // element is in the list, it means there are previously created elements
567c1ccf078SCarlos Alberto Enciso     // referencing this element.
568c1ccf078SCarlos Alberto Enciso     if (ElementTable.find(Offset) == ElementTable.end()) {
569c1ccf078SCarlos Alberto Enciso       // No previous references to this offset.
570c1ccf078SCarlos Alberto Enciso       ElementTable.emplace(std::piecewise_construct,
571c1ccf078SCarlos Alberto Enciso                            std::forward_as_tuple(Offset),
572c1ccf078SCarlos Alberto Enciso                            std::forward_as_tuple(CurrentElement));
573c1ccf078SCarlos Alberto Enciso     } else {
574c1ccf078SCarlos Alberto Enciso       // There are previous references to this element. We need to update the
575c1ccf078SCarlos Alberto Enciso       // element and all the references pointing to this element.
576c1ccf078SCarlos Alberto Enciso       LVElementEntry &Reference = ElementTable[Offset];
577c1ccf078SCarlos Alberto Enciso       Reference.Element = CurrentElement;
578c1ccf078SCarlos Alberto Enciso       // Traverse the element set and update the elements (backtracking).
579c1ccf078SCarlos Alberto Enciso       for (LVElement *Target : Reference.References)
580c1ccf078SCarlos Alberto Enciso         Target->setReference(CurrentElement);
581c1ccf078SCarlos Alberto Enciso       for (LVElement *Target : Reference.Types)
582c1ccf078SCarlos Alberto Enciso         Target->setType(CurrentElement);
583c1ccf078SCarlos Alberto Enciso       // Clear the pending elements.
584c1ccf078SCarlos Alberto Enciso       Reference.References.clear();
585c1ccf078SCarlos Alberto Enciso       Reference.Types.clear();
586c1ccf078SCarlos Alberto Enciso     }
587c1ccf078SCarlos Alberto Enciso 
588c1ccf078SCarlos Alberto Enciso     // Add the current element to its parent as there are attributes
589c1ccf078SCarlos Alberto Enciso     // (locations) that require the scope level.
590c1ccf078SCarlos Alberto Enciso     if (CurrentScope)
591c1ccf078SCarlos Alberto Enciso       Parent->addElement(CurrentScope);
592c1ccf078SCarlos Alberto Enciso     else if (CurrentSymbol)
593c1ccf078SCarlos Alberto Enciso       Parent->addElement(CurrentSymbol);
594c1ccf078SCarlos Alberto Enciso     else if (CurrentType)
595c1ccf078SCarlos Alberto Enciso       Parent->addElement(CurrentType);
596c1ccf078SCarlos Alberto Enciso 
597c1ccf078SCarlos Alberto Enciso     // Process the attributes for the given DIE.
598c1ccf078SCarlos Alberto Enciso     auto ProcessAttributes = [&](const DWARFDie &TheDIE,
599c1ccf078SCarlos Alberto Enciso                                  DWARFDataExtractor &DebugData) {
600c1ccf078SCarlos Alberto Enciso       CurrentEndOffset = Offset;
601c1ccf078SCarlos Alberto Enciso       uint32_t abbrCode = DebugData.getULEB128(&CurrentEndOffset);
602c1ccf078SCarlos Alberto Enciso       if (abbrCode) {
603c1ccf078SCarlos Alberto Enciso         if (const DWARFAbbreviationDeclaration *AbbrevDecl =
604c1ccf078SCarlos Alberto Enciso                 TheDIE.getAbbreviationDeclarationPtr())
605c1ccf078SCarlos Alberto Enciso           if (AbbrevDecl)
606c1ccf078SCarlos Alberto Enciso             for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
607c1ccf078SCarlos Alberto Enciso                  AbbrevDecl->attributes())
608c1ccf078SCarlos Alberto Enciso               processOneAttribute(TheDIE, &CurrentEndOffset, AttrSpec);
609c1ccf078SCarlos Alberto Enciso       }
610c1ccf078SCarlos Alberto Enciso     };
611c1ccf078SCarlos Alberto Enciso 
612c1ccf078SCarlos Alberto Enciso     ProcessAttributes(DIE, DebugInfoData);
613c1ccf078SCarlos Alberto Enciso 
614c1ccf078SCarlos Alberto Enciso     // If the input DIE is for a compile unit, process its attributes in
615c1ccf078SCarlos Alberto Enciso     // the case of split DWARF, to override any common attribute values.
616c1ccf078SCarlos Alberto Enciso     if (SkeletonDie.isValid()) {
617c1ccf078SCarlos Alberto Enciso       DWARFDataExtractor DebugInfoData =
618c1ccf078SCarlos Alberto Enciso           InputDIE.getDwarfUnit()->getDebugInfoExtractor();
619c1ccf078SCarlos Alberto Enciso       LVOffset Offset = InputDIE.getOffset();
620c1ccf078SCarlos Alberto Enciso       if (DebugInfoData.isValidOffset(Offset))
621c1ccf078SCarlos Alberto Enciso         ProcessAttributes(InputDIE, DebugInfoData);
622c1ccf078SCarlos Alberto Enciso     }
623c1ccf078SCarlos Alberto Enciso   }
624c1ccf078SCarlos Alberto Enciso 
625c1ccf078SCarlos Alberto Enciso   if (CurrentScope) {
626c1ccf078SCarlos Alberto Enciso     if (CurrentScope->getCanHaveRanges()) {
627c1ccf078SCarlos Alberto Enciso       // If the scope has ranges, they are already added to the scope.
628c1ccf078SCarlos Alberto Enciso       // Add any collected LowPC/HighPC values.
629c1ccf078SCarlos Alberto Enciso       bool IsCompileUnit = CurrentScope->getIsCompileUnit();
630c1ccf078SCarlos Alberto Enciso       if (FoundLowPC && FoundHighPC) {
631c1ccf078SCarlos Alberto Enciso         CurrentScope->addObject(CurrentLowPC, CurrentHighPC);
632c1ccf078SCarlos Alberto Enciso         if (!IsCompileUnit) {
633c1ccf078SCarlos Alberto Enciso           // If the scope is a function, add it to the public names.
634c1ccf078SCarlos Alberto Enciso           if ((options().getAttributePublics() ||
635c1ccf078SCarlos Alberto Enciso                options().getPrintAnyLine()) &&
636c1ccf078SCarlos Alberto Enciso               CurrentScope->getIsFunction() &&
637c1ccf078SCarlos Alberto Enciso               !CurrentScope->getIsInlinedFunction())
638c1ccf078SCarlos Alberto Enciso             CompileUnit->addPublicName(CurrentScope, CurrentLowPC,
639c1ccf078SCarlos Alberto Enciso                                        CurrentHighPC);
640c1ccf078SCarlos Alberto Enciso         }
641c1ccf078SCarlos Alberto Enciso       }
642c1ccf078SCarlos Alberto Enciso 
643c1ccf078SCarlos Alberto Enciso       // Look for scopes with ranges and no linkage name information that
644c1ccf078SCarlos Alberto Enciso       // are referencing another scopes via DW_AT_specification. They are
645c1ccf078SCarlos Alberto Enciso       // possible candidates for a comdat scope.
646c1ccf078SCarlos Alberto Enciso       if (CurrentScope->getHasRanges() &&
647c1ccf078SCarlos Alberto Enciso           !CurrentScope->getLinkageNameIndex() &&
648c1ccf078SCarlos Alberto Enciso           CurrentScope->getHasReferenceSpecification()) {
649c1ccf078SCarlos Alberto Enciso         // Get the linkage name in order to search for a possible comdat.
650c1ccf078SCarlos Alberto Enciso         std::optional<DWARFFormValue> LinkageDIE =
651c1ccf078SCarlos Alberto Enciso             DIE.findRecursively(dwarf::DW_AT_linkage_name);
652c1ccf078SCarlos Alberto Enciso         if (LinkageDIE.has_value()) {
653c1ccf078SCarlos Alberto Enciso           StringRef Name(dwarf::toStringRef(LinkageDIE));
654c1ccf078SCarlos Alberto Enciso           if (!Name.empty())
655c1ccf078SCarlos Alberto Enciso             CurrentScope->setLinkageName(Name);
656c1ccf078SCarlos Alberto Enciso         }
657c1ccf078SCarlos Alberto Enciso       }
658c1ccf078SCarlos Alberto Enciso 
659c1ccf078SCarlos Alberto Enciso       // If the current scope is in the 'LinkageNames' table, update its
660c1ccf078SCarlos Alberto Enciso       // logical scope. For other scopes, always we will assume the default
661c1ccf078SCarlos Alberto Enciso       // ".text" section index.
662c1ccf078SCarlos Alberto Enciso       LVSectionIndex SectionIndex = updateSymbolTable(CurrentScope);
663c1ccf078SCarlos Alberto Enciso       if (CurrentScope->getIsComdat())
664c1ccf078SCarlos Alberto Enciso         CompileUnit->setHasComdatScopes();
665c1ccf078SCarlos Alberto Enciso 
666c1ccf078SCarlos Alberto Enciso       // Update section index contained ranges.
667c1ccf078SCarlos Alberto Enciso       if (SectionIndex) {
668c1ccf078SCarlos Alberto Enciso         if (!CurrentRanges.empty()) {
669c1ccf078SCarlos Alberto Enciso           for (LVAddressRange &Range : CurrentRanges)
670c1ccf078SCarlos Alberto Enciso             addSectionRange(SectionIndex, CurrentScope, Range.first,
671c1ccf078SCarlos Alberto Enciso                             Range.second);
672c1ccf078SCarlos Alberto Enciso           CurrentRanges.clear();
673c1ccf078SCarlos Alberto Enciso         }
674c1ccf078SCarlos Alberto Enciso         // If the scope is the CU, do not update the ranges set.
675c1ccf078SCarlos Alberto Enciso         if (FoundLowPC && FoundHighPC && !IsCompileUnit) {
676c1ccf078SCarlos Alberto Enciso           addSectionRange(SectionIndex, CurrentScope, CurrentLowPC,
677c1ccf078SCarlos Alberto Enciso                           CurrentHighPC);
678c1ccf078SCarlos Alberto Enciso         }
679c1ccf078SCarlos Alberto Enciso       }
680c1ccf078SCarlos Alberto Enciso     }
681c1ccf078SCarlos Alberto Enciso     // Mark member functions.
682c1ccf078SCarlos Alberto Enciso     if (Parent->getIsAggregate())
683c1ccf078SCarlos Alberto Enciso       CurrentScope->setIsMember();
684c1ccf078SCarlos Alberto Enciso   }
685c1ccf078SCarlos Alberto Enciso 
686c1ccf078SCarlos Alberto Enciso   // Keep track of symbols with locations.
687c1ccf078SCarlos Alberto Enciso   if (options().getAttributeAnyLocation() && CurrentSymbol &&
688c1ccf078SCarlos Alberto Enciso       CurrentSymbol->getHasLocation())
689c1ccf078SCarlos Alberto Enciso     SymbolsWithLocations.push_back(CurrentSymbol);
690c1ccf078SCarlos Alberto Enciso 
691c1ccf078SCarlos Alberto Enciso   // If we have template parameters, mark the parent as template.
692c1ccf078SCarlos Alberto Enciso   if (CurrentType && CurrentType->getIsTemplateParam())
693c1ccf078SCarlos Alberto Enciso     Parent->setIsTemplate();
694c1ccf078SCarlos Alberto Enciso 
695c1ccf078SCarlos Alberto Enciso   return CurrentScope;
696c1ccf078SCarlos Alberto Enciso }
697c1ccf078SCarlos Alberto Enciso 
698c1ccf078SCarlos Alberto Enciso void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent,
699c1ccf078SCarlos Alberto Enciso                                            DWARFDie &SkeletonDie) {
700c1ccf078SCarlos Alberto Enciso   // Process the current DIE.
701c1ccf078SCarlos Alberto Enciso   LVScope *Scope = processOneDie(DIE, Parent, SkeletonDie);
702c1ccf078SCarlos Alberto Enciso   if (Scope) {
703c1ccf078SCarlos Alberto Enciso     LVOffset Lower = DIE.getOffset();
704c1ccf078SCarlos Alberto Enciso     LVOffset Upper = CurrentEndOffset;
705c1ccf078SCarlos Alberto Enciso     DWARFDie DummyDie;
706c1ccf078SCarlos Alberto Enciso     // Traverse the children chain.
707c1ccf078SCarlos Alberto Enciso     DWARFDie Child = DIE.getFirstChild();
708c1ccf078SCarlos Alberto Enciso     while (Child) {
709c1ccf078SCarlos Alberto Enciso       traverseDieAndChildren(Child, Scope, DummyDie);
710c1ccf078SCarlos Alberto Enciso       Upper = Child.getOffset();
711c1ccf078SCarlos Alberto Enciso       Child = Child.getSibling();
712c1ccf078SCarlos Alberto Enciso     }
713c1ccf078SCarlos Alberto Enciso     // Calculate contributions to the debug info section.
714c1ccf078SCarlos Alberto Enciso     if (options().getPrintSizes() && Upper)
715c1ccf078SCarlos Alberto Enciso       CompileUnit->addSize(Scope, Lower, Upper);
716c1ccf078SCarlos Alberto Enciso   }
717c1ccf078SCarlos Alberto Enciso }
718c1ccf078SCarlos Alberto Enciso 
719c1ccf078SCarlos Alberto Enciso void LVDWARFReader::processLocationGaps() {
720c1ccf078SCarlos Alberto Enciso   if (options().getAttributeAnyLocation())
721c1ccf078SCarlos Alberto Enciso     for (LVSymbol *Symbol : SymbolsWithLocations)
722c1ccf078SCarlos Alberto Enciso       Symbol->fillLocationGaps();
723c1ccf078SCarlos Alberto Enciso }
724c1ccf078SCarlos Alberto Enciso 
725c1ccf078SCarlos Alberto Enciso void LVDWARFReader::createLineAndFileRecords(
726c1ccf078SCarlos Alberto Enciso     const DWARFDebugLine::LineTable *Lines) {
727c1ccf078SCarlos Alberto Enciso   if (!Lines)
728c1ccf078SCarlos Alberto Enciso     return;
729c1ccf078SCarlos Alberto Enciso 
730c1ccf078SCarlos Alberto Enciso   // Get the source filenames.
731c1ccf078SCarlos Alberto Enciso   if (!Lines->Prologue.FileNames.empty())
732c1ccf078SCarlos Alberto Enciso     for (const DWARFDebugLine::FileNameEntry &Entry :
733c1ccf078SCarlos Alberto Enciso          Lines->Prologue.FileNames) {
734c1ccf078SCarlos Alberto Enciso       std::string Directory;
735c1ccf078SCarlos Alberto Enciso       if (Lines->getDirectoryForEntry(Entry, Directory))
736c1ccf078SCarlos Alberto Enciso         Directory = transformPath(Directory);
737c1ccf078SCarlos Alberto Enciso       if (Directory.empty())
738c1ccf078SCarlos Alberto Enciso         Directory = std::string(CompileUnit->getCompilationDirectory());
739c1ccf078SCarlos Alberto Enciso       std::string File = transformPath(dwarf::toStringRef(Entry.Name));
740c1ccf078SCarlos Alberto Enciso       std::string String;
741c1ccf078SCarlos Alberto Enciso       raw_string_ostream(String) << Directory << "/" << File;
742c1ccf078SCarlos Alberto Enciso       CompileUnit->addFilename(String);
743c1ccf078SCarlos Alberto Enciso     }
744c1ccf078SCarlos Alberto Enciso 
745c1ccf078SCarlos Alberto Enciso   // In DWARF5 the file indexes start at 0;
746c1ccf078SCarlos Alberto Enciso   bool IncrementIndex = Lines->Prologue.getVersion() >= 5;
747c1ccf078SCarlos Alberto Enciso 
748c1ccf078SCarlos Alberto Enciso   // Get the source lines if requested by command line option.
749c1ccf078SCarlos Alberto Enciso   if (options().getPrintLines() && Lines->Rows.size())
750c1ccf078SCarlos Alberto Enciso     for (const DWARFDebugLine::Row &Row : Lines->Rows) {
751c1ccf078SCarlos Alberto Enciso       // Here we collect logical debug lines in CULines. Later on,
752c1ccf078SCarlos Alberto Enciso       // the 'processLines()' function will move each created logical line
753c1ccf078SCarlos Alberto Enciso       // to its enclosing logical scope, using the debug ranges information
754c1ccf078SCarlos Alberto Enciso       // and they will be released when its scope parent is deleted.
755c1ccf078SCarlos Alberto Enciso       LVLineDebug *Line = createLineDebug();
756c1ccf078SCarlos Alberto Enciso       CULines.push_back(Line);
757c1ccf078SCarlos Alberto Enciso       // Consider the case of WebAssembly.
758c1ccf078SCarlos Alberto Enciso       Line->setAddress(Row.Address.Address + WasmCodeSectionOffset);
759c1ccf078SCarlos Alberto Enciso       Line->setFilename(
760c1ccf078SCarlos Alberto Enciso           CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));
761c1ccf078SCarlos Alberto Enciso       Line->setLineNumber(Row.Line);
762c1ccf078SCarlos Alberto Enciso       if (Row.Discriminator)
763c1ccf078SCarlos Alberto Enciso         Line->setDiscriminator(Row.Discriminator);
764c1ccf078SCarlos Alberto Enciso       if (Row.IsStmt)
765c1ccf078SCarlos Alberto Enciso         Line->setIsNewStatement();
766c1ccf078SCarlos Alberto Enciso       if (Row.BasicBlock)
767c1ccf078SCarlos Alberto Enciso         Line->setIsBasicBlock();
768c1ccf078SCarlos Alberto Enciso       if (Row.EndSequence)
769c1ccf078SCarlos Alberto Enciso         Line->setIsEndSequence();
770c1ccf078SCarlos Alberto Enciso       if (Row.EpilogueBegin)
771c1ccf078SCarlos Alberto Enciso         Line->setIsEpilogueBegin();
772c1ccf078SCarlos Alberto Enciso       if (Row.PrologueEnd)
773c1ccf078SCarlos Alberto Enciso         Line->setIsPrologueEnd();
774c1ccf078SCarlos Alberto Enciso       LLVM_DEBUG({
775c1ccf078SCarlos Alberto Enciso         dbgs() << "Address: " << hexValue(Line->getAddress())
776c1ccf078SCarlos Alberto Enciso                << " Line: " << Line->lineNumberAsString(/*ShowZero=*/true)
777c1ccf078SCarlos Alberto Enciso                << "\n";
778c1ccf078SCarlos Alberto Enciso       });
779c1ccf078SCarlos Alberto Enciso     }
780c1ccf078SCarlos Alberto Enciso }
781c1ccf078SCarlos Alberto Enciso 
782c1ccf078SCarlos Alberto Enciso std::string LVDWARFReader::getRegisterName(LVSmall Opcode,
783c1ccf078SCarlos Alberto Enciso                                            ArrayRef<uint64_t> Operands) {
784c1ccf078SCarlos Alberto Enciso   // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support
785c1ccf078SCarlos Alberto Enciso   // DW_OP_regval_type. At this point we are operating on a logical view
786c1ccf078SCarlos Alberto Enciso   // item, with no access to the underlying DWARF data used by LLVM.
787c1ccf078SCarlos Alberto Enciso   // We do not support DW_OP_regval_type here.
788c1ccf078SCarlos Alberto Enciso   if (Opcode == dwarf::DW_OP_regval_type)
789c1ccf078SCarlos Alberto Enciso     return {};
790c1ccf078SCarlos Alberto Enciso 
791c1ccf078SCarlos Alberto Enciso   std::string string;
792c1ccf078SCarlos Alberto Enciso   raw_string_ostream Stream(string);
793c1ccf078SCarlos Alberto Enciso   DIDumpOptions DumpOpts;
794c1ccf078SCarlos Alberto Enciso   auto *MCRegInfo = MRI.get();
795c1ccf078SCarlos Alberto Enciso   auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
796c1ccf078SCarlos Alberto Enciso     if (!MCRegInfo)
797c1ccf078SCarlos Alberto Enciso       return {};
798f2b71491SCraig Topper     if (std::optional<MCRegister> LLVMRegNum =
799c1ccf078SCarlos Alberto Enciso             MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
800c1ccf078SCarlos Alberto Enciso       if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))
801c1ccf078SCarlos Alberto Enciso         return StringRef(RegName);
802c1ccf078SCarlos Alberto Enciso     return {};
803c1ccf078SCarlos Alberto Enciso   };
804c1ccf078SCarlos Alberto Enciso   DumpOpts.GetNameForDWARFReg = GetRegName;
805c1ccf078SCarlos Alberto Enciso   DWARFExpression::prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts,
806c1ccf078SCarlos Alberto Enciso                                          Opcode, Operands);
807c1ccf078SCarlos Alberto Enciso   return Stream.str();
808c1ccf078SCarlos Alberto Enciso }
809c1ccf078SCarlos Alberto Enciso 
810c1ccf078SCarlos Alberto Enciso Error LVDWARFReader::createScopes() {
811c1ccf078SCarlos Alberto Enciso   LLVM_DEBUG({
812c1ccf078SCarlos Alberto Enciso     W.startLine() << "\n";
813c1ccf078SCarlos Alberto Enciso     W.printString("File", Obj.getFileName().str());
814c1ccf078SCarlos Alberto Enciso     W.printString("Format", FileFormatName);
815c1ccf078SCarlos Alberto Enciso   });
816c1ccf078SCarlos Alberto Enciso 
817c1ccf078SCarlos Alberto Enciso   if (Error Err = LVReader::createScopes())
818c1ccf078SCarlos Alberto Enciso     return Err;
819c1ccf078SCarlos Alberto Enciso 
820c1ccf078SCarlos Alberto Enciso   // As the DwarfContext object is valid only during the scopes creation,
821c1ccf078SCarlos Alberto Enciso   // we need to create our own Target information, to be used during the
822c1ccf078SCarlos Alberto Enciso   // logical view printing, in the case of instructions being requested.
823c1ccf078SCarlos Alberto Enciso   std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(Obj);
824c1ccf078SCarlos Alberto Enciso   if (!DwarfContext)
825c1ccf078SCarlos Alberto Enciso     return createStringError(errc::invalid_argument,
826c1ccf078SCarlos Alberto Enciso                              "Could not create DWARF information: %s",
827c1ccf078SCarlos Alberto Enciso                              getFilename().str().c_str());
828c1ccf078SCarlos Alberto Enciso 
829c1ccf078SCarlos Alberto Enciso   if (Error Err = loadTargetInfo(Obj))
830c1ccf078SCarlos Alberto Enciso     return Err;
831c1ccf078SCarlos Alberto Enciso 
832c1ccf078SCarlos Alberto Enciso   // Create a mapping for virtual addresses.
833c1ccf078SCarlos Alberto Enciso   mapVirtualAddress(Obj);
834c1ccf078SCarlos Alberto Enciso 
835c1ccf078SCarlos Alberto Enciso   // Select the correct compile unit range, depending if we are dealing with
836c1ccf078SCarlos Alberto Enciso   // a standard or split DWARF object.
837c1ccf078SCarlos Alberto Enciso   DWARFContext::compile_unit_range CompileUnits =
838c1ccf078SCarlos Alberto Enciso       DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units()
839c1ccf078SCarlos Alberto Enciso                                          : DwarfContext->dwo_compile_units();
840c1ccf078SCarlos Alberto Enciso   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {
841c1ccf078SCarlos Alberto Enciso 
842c1ccf078SCarlos Alberto Enciso     // Deduction of index used for the line records.
843c1ccf078SCarlos Alberto Enciso     //
844c1ccf078SCarlos Alberto Enciso     // For the following test case: test.cpp
845c1ccf078SCarlos Alberto Enciso     //  void foo(void ParamPtr) { }
846c1ccf078SCarlos Alberto Enciso 
847c1ccf078SCarlos Alberto Enciso     // Both GCC and Clang generate DWARF-5 .debug_line layout.
848c1ccf078SCarlos Alberto Enciso 
849c1ccf078SCarlos Alberto Enciso     // * GCC (GNU C++17 11.3.0) - All DW_AT_decl_file use index 1.
850c1ccf078SCarlos Alberto Enciso     //
851c1ccf078SCarlos Alberto Enciso     //   .debug_info:
852c1ccf078SCarlos Alberto Enciso     //     format = DWARF32, version = 0x0005
853c1ccf078SCarlos Alberto Enciso     //     DW_TAG_compile_unit
854c1ccf078SCarlos Alberto Enciso     //       DW_AT_name	("test.cpp")
855c1ccf078SCarlos Alberto Enciso     //       DW_TAG_subprogram ("foo")
856c1ccf078SCarlos Alberto Enciso     //         DW_AT_decl_file (1)
857c1ccf078SCarlos Alberto Enciso     //         DW_TAG_formal_parameter ("ParamPtr")
858c1ccf078SCarlos Alberto Enciso     //           DW_AT_decl_file (1)
859c1ccf078SCarlos Alberto Enciso     //   .debug_line:
860c1ccf078SCarlos Alberto Enciso     //     Line table prologue: format (DWARF32), version (5)
861c1ccf078SCarlos Alberto Enciso     //     include_directories[0] = "..."
862c1ccf078SCarlos Alberto Enciso     //     file_names[0]: name ("test.cpp"), dir_index (0)
863c1ccf078SCarlos Alberto Enciso     //     file_names[1]: name ("test.cpp"), dir_index (0)
864c1ccf078SCarlos Alberto Enciso 
865c1ccf078SCarlos Alberto Enciso     // * Clang (14.0.6) - All DW_AT_decl_file use index 0.
866c1ccf078SCarlos Alberto Enciso     //
867c1ccf078SCarlos Alberto Enciso     //   .debug_info:
868c1ccf078SCarlos Alberto Enciso     //     format = DWARF32, version = 0x0005
869c1ccf078SCarlos Alberto Enciso     //     DW_AT_producer	("clang version 14.0.6")
870c1ccf078SCarlos Alberto Enciso     //     DW_AT_name	("test.cpp")
871c1ccf078SCarlos Alberto Enciso     //
872c1ccf078SCarlos Alberto Enciso     //     DW_TAG_subprogram ("foo")
873c1ccf078SCarlos Alberto Enciso     //       DW_AT_decl_file (0)
874c1ccf078SCarlos Alberto Enciso     //       DW_TAG_formal_parameter ("ParamPtr")
875c1ccf078SCarlos Alberto Enciso     //         DW_AT_decl_file (0)
876c1ccf078SCarlos Alberto Enciso     //   .debug_line:
877c1ccf078SCarlos Alberto Enciso     //     Line table prologue: format (DWARF32), version (5)
878c1ccf078SCarlos Alberto Enciso     //     include_directories[0] = "..."
879c1ccf078SCarlos Alberto Enciso     //     file_names[0]: name ("test.cpp"), dir_index (0)
880c1ccf078SCarlos Alberto Enciso 
881c1ccf078SCarlos Alberto Enciso     // From DWARFDebugLine::getFileNameByIndex documentation:
882c1ccf078SCarlos Alberto Enciso     //   In Dwarf 4, the files are 1-indexed.
883c1ccf078SCarlos Alberto Enciso     //   In Dwarf 5, the files are 0-indexed.
884c1ccf078SCarlos Alberto Enciso     // Additional discussions here:
885c1ccf078SCarlos Alberto Enciso     // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html
886c1ccf078SCarlos Alberto Enciso 
8879c0c98edSCarlos Alberto Enciso     // The DWARF reader is expecting the files are 1-indexed, so using
888c1ccf078SCarlos Alberto Enciso     // the .debug_line header information decide if the indexed require
889c1ccf078SCarlos Alberto Enciso     // an internal adjustment.
890c1ccf078SCarlos Alberto Enciso 
891c1ccf078SCarlos Alberto Enciso     // For the case of GCC (DWARF5), if the entries[0] and [1] are the
892c1ccf078SCarlos Alberto Enciso     // same, do not perform any adjustment.
893c1ccf078SCarlos Alberto Enciso     auto DeduceIncrementFileIndex = [&]() -> bool {
894c1ccf078SCarlos Alberto Enciso       if (CU->getVersion() < 5)
895c1ccf078SCarlos Alberto Enciso         // DWARF-4 or earlier -> Don't increment index.
896c1ccf078SCarlos Alberto Enciso         return false;
897c1ccf078SCarlos Alberto Enciso 
898c1ccf078SCarlos Alberto Enciso       if (const DWARFDebugLine::LineTable *LT =
899c1ccf078SCarlos Alberto Enciso               CU->getContext().getLineTableForUnit(CU.get())) {
900c1ccf078SCarlos Alberto Enciso         // Check if there are at least 2 entries and if they are the same.
901c1ccf078SCarlos Alberto Enciso         if (LT->hasFileAtIndex(0) && LT->hasFileAtIndex(1)) {
902c1ccf078SCarlos Alberto Enciso           const DWARFDebugLine::FileNameEntry &EntryZero =
903c1ccf078SCarlos Alberto Enciso               LT->Prologue.getFileNameEntry(0);
904c1ccf078SCarlos Alberto Enciso           const DWARFDebugLine::FileNameEntry &EntryOne =
905c1ccf078SCarlos Alberto Enciso               LT->Prologue.getFileNameEntry(1);
906c1ccf078SCarlos Alberto Enciso           // Check directory indexes.
907c1ccf078SCarlos Alberto Enciso           if (EntryZero.DirIdx != EntryOne.DirIdx)
908c1ccf078SCarlos Alberto Enciso             // DWARF-5 -> Increment index.
909c1ccf078SCarlos Alberto Enciso             return true;
910c1ccf078SCarlos Alberto Enciso           // Check filename.
911c1ccf078SCarlos Alberto Enciso           std::string FileZero;
912c1ccf078SCarlos Alberto Enciso           std::string FileOne;
913c1ccf078SCarlos Alberto Enciso           StringRef None;
914c1ccf078SCarlos Alberto Enciso           LT->getFileNameByIndex(
915c1ccf078SCarlos Alberto Enciso               0, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,
916c1ccf078SCarlos Alberto Enciso               FileZero);
917c1ccf078SCarlos Alberto Enciso           LT->getFileNameByIndex(
918c1ccf078SCarlos Alberto Enciso               1, None, DILineInfoSpecifier::FileLineInfoKind::RawValue,
919c1ccf078SCarlos Alberto Enciso               FileOne);
920c1ccf078SCarlos Alberto Enciso           return FileZero.compare(FileOne);
921c1ccf078SCarlos Alberto Enciso         }
922c1ccf078SCarlos Alberto Enciso       }
923c1ccf078SCarlos Alberto Enciso 
924c1ccf078SCarlos Alberto Enciso       // DWARF-5 -> Increment index.
925c1ccf078SCarlos Alberto Enciso       return true;
926c1ccf078SCarlos Alberto Enciso     };
9279c0c98edSCarlos Alberto Enciso     // The DWARF reader expects the indexes as 1-indexed.
928c1ccf078SCarlos Alberto Enciso     IncrementFileIndex = DeduceIncrementFileIndex();
929c1ccf078SCarlos Alberto Enciso 
930c1ccf078SCarlos Alberto Enciso     DWARFDie UnitDie = CU->getUnitDIE();
931c1ccf078SCarlos Alberto Enciso     SmallString<16> DWOAlternativeLocation;
932c1ccf078SCarlos Alberto Enciso     if (UnitDie) {
933c1ccf078SCarlos Alberto Enciso       std::optional<const char *> DWOFileName =
934c1ccf078SCarlos Alberto Enciso           CU->getVersion() >= 5
935c1ccf078SCarlos Alberto Enciso               ? dwarf::toString(UnitDie.find(dwarf::DW_AT_dwo_name))
936c1ccf078SCarlos Alberto Enciso               : dwarf::toString(UnitDie.find(dwarf::DW_AT_GNU_dwo_name));
937c1ccf078SCarlos Alberto Enciso       StringRef From(DWOFileName.value_or(""));
938c1ccf078SCarlos Alberto Enciso       DWOAlternativeLocation = createAlternativePath(From);
939c1ccf078SCarlos Alberto Enciso     }
940c1ccf078SCarlos Alberto Enciso 
941c1ccf078SCarlos Alberto Enciso     // The current CU can be a normal compile unit (standard) or a skeleton
942c1ccf078SCarlos Alberto Enciso     // compile unit (split). For both cases, the returned die, will be used
943c1ccf078SCarlos Alberto Enciso     // to create the logical scopes.
944c1ccf078SCarlos Alberto Enciso     DWARFDie CUDie = CU->getNonSkeletonUnitDIE(
945c1ccf078SCarlos Alberto Enciso         /*ExtractUnitDIEOnly=*/false,
946c1ccf078SCarlos Alberto Enciso         /*DWOAlternativeLocation=*/DWOAlternativeLocation);
947c1ccf078SCarlos Alberto Enciso     if (!CUDie.isValid())
948c1ccf078SCarlos Alberto Enciso       continue;
949c1ccf078SCarlos Alberto Enciso 
950c1ccf078SCarlos Alberto Enciso     // The current unit corresponds to the .dwo file. We need to get the
951c1ccf078SCarlos Alberto Enciso     // skeleton unit and query for any ranges that will enclose any ranges
952c1ccf078SCarlos Alberto Enciso     // in the non-skeleton unit.
953c1ccf078SCarlos Alberto Enciso     DWARFDie DummyDie;
954c1ccf078SCarlos Alberto Enciso     DWARFDie SkeletonDie =
955c1ccf078SCarlos Alberto Enciso         CUDie.getDwarfUnit()->isDWOUnit() ? CU->getUnitDIE(false) : DummyDie;
956c1ccf078SCarlos Alberto Enciso     // Disable the ranges processing if we have just a single .dwo object,
957c1ccf078SCarlos Alberto Enciso     // as any DW_AT_ranges will access not available range information.
958c1ccf078SCarlos Alberto Enciso     RangesDataAvailable =
959c1ccf078SCarlos Alberto Enciso         (!CUDie.getDwarfUnit()->isDWOUnit() ||
960c1ccf078SCarlos Alberto Enciso          (SkeletonDie.isValid() ? !SkeletonDie.getDwarfUnit()->isDWOUnit()
961c1ccf078SCarlos Alberto Enciso                                 : true));
962c1ccf078SCarlos Alberto Enciso 
963c1ccf078SCarlos Alberto Enciso     traverseDieAndChildren(CUDie, Root, SkeletonDie);
964c1ccf078SCarlos Alberto Enciso 
965c1ccf078SCarlos Alberto Enciso     createLineAndFileRecords(DwarfContext->getLineTableForUnit(CU.get()));
966c1ccf078SCarlos Alberto Enciso     if (Error Err = createInstructions())
967c1ccf078SCarlos Alberto Enciso       return Err;
968c1ccf078SCarlos Alberto Enciso 
969c1ccf078SCarlos Alberto Enciso     // Process the compilation unit, as there are cases where enclosed
970c1ccf078SCarlos Alberto Enciso     // functions have the same ranges values. Insert the compilation unit
971c1ccf078SCarlos Alberto Enciso     // ranges at the end, to allow enclosing ranges to be first in the list.
972c1ccf078SCarlos Alberto Enciso     LVSectionIndex SectionIndex = getSectionIndex(CompileUnit);
973c1ccf078SCarlos Alberto Enciso     addSectionRange(SectionIndex, CompileUnit);
974c1ccf078SCarlos Alberto Enciso     LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
975c1ccf078SCarlos Alberto Enciso     ScopesWithRanges->sort();
976c1ccf078SCarlos Alberto Enciso 
977c1ccf078SCarlos Alberto Enciso     processLines(&CULines, SectionIndex);
978c1ccf078SCarlos Alberto Enciso     processLocationGaps();
979c1ccf078SCarlos Alberto Enciso 
980c1ccf078SCarlos Alberto Enciso     // These are per compile unit.
981c1ccf078SCarlos Alberto Enciso     ScopesWithRanges->clear();
982c1ccf078SCarlos Alberto Enciso     SymbolsWithLocations.clear();
983c1ccf078SCarlos Alberto Enciso     CULines.clear();
984c1ccf078SCarlos Alberto Enciso   }
985c1ccf078SCarlos Alberto Enciso 
986c1ccf078SCarlos Alberto Enciso   return Error::success();
987c1ccf078SCarlos Alberto Enciso }
988c1ccf078SCarlos Alberto Enciso 
989c1ccf078SCarlos Alberto Enciso // Get the location information for the associated attribute.
990c1ccf078SCarlos Alberto Enciso void LVDWARFReader::processLocationList(dwarf::Attribute Attr,
991c1ccf078SCarlos Alberto Enciso                                         const DWARFFormValue &FormValue,
992c1ccf078SCarlos Alberto Enciso                                         const DWARFDie &Die,
993c1ccf078SCarlos Alberto Enciso                                         uint64_t OffsetOnEntry,
994c1ccf078SCarlos Alberto Enciso                                         bool CallSiteLocation) {
995c1ccf078SCarlos Alberto Enciso 
996c1ccf078SCarlos Alberto Enciso   auto ProcessLocationExpression = [&](const DWARFExpression &Expression) {
997c1ccf078SCarlos Alberto Enciso     for (const DWARFExpression::Operation &Op : Expression)
998c1ccf078SCarlos Alberto Enciso       CurrentSymbol->addLocationOperands(Op.getCode(), Op.getRawOperands());
999c1ccf078SCarlos Alberto Enciso   };
1000c1ccf078SCarlos Alberto Enciso 
1001c1ccf078SCarlos Alberto Enciso   DWARFUnit *U = Die.getDwarfUnit();
1002c1ccf078SCarlos Alberto Enciso   DWARFContext &DwarfContext = U->getContext();
1003c1ccf078SCarlos Alberto Enciso   bool IsLittleEndian = DwarfContext.isLittleEndian();
1004c1ccf078SCarlos Alberto Enciso   if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
1005c1ccf078SCarlos Alberto Enciso       (DWARFAttribute::mayHaveLocationExpr(Attr) &&
1006c1ccf078SCarlos Alberto Enciso        FormValue.isFormClass(DWARFFormValue::FC_Exprloc))) {
1007c1ccf078SCarlos Alberto Enciso     ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
1008c1ccf078SCarlos Alberto Enciso     DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
1009c1ccf078SCarlos Alberto Enciso                        IsLittleEndian, 0);
1010c1ccf078SCarlos Alberto Enciso     DWARFExpression Expression(Data, U->getAddressByteSize(),
1011c1ccf078SCarlos Alberto Enciso                                U->getFormParams().Format);
1012c1ccf078SCarlos Alberto Enciso 
1013c1ccf078SCarlos Alberto Enciso     // Add location and operation entries.
1014c1ccf078SCarlos Alberto Enciso     CurrentSymbol->addLocation(Attr, /*LowPC=*/0, /*HighPC=*/-1,
1015c1ccf078SCarlos Alberto Enciso                                /*SectionOffset=*/0, OffsetOnEntry,
1016c1ccf078SCarlos Alberto Enciso                                CallSiteLocation);
1017c1ccf078SCarlos Alberto Enciso     ProcessLocationExpression(Expression);
1018c1ccf078SCarlos Alberto Enciso     return;
1019c1ccf078SCarlos Alberto Enciso   }
1020c1ccf078SCarlos Alberto Enciso 
1021c1ccf078SCarlos Alberto Enciso   if (DWARFAttribute::mayHaveLocationList(Attr) &&
1022c1ccf078SCarlos Alberto Enciso       FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
1023c1ccf078SCarlos Alberto Enciso     uint64_t Offset = *FormValue.getAsSectionOffset();
1024c1ccf078SCarlos Alberto Enciso     if (FormValue.getForm() == dwarf::DW_FORM_loclistx) {
1025c1ccf078SCarlos Alberto Enciso       std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(Offset);
1026c1ccf078SCarlos Alberto Enciso       if (!LoclistOffset)
1027c1ccf078SCarlos Alberto Enciso         return;
1028c1ccf078SCarlos Alberto Enciso       Offset = *LoclistOffset;
1029c1ccf078SCarlos Alberto Enciso     }
1030c1ccf078SCarlos Alberto Enciso     uint64_t BaseAddr = 0;
1031c1ccf078SCarlos Alberto Enciso     if (std::optional<SectionedAddress> BA = U->getBaseAddress())
1032c1ccf078SCarlos Alberto Enciso       BaseAddr = BA->Address;
1033c1ccf078SCarlos Alberto Enciso     LVAddress LowPC = 0;
1034c1ccf078SCarlos Alberto Enciso     LVAddress HighPC = 0;
1035c1ccf078SCarlos Alberto Enciso 
1036c1ccf078SCarlos Alberto Enciso     auto ProcessLocationEntry = [&](const DWARFLocationEntry &Entry) {
1037c1ccf078SCarlos Alberto Enciso       if (Entry.Kind == dwarf::DW_LLE_base_address) {
1038c1ccf078SCarlos Alberto Enciso         BaseAddr = Entry.Value0;
1039c1ccf078SCarlos Alberto Enciso         return;
1040c1ccf078SCarlos Alberto Enciso       }
1041c1ccf078SCarlos Alberto Enciso       if (Entry.Kind == dwarf::DW_LLE_offset_pair) {
1042c1ccf078SCarlos Alberto Enciso         LowPC = BaseAddr + Entry.Value0;
1043c1ccf078SCarlos Alberto Enciso         HighPC = BaseAddr + Entry.Value1;
1044c1ccf078SCarlos Alberto Enciso         DWARFAddressRange Range{LowPC, HighPC, Entry.SectionIndex};
1045c1ccf078SCarlos Alberto Enciso         if (Range.SectionIndex == SectionedAddress::UndefSection)
1046c1ccf078SCarlos Alberto Enciso           Range.SectionIndex = Entry.SectionIndex;
1047c1ccf078SCarlos Alberto Enciso         DWARFLocationExpression Loc{Range, Entry.Loc};
1048c1ccf078SCarlos Alberto Enciso         DWARFDataExtractor Data(Loc.Expr, IsLittleEndian,
1049c1ccf078SCarlos Alberto Enciso                                 U->getAddressByteSize());
1050c1ccf078SCarlos Alberto Enciso         DWARFExpression Expression(Data, U->getAddressByteSize());
1051c1ccf078SCarlos Alberto Enciso 
1052c1ccf078SCarlos Alberto Enciso         // Store the real upper limit for the address range.
1053c1ccf078SCarlos Alberto Enciso         if (UpdateHighAddress && HighPC > 0)
1054c1ccf078SCarlos Alberto Enciso           --HighPC;
1055c1ccf078SCarlos Alberto Enciso         // Add location and operation entries.
1056c1ccf078SCarlos Alberto Enciso         CurrentSymbol->addLocation(Attr, LowPC, HighPC, Offset, OffsetOnEntry,
1057c1ccf078SCarlos Alberto Enciso                                    CallSiteLocation);
1058c1ccf078SCarlos Alberto Enciso         ProcessLocationExpression(Expression);
1059c1ccf078SCarlos Alberto Enciso       }
1060c1ccf078SCarlos Alberto Enciso     };
1061c1ccf078SCarlos Alberto Enciso     Error E = U->getLocationTable().visitLocationList(
1062c1ccf078SCarlos Alberto Enciso         &Offset, [&](const DWARFLocationEntry &E) {
1063c1ccf078SCarlos Alberto Enciso           ProcessLocationEntry(E);
1064c1ccf078SCarlos Alberto Enciso           return true;
1065c1ccf078SCarlos Alberto Enciso         });
1066c1ccf078SCarlos Alberto Enciso     if (E)
1067c1ccf078SCarlos Alberto Enciso       consumeError(std::move(E));
1068c1ccf078SCarlos Alberto Enciso   }
1069c1ccf078SCarlos Alberto Enciso }
1070c1ccf078SCarlos Alberto Enciso 
1071c1ccf078SCarlos Alberto Enciso void LVDWARFReader::processLocationMember(dwarf::Attribute Attr,
1072c1ccf078SCarlos Alberto Enciso                                           const DWARFFormValue &FormValue,
1073c1ccf078SCarlos Alberto Enciso                                           const DWARFDie &Die,
1074c1ccf078SCarlos Alberto Enciso                                           uint64_t OffsetOnEntry) {
1075c1ccf078SCarlos Alberto Enciso   // Check if the value is an integer constant.
1076c1ccf078SCarlos Alberto Enciso   if (FormValue.isFormClass(DWARFFormValue::FC_Constant))
1077c1ccf078SCarlos Alberto Enciso     // Add a record to hold a constant as location.
1078c1ccf078SCarlos Alberto Enciso     CurrentSymbol->addLocationConstant(Attr, *FormValue.getAsUnsignedConstant(),
1079c1ccf078SCarlos Alberto Enciso                                        OffsetOnEntry);
1080c1ccf078SCarlos Alberto Enciso   else
1081c1ccf078SCarlos Alberto Enciso     // This is a location description, or a reference to one.
1082c1ccf078SCarlos Alberto Enciso     processLocationList(Attr, FormValue, Die, OffsetOnEntry);
1083c1ccf078SCarlos Alberto Enciso }
1084c1ccf078SCarlos Alberto Enciso 
1085c1ccf078SCarlos Alberto Enciso // Update the current element with the reference.
1086c1ccf078SCarlos Alberto Enciso void LVDWARFReader::updateReference(dwarf::Attribute Attr,
1087c1ccf078SCarlos Alberto Enciso                                     const DWARFFormValue &FormValue) {
1088c1ccf078SCarlos Alberto Enciso   // FIXME: We are assuming that at most one Reference (DW_AT_specification,
1089c1ccf078SCarlos Alberto Enciso   // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type)
1090c1ccf078SCarlos Alberto Enciso   // appear in any single DIE, but this may not be true.
1091d0d61a7eSPavel Labath   uint64_t Offset;
1092d0d61a7eSPavel Labath   if (std::optional<uint64_t> Off = FormValue.getAsRelativeReference())
1093d0d61a7eSPavel Labath     Offset = FormValue.getUnit()->getOffset() + *Off;
1094d0d61a7eSPavel Labath   else if (Off = FormValue.getAsDebugInfoReference(); Off)
1095d0d61a7eSPavel Labath     Offset = *Off;
1096d0d61a7eSPavel Labath   else
1097d0d61a7eSPavel Labath     llvm_unreachable("Unsupported reference type");
1098d0d61a7eSPavel Labath 
1099c1ccf078SCarlos Alberto Enciso   // Get target for the given reference, if already created.
1100c1ccf078SCarlos Alberto Enciso   LVElement *Target = getElementForOffset(
1101d0d61a7eSPavel Labath       Offset, CurrentElement,
1102c1ccf078SCarlos Alberto Enciso       /*IsType=*/Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type);
1103c1ccf078SCarlos Alberto Enciso   // Check if we are dealing with cross CU references.
1104c1ccf078SCarlos Alberto Enciso   if (FormValue.getForm() == dwarf::DW_FORM_ref_addr) {
1105c1ccf078SCarlos Alberto Enciso     if (Target) {
1106c1ccf078SCarlos Alberto Enciso       // The global reference is ready. Mark it as global.
1107c1ccf078SCarlos Alberto Enciso       Target->setIsGlobalReference();
1108c1ccf078SCarlos Alberto Enciso       // Remove global reference from the unseen list.
1109d0d61a7eSPavel Labath       removeGlobalOffset(Offset);
1110c1ccf078SCarlos Alberto Enciso     } else
1111c1ccf078SCarlos Alberto Enciso       // Record the unseen cross CU reference.
1112d0d61a7eSPavel Labath       addGlobalOffset(Offset);
1113c1ccf078SCarlos Alberto Enciso   }
1114c1ccf078SCarlos Alberto Enciso 
1115c1ccf078SCarlos Alberto Enciso   // At this point, 'Target' can be null, in the case of the target element
1116c1ccf078SCarlos Alberto Enciso   // not being seen. But the correct bit is set, to indicate that the target
1117c1ccf078SCarlos Alberto Enciso   // is being referenced by (abstract_origin, extension, specification) or
1118c1ccf078SCarlos Alberto Enciso   // (import, type).
1119c1ccf078SCarlos Alberto Enciso   // We must differentiate between the kind of reference. This is needed to
1120c1ccf078SCarlos Alberto Enciso   // complete inlined function instances with dropped abstract references,
1121c1ccf078SCarlos Alberto Enciso   // in order to facilitate a logical comparison.
1122c1ccf078SCarlos Alberto Enciso   switch (Attr) {
1123c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_abstract_origin:
1124c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_call_origin:
1125c1ccf078SCarlos Alberto Enciso     CurrentElement->setReference(Target);
1126c1ccf078SCarlos Alberto Enciso     CurrentElement->setHasReferenceAbstract();
1127c1ccf078SCarlos Alberto Enciso     break;
1128c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_extension:
1129c1ccf078SCarlos Alberto Enciso     CurrentElement->setReference(Target);
1130c1ccf078SCarlos Alberto Enciso     CurrentElement->setHasReferenceExtension();
1131c1ccf078SCarlos Alberto Enciso     break;
1132c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_specification:
1133c1ccf078SCarlos Alberto Enciso     CurrentElement->setReference(Target);
1134c1ccf078SCarlos Alberto Enciso     CurrentElement->setHasReferenceSpecification();
1135c1ccf078SCarlos Alberto Enciso     break;
1136c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_import:
1137c1ccf078SCarlos Alberto Enciso   case dwarf::DW_AT_type:
1138c1ccf078SCarlos Alberto Enciso     CurrentElement->setType(Target);
1139c1ccf078SCarlos Alberto Enciso     break;
1140c1ccf078SCarlos Alberto Enciso   default:
1141c1ccf078SCarlos Alberto Enciso     break;
1142c1ccf078SCarlos Alberto Enciso   }
1143c1ccf078SCarlos Alberto Enciso }
1144c1ccf078SCarlos Alberto Enciso 
1145c1ccf078SCarlos Alberto Enciso // Get an element given the DIE offset.
1146c1ccf078SCarlos Alberto Enciso LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset,
1147c1ccf078SCarlos Alberto Enciso                                               LVElement *Element, bool IsType) {
1148c1ccf078SCarlos Alberto Enciso   // Update the element and all the references pointing to this element.
11498b6764fdSKazu Hirata   LVElementEntry &Entry = ElementTable[Offset];
1150c1ccf078SCarlos Alberto Enciso   if (!Entry.Element) {
1151c1ccf078SCarlos Alberto Enciso     if (IsType)
1152c1ccf078SCarlos Alberto Enciso       Entry.Types.insert(Element);
1153c1ccf078SCarlos Alberto Enciso     else
1154c1ccf078SCarlos Alberto Enciso       Entry.References.insert(Element);
1155c1ccf078SCarlos Alberto Enciso   }
1156c1ccf078SCarlos Alberto Enciso   return Entry.Element;
1157c1ccf078SCarlos Alberto Enciso }
1158c1ccf078SCarlos Alberto Enciso 
1159c1ccf078SCarlos Alberto Enciso Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) {
1160c1ccf078SCarlos Alberto Enciso   // Detect the architecture from the object file. We usually don't need OS
1161c1ccf078SCarlos Alberto Enciso   // info to lookup a target and create register info.
1162c1ccf078SCarlos Alberto Enciso   Triple TT;
1163c1ccf078SCarlos Alberto Enciso   TT.setArch(Triple::ArchType(Obj.getArch()));
1164c1ccf078SCarlos Alberto Enciso   TT.setVendor(Triple::UnknownVendor);
1165c1ccf078SCarlos Alberto Enciso   TT.setOS(Triple::UnknownOS);
1166c1ccf078SCarlos Alberto Enciso 
1167c1ccf078SCarlos Alberto Enciso   // Features to be passed to target/subtarget
1168c1ccf078SCarlos Alberto Enciso   Expected<SubtargetFeatures> Features = Obj.getFeatures();
1169c1ccf078SCarlos Alberto Enciso   SubtargetFeatures FeaturesValue;
1170c1ccf078SCarlos Alberto Enciso   if (!Features) {
1171c1ccf078SCarlos Alberto Enciso     consumeError(Features.takeError());
1172c1ccf078SCarlos Alberto Enciso     FeaturesValue = SubtargetFeatures();
1173c1ccf078SCarlos Alberto Enciso   }
1174c1ccf078SCarlos Alberto Enciso   FeaturesValue = *Features;
1175c1ccf078SCarlos Alberto Enciso   return loadGenericTargetInfo(TT.str(), FeaturesValue.getString());
1176c1ccf078SCarlos Alberto Enciso }
1177c1ccf078SCarlos Alberto Enciso 
1178c1ccf078SCarlos Alberto Enciso void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) {
1179c1ccf078SCarlos Alberto Enciso   for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) {
1180c1ccf078SCarlos Alberto Enciso     const SymbolRef &Symbol = *Iter;
1181c1ccf078SCarlos Alberto Enciso 
1182c1ccf078SCarlos Alberto Enciso     Expected<SymbolRef::Type> TypeOrErr = Symbol.getType();
1183c1ccf078SCarlos Alberto Enciso     if (!TypeOrErr) {
1184c1ccf078SCarlos Alberto Enciso       consumeError(TypeOrErr.takeError());
1185c1ccf078SCarlos Alberto Enciso       continue;
1186c1ccf078SCarlos Alberto Enciso     }
1187c1ccf078SCarlos Alberto Enciso 
1188c1ccf078SCarlos Alberto Enciso     // Process only symbols that represent a function.
1189c1ccf078SCarlos Alberto Enciso     SymbolRef::Type Type = *TypeOrErr;
1190c1ccf078SCarlos Alberto Enciso     if (Type != SymbolRef::ST_Function)
1191c1ccf078SCarlos Alberto Enciso       continue;
1192c1ccf078SCarlos Alberto Enciso 
1193c1ccf078SCarlos Alberto Enciso     // In the case of a Mach-O STAB symbol, get its section only if
1194c1ccf078SCarlos Alberto Enciso     // the STAB symbol's section field refers to a valid section index.
1195c1ccf078SCarlos Alberto Enciso     // Otherwise the symbol may error trying to load a section that
1196c1ccf078SCarlos Alberto Enciso     // does not exist.
1197c1ccf078SCarlos Alberto Enciso     const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);
1198c1ccf078SCarlos Alberto Enciso     bool IsSTAB = false;
1199c1ccf078SCarlos Alberto Enciso     if (MachO) {
1200c1ccf078SCarlos Alberto Enciso       DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1201c1ccf078SCarlos Alberto Enciso       uint8_t NType =
1202c1ccf078SCarlos Alberto Enciso           (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
1203c1ccf078SCarlos Alberto Enciso                             : MachO->getSymbolTableEntry(SymDRI).n_type);
1204c1ccf078SCarlos Alberto Enciso       if (NType & MachO::N_STAB)
1205c1ccf078SCarlos Alberto Enciso         IsSTAB = true;
1206c1ccf078SCarlos Alberto Enciso     }
1207c1ccf078SCarlos Alberto Enciso 
1208c1ccf078SCarlos Alberto Enciso     Expected<section_iterator> IterOrErr = Symbol.getSection();
1209c1ccf078SCarlos Alberto Enciso     if (!IterOrErr) {
1210c1ccf078SCarlos Alberto Enciso       consumeError(IterOrErr.takeError());
1211c1ccf078SCarlos Alberto Enciso       continue;
1212c1ccf078SCarlos Alberto Enciso     }
1213c1ccf078SCarlos Alberto Enciso     section_iterator Section = IsSTAB ? Obj.section_end() : *IterOrErr;
1214c1ccf078SCarlos Alberto Enciso     if (Section == Obj.section_end())
1215c1ccf078SCarlos Alberto Enciso       continue;
1216c1ccf078SCarlos Alberto Enciso 
1217c1ccf078SCarlos Alberto Enciso     // Get the symbol value.
1218c1ccf078SCarlos Alberto Enciso     Expected<uint64_t> AddressOrErr = Symbol.getAddress();
1219c1ccf078SCarlos Alberto Enciso     if (!AddressOrErr) {
1220c1ccf078SCarlos Alberto Enciso       consumeError(AddressOrErr.takeError());
1221c1ccf078SCarlos Alberto Enciso       continue;
1222c1ccf078SCarlos Alberto Enciso     }
1223c1ccf078SCarlos Alberto Enciso     uint64_t Address = *AddressOrErr;
1224c1ccf078SCarlos Alberto Enciso 
1225c1ccf078SCarlos Alberto Enciso     // Get symbol name.
1226c1ccf078SCarlos Alberto Enciso     StringRef Name;
1227c1ccf078SCarlos Alberto Enciso     Expected<StringRef> NameOrErr = Symbol.getName();
1228c1ccf078SCarlos Alberto Enciso     if (!NameOrErr) {
1229c1ccf078SCarlos Alberto Enciso       consumeError(NameOrErr.takeError());
1230c1ccf078SCarlos Alberto Enciso       continue;
1231c1ccf078SCarlos Alberto Enciso     }
1232c1ccf078SCarlos Alberto Enciso     Name = *NameOrErr;
1233c1ccf078SCarlos Alberto Enciso 
1234c1ccf078SCarlos Alberto Enciso     // Check if the symbol is Comdat.
1235c1ccf078SCarlos Alberto Enciso     Expected<uint32_t> FlagsOrErr = Symbol.getFlags();
1236c1ccf078SCarlos Alberto Enciso     if (!FlagsOrErr) {
1237c1ccf078SCarlos Alberto Enciso       consumeError(FlagsOrErr.takeError());
1238c1ccf078SCarlos Alberto Enciso       continue;
1239c1ccf078SCarlos Alberto Enciso     }
1240c1ccf078SCarlos Alberto Enciso     uint32_t Flags = *FlagsOrErr;
1241c1ccf078SCarlos Alberto Enciso 
1242c1ccf078SCarlos Alberto Enciso     // Mark the symbol as 'comdat' in any of the following cases:
1243c1ccf078SCarlos Alberto Enciso     // - Symbol has the SF_Weak flag or
1244c1ccf078SCarlos Alberto Enciso     // - Symbol section index different from the DotTextSectionIndex.
1245c1ccf078SCarlos Alberto Enciso     LVSectionIndex SectionIndex = Section->getIndex();
1246c1ccf078SCarlos Alberto Enciso     bool IsComdat =
1247c1ccf078SCarlos Alberto Enciso         (Flags & SymbolRef::SF_Weak) || (SectionIndex != DotTextSectionIndex);
1248c1ccf078SCarlos Alberto Enciso 
1249c1ccf078SCarlos Alberto Enciso     // Record the symbol name (linkage) and its loading address.
1250c1ccf078SCarlos Alberto Enciso     addToSymbolTable(Name, Address, SectionIndex, IsComdat);
1251c1ccf078SCarlos Alberto Enciso   }
1252c1ccf078SCarlos Alberto Enciso }
1253c1ccf078SCarlos Alberto Enciso 
1254c1ccf078SCarlos Alberto Enciso void LVDWARFReader::sortScopes() { Root->sort(); }
1255c1ccf078SCarlos Alberto Enciso 
1256c1ccf078SCarlos Alberto Enciso void LVDWARFReader::print(raw_ostream &OS) const {
1257c1ccf078SCarlos Alberto Enciso   OS << "LVType\n";
1258c1ccf078SCarlos Alberto Enciso   LLVM_DEBUG(dbgs() << "CreateReaders\n");
1259c1ccf078SCarlos Alberto Enciso }
1260