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