diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h index 9ad27033ec110..78ac34e5f0d26 100644 --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -204,6 +204,7 @@ struct DIDumpOptions { bool Verbose = false; bool DisplayRawContents = false; bool IsEH = false; + bool DumpNonSkeleton = false; std::function GetNameForDWARFReg; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index fa98cbcfc4d99..7be65a8b45e2d 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -372,7 +372,13 @@ class DWARFContext : public DIContext { /// given address where applicable. /// TODO: change input parameter from "uint64_t Address" /// into "SectionedAddress Address" - DIEsForAddress getDIEsForAddress(uint64_t Address); + /// \param[in] CheckDWO If this is false then only search for address matches + /// in the current context's DIEs. If this is true, then each + /// DWARFUnit that has a DWO file will have the debug info in the + /// DWO file searched as well. This allows for lookups to succeed + /// by searching the split DWARF debug info when using the main + /// executable's debug info. + DIEsForAddress getDIEsForAddress(uint64_t Address, bool CheckDWO = false); DILineInfo getLineInfoForAddress( object::SectionedAddress Address, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 6461f2ac031d2..30afa651ffc23 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -35,10 +35,16 @@ void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset()) << ")\n"; - if (DWARFDie CUDie = getUnitDIE(false)) + if (DWARFDie CUDie = getUnitDIE(false)) { CUDie.dump(OS, 0, DumpOpts); - else + if (DumpOpts.DumpNonSkeleton) { + DWARFDie NonSkeletonCUDie = getNonSkeletonUnitDIE(false); + if (NonSkeletonCUDie && CUDie != NonSkeletonCUDie) + NonSkeletonCUDie.dump(OS, 0, DumpOpts); + } + } else { OS << "\n\n"; + } } // VTable anchor. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index c671aedbc9e52..e6df590b8dd7a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1024,9 +1024,17 @@ void DWARFContext::dump( auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) { OS << '\n' << Name << " contents:\n"; if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) - for (const auto &U : Units) + for (const auto &U : Units) { U->getDIEForOffset(*DumpOffset) .dump(OS, 0, DumpOpts.noImplicitRecursion()); + DWARFDie CUDie = U->getUnitDIE(false); + DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false); + if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) { + CUNonSkeletonDie.getDwarfUnit() + ->getDIEForOffset(*DumpOffset) + .dump(OS, 0, DumpOpts.noImplicitRecursion()); + } + } else for (const auto &U : Units) U->dump(OS, DumpOpts); @@ -1537,15 +1545,38 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { return nullptr; } -DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { +DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address, + bool CheckDWO) { DIEsForAddress Result; DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address); if (!CU) return Result; - Result.CompileUnit = CU; - Result.FunctionDIE = CU->getSubroutineForAddress(Address); + if (CheckDWO) { + // We were asked to check the DWO file and this debug information is more + // complete that any information in the skeleton compile unit, so search the + // DWO first to see if we have a match. + DWARFDie CUDie = CU->getUnitDIE(false); + DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false); + if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) { + // We have a DWO file, lets search it. + DWARFCompileUnit *CUDwo = + dyn_cast_or_null(CUDwoDie.getDwarfUnit()); + if (CUDwo) { + Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address); + if (Result.FunctionDIE) + Result.CompileUnit = CUDwo; + } + } + } + + // Search the normal DWARF if we didn't find a match in the DWO file or if + // we didn't check the DWO file above. + if (!Result) { + Result.CompileUnit = CU; + Result.FunctionDIE = CU->getSubroutineForAddress(Address); + } std::vector Worklist; Worklist.push_back(Result.FunctionDIE); diff --git a/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.dwo.yaml b/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.dwo.yaml new file mode 100644 index 0000000000000..5f24586bded06 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.dwo.yaml @@ -0,0 +1,37 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .debug_str_offsets.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 2C0000000500000000000000080000000C00000010000000150000001A0000001F000000240000005400000061000000 + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 5F5A33666F6F7600666F6F00696E74006D61696E006172676300617267760063686172004170706C6520636C616E672076657273696F6E2031352E302E302028636C616E672D313530302E312E302E322E35290064756D705F64776F2E637070002E2F64756D705F64776F2E64776F00 + - Name: .debug_info.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 64000000050005080000000036C1C3A75DD36D37010704000809020008000000015600010002500000000301230000000156030006500000000402917804000650000000040291700500065400000000050205040659000000065E00000007630000000506060100 + - Name: .debug_abbrev.dwo + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + AddressAlign: 0x1 + Content: 01110125251305032576250000022E00111B120640186E2503253A0B3B0B49133F190000032E01111B1206401803253A0B3B0B49133F190000040500021803253A0B3B0B4913000005240003253E0B0B0B0000060F00491300000726004913000000 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .debug_str_offsets.dwo + - Name: .debug_str.dwo + - Name: .debug_info.dwo + - Name: .debug_abbrev.dwo +... diff --git a/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.o.yaml b/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.o.yaml new file mode 100644 index 0000000000000..8b15e0888659c --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/Inputs/dump_dwo.o.yaml @@ -0,0 +1,251 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x10 + Content: 554889E531C05DC30F1F840000000000554889E54883EC10C745FC00000000897DF8488975F0E80000000031C04883C4105DC3 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 014A00101772171B25B442197625111B12067317000000 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 24000000050004080000000036C1C3A75DD36D370100000000000000000001003300000000000000 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 0C000000050000000000000000000000 + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 21000000020000000000280000001A00000030666F6F002A000000306D61696E0000000000 + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '21000000020000000000280000005000000090696E74006300000090636861720000000000' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 004170706C6520636C616E672076657273696F6E2031352E302E302028636C616E672D313530302E312E302E322E352900 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x1 + - Name: .eh_frame + Type: SHT_X86_64_UNWIND + Flags: [ SHF_ALLOC ] + AddressAlign: 0x8 + Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C000000000000000800000000410E108602430D06430C07080000001C0000003C000000000000002300000000410E108602430D065E0C0708000000 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 5F0000000500080037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E0100000000004000920BB47E0DDA24E8521F209EDB37040000090200000000000000001305020A4B0500BD05030A0859590208000101 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 2E2F0064756D705F64776F2E63707000 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Offset: 0x27 + Symbol: _Z3foov + Type: R_X86_64_PLT32 + Addend: -4 + - Name: .rela.debug_info + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_info + Relocations: + - Offset: 0x8 + Symbol: .debug_abbrev + Type: R_X86_64_32 + - Offset: 0x15 + Symbol: .debug_line + Type: R_X86_64_32 + - Offset: 0x19 + Symbol: .debug_str_offsets + Type: R_X86_64_32 + Addend: 8 + - Offset: 0x24 + Symbol: .debug_addr + Type: R_X86_64_32 + Addend: 8 + - Name: .rela.debug_str_offsets + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_str_offsets + Relocations: + - Offset: 0x8 + Symbol: .debug_str + Type: R_X86_64_32 + - Offset: 0xC + Symbol: .debug_str + Type: R_X86_64_32 + Addend: 3 + - Name: .rela.debug_addr + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_addr + Relocations: + - Offset: 0x8 + Symbol: .text + Type: R_X86_64_64 + - Offset: 0x10 + Symbol: .text + Type: R_X86_64_64 + Addend: 16 + - Name: .rela.debug_gnu_pubnames + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_gnu_pubnames + Relocations: + - Offset: 0x6 + Symbol: .debug_info + Type: R_X86_64_32 + - Name: .rela.debug_gnu_pubtypes + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_gnu_pubtypes + Relocations: + - Offset: 0x6 + Symbol: .debug_info + Type: R_X86_64_32 + - Name: .rela.eh_frame + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .eh_frame + Relocations: + - Offset: 0x20 + Symbol: .text + Type: R_X86_64_PC32 + - Offset: 0x40 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 16 + - Name: .rela.debug_line + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .debug_line + Relocations: + - Offset: 0x22 + Symbol: .debug_line_str + Type: R_X86_64_32 + - Offset: 0x2E + Symbol: .debug_line_str + Type: R_X86_64_32 + Addend: 3 + - Offset: 0x48 + Symbol: .text + Type: R_X86_64_64 + - Name: .llvm_addrsig + Type: SHT_LLVM_ADDRSIG + Flags: [ SHF_EXCLUDE ] + Link: .symtab + AddressAlign: 0x1 + Symbols: [ _Z3foov ] + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .debug_abbrev + - Name: .debug_info + - Name: .rela.debug_info + - Name: .debug_str_offsets + - Name: .rela.debug_str_offsets + - Name: .debug_str + - Name: .debug_addr + - Name: .rela.debug_addr + - Name: .debug_gnu_pubnames + - Name: .rela.debug_gnu_pubnames + - Name: .debug_gnu_pubtypes + - Name: .rela.debug_gnu_pubtypes + - Name: .comment + - Name: .note.GNU-stack + - Name: .eh_frame + - Name: .rela.eh_frame + - Name: .debug_line + - Name: .rela.debug_line + - Name: .debug_line_str + - Name: .llvm_addrsig + - Name: .symtab +Symbols: + - Name: dump_dwo.cpp + Type: STT_FILE + Index: SHN_ABS + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .debug_abbrev + Type: STT_SECTION + Section: .debug_abbrev + - Name: .debug_info + Type: STT_SECTION + Section: .debug_info + - Name: .debug_str_offsets + Type: STT_SECTION + Section: .debug_str_offsets + - Name: .debug_str + Type: STT_SECTION + Section: .debug_str + - Name: .debug_addr + Type: STT_SECTION + Section: .debug_addr + - Name: .debug_line + Type: STT_SECTION + Section: .debug_line + - Name: .debug_line_str + Type: STT_SECTION + Section: .debug_line_str + - Name: _Z3foov + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Size: 0x8 + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x10 + Size: 0x23 +DWARF: + debug_str: + - './' + - './dump_dwo.dwo' + debug_addr: + - Length: 0x14 + Version: 0x5 + AddressSize: 0x8 + Entries: + - {} + - Address: 0x10 +... diff --git a/llvm/test/tools/llvm-dwarfdump/dump_dwo.test b/llvm/test/tools/llvm-dwarfdump/dump_dwo.test new file mode 100644 index 0000000000000..a42499003dce9 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/dump_dwo.test @@ -0,0 +1,149 @@ +## Check that llvm-dwarfdump works when dumping .o files with .dwo files. + +# RUN: yaml2obj %p/Inputs/dump_dwo.o.yaml -o %T/dump_dwo.o +# RUN: yaml2obj %p/Inputs/dump_dwo.dwo.yaml -o %T/dump_dwo.dwo +## We need to be in the same directory so we can find .dwo file +# RUN: cd %T +# RUN: llvm-dwarfdump --dwo dump_dwo.o | FileCheck %s +# RUN: llvm-dwarfdump --dwo --name int --name char dump_dwo.o | FileCheck %s --check-prefix=NAMES +# RUN: llvm-dwarfdump --name int --name char dump_dwo.o | FileCheck %s --check-prefix=NAMES_NO_DWO +# RUN: llvm-dwarfdump --dwo --lookup 0x10 dump_dwo.o | FileCheck %s --check-prefix=LOOKUP +# RUN: llvm-dwarfdump --lookup 0x10 dump_dwo.o | FileCheck %s --check-prefix=LOOKUP_NO_DWO + + +## Make sure if we dump dump_dwo.o with the --dwo option that we see the +## contents of the dump_dwo.o _and_ the dump_dwo.dwo file. + +# CHECK: .debug_info contents: +# CHECK: 0x00000000: Compile Unit: length = 0x00000024, format = DWARF32, version = 0x0005, unit_type = DW_UT_skeleton, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = 0x376dd35da7c3c136 (next unit at 0x00000028) + +# CHECK: 0x00000014: DW_TAG_skeleton_unit +# CHECK: DW_AT_stmt_list (0x00000000) +# CHECK: DW_AT_str_offsets_base (0x00000008) +# CHECK: DW_AT_comp_dir ("./") +# CHECK: DW_AT_GNU_pubnames (true) +# CHECK: DW_AT_dwo_name ("./dump_dwo.dwo") +# CHECK: DW_AT_low_pc (0x0000000000000000) +# CHECK: DW_AT_high_pc (0x0000000000000033) +# CHECK: DW_AT_addr_base (0x00000008) + +# CHECK: 0x00000014: DW_TAG_compile_unit +# CHECK: DW_AT_producer ("Apple clang version 15.0.0 (clang-1500.1.0.2.5)") +# CHECK: DW_AT_language (DW_LANG_C_plus_plus) +# CHECK: DW_AT_name ("dump_dwo.cpp") +# CHECK: DW_AT_dwo_name ("./dump_dwo.dwo") + +# CHECK: 0x0000001a: DW_TAG_subprogram +# CHECK: DW_AT_low_pc (0x0000000000000000) +# CHECK: DW_AT_high_pc (0x0000000000000008) +# CHECK: DW_AT_frame_base (DW_OP_reg6 RBP) +# CHECK: DW_AT_linkage_name ("_Z3foov") +# CHECK: DW_AT_name ("foo") +# CHECK: DW_AT_decl_file (0x00) +# CHECK: DW_AT_decl_line (2) +# CHECK: DW_AT_type (0x00000050 "int") +# CHECK: DW_AT_external (true) + +# CHECK: 0x0000002a: DW_TAG_subprogram +# CHECK: DW_AT_low_pc (0x0000000000000010) +# CHECK: DW_AT_high_pc (0x0000000000000033) +# CHECK: DW_AT_frame_base (DW_OP_reg6 RBP) +# CHECK: DW_AT_name ("main") +# CHECK: DW_AT_decl_file (0x00) +# CHECK: DW_AT_decl_line (6) +# CHECK: DW_AT_type (0x00000050 "int") +# CHECK: DW_AT_external (true) + +# CHECK: 0x00000039: DW_TAG_formal_parameter +# CHECK: DW_AT_location (DW_OP_fbreg -8) +# CHECK: DW_AT_name ("argc") +# CHECK: DW_AT_decl_file (0x00) +# CHECK: DW_AT_decl_line (6) +# CHECK: DW_AT_type (0x00000050 "int") + +# CHECK: 0x00000044: DW_TAG_formal_parameter +# CHECK: DW_AT_location (DW_OP_fbreg -16) +# CHECK: DW_AT_name ("argv") +# CHECK: DW_AT_decl_file (0x00) +# CHECK: DW_AT_decl_line (6) +# CHECK: DW_AT_type (0x00000054 "const char **") + +# CHECK: 0x0000004f: NULL + +# CHECK: 0x00000050: DW_TAG_base_type +# CHECK: DW_AT_name ("int") +# CHECK: DW_AT_encoding (DW_ATE_signed) +# CHECK: DW_AT_byte_size (0x04) + +# CHECK: 0x00000054: DW_TAG_pointer_type +# CHECK: DW_AT_type (0x00000059 "const char *") + +# CHECK: 0x00000059: DW_TAG_pointer_type +# CHECK: DW_AT_type (0x0000005e "const char") + +# CHECK: 0x0000005e: DW_TAG_const_type +# CHECK: DW_AT_type (0x00000063 "char") + +# CHECK: 0x00000063: DW_TAG_base_type +# CHECK: DW_AT_name ("char") +# CHECK: DW_AT_encoding (DW_ATE_signed_char) +# CHECK: DW_AT_byte_size (0x01) + +# CHECK: 0x00000067: NULL + + +## Make sure that if we do specify the --dwo when using --name that we get +## the expected results form the .dwo file + +# NAMES: 0x00000050: DW_TAG_base_type +# NAMES: DW_AT_name ("int") +# NAMES: DW_AT_encoding (DW_ATE_signed) +# NAMES: DW_AT_byte_size (0x04) + +# NAMES: 0x00000063: DW_TAG_base_type +# NAMES: DW_AT_name ("char") +# NAMES: DW_AT_encoding (DW_ATE_signed_char) +# NAMES: DW_AT_byte_size (0x01) + +## Make sure that if we don't specify the --dwo when using --name that we get +## no results + +# NAMES_NO_DWO-NOT: 0x00000050: DW_TAG_base_type +# NAMES_NO_DWO-NOT: 0x00000063: DW_TAG_base_type + +## Make sure address lookups succeed when using the --dwo option and the +## --lookup option. Verify that we see the information from the .dwo file which +## means "unit_type = DW_UT_split_compile" and that we see a DW_TAG_compile_unit +# LOOKUP: 0x00000000: Compile Unit: length = 0x00000064, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = 0x376dd35da7c3c136 (next unit at 0x00000068) + +# LOOKUP: 0x00000014: DW_TAG_compile_unit +# LOOKUP: DW_AT_producer ("Apple clang version 15.0.0 (clang-1500.1.0.2.5)") +# LOOKUP: DW_AT_language (DW_LANG_C_plus_plus) +# LOOKUP: DW_AT_name ("dump_dwo.cpp") +# LOOKUP: DW_AT_dwo_name ("./dump_dwo.dwo") + +# LOOKUP: 0x0000002a: DW_TAG_subprogram +# LOOKUP: DW_AT_low_pc (0x0000000000000010) +# LOOKUP: DW_AT_high_pc (0x0000000000000033) +# LOOKUP: DW_AT_frame_base (DW_OP_reg6) +# LOOKUP: DW_AT_name ("main") +# LOOKUP: DW_AT_decl_file (0x00) +# LOOKUP: DW_AT_decl_line (6) +# LOOKUP: DW_AT_type (0x00000050 "int") +# LOOKUP: DW_AT_external (true) + +## Make sure address lookups succeed when not using the --dwo option and the +## --lookup option. Verify that we see the information from the .o file which +## Means "unit_type = DW_UT_skeleton" and that we see a DW_TAG_skeleton_unit + +# LOOKUP_NO_DWO: 0x00000000: Compile Unit: length = 0x00000024, format = DWARF32, version = 0x0005, unit_type = DW_UT_skeleton, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = 0x376dd35da7c3c136 (next unit at 0x00000028) + +# LOOKUP_NO_DWO: 0x00000014: DW_TAG_skeleton_unit +# LOOKUP_NO_DWO: DW_AT_stmt_list (0x00000000) +# LOOKUP_NO_DWO: DW_AT_str_offsets_base (0x00000008) +# LOOKUP_NO_DWO: DW_AT_comp_dir ("./") +# LOOKUP_NO_DWO: DW_AT_GNU_pubnames (true) +# LOOKUP_NO_DWO: DW_AT_dwo_name ("./dump_dwo.dwo") +# LOOKUP_NO_DWO: DW_AT_low_pc (0x0000000000000000) +# LOOKUP_NO_DWO: DW_AT_high_pc (0x0000000000000033) +# LOOKUP_NO_DWO: DW_AT_addr_base (0x00000008) diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 8180ad2138f41..941df4eb18445 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -181,6 +181,13 @@ static opt FindAllApple( static opt IgnoreCase("ignore-case", desc("Ignore case distinctions when using --name."), value_desc("i"), cat(DwarfDumpCategory)); +static opt DumpNonSkeleton( + "dwo", + desc("Dump the non skeleton DIE in the .dwo or .dwp file after dumping the " + "skeleton DIE from the main executable. This allows dumping the .dwo " + "files with resolved addresses."), + value_desc("d"), cat(DwarfDumpCategory)); + static alias IgnoreCaseAlias("i", desc("Alias for --ignore-case."), aliasopt(IgnoreCase), cl::NotHidden); static list Name( @@ -315,6 +322,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) { DumpOpts.ShowForm = ShowForm; DumpOpts.SummarizeTypes = SummarizeTypes; DumpOpts.Verbose = Verbose; + DumpOpts.DumpNonSkeleton = DumpNonSkeleton; DumpOpts.RecoverableErrorHandler = C.getRecoverableErrorHandler(); // In -verify mode, print DIEs without children in error messages. if (Verify) { @@ -390,15 +398,27 @@ static void filterByName( const StringSet<> &Names, DWARFContext::unit_iterator_range CUs, raw_ostream &OS, std::function GetNameForDWARFReg) { - for (const auto &CU : CUs) - for (const auto &Entry : CU->dies()) { - DWARFDie Die = {CU.get(), &Entry}; + auto filterDieNames = [&](DWARFUnit *Unit) { + for (const auto &Entry : Unit->dies()) { + DWARFDie Die = {Unit, &Entry}; if (const char *Name = Die.getName(DINameKind::ShortName)) if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg)) continue; if (const char *Name = Die.getName(DINameKind::LinkageName)) filterByName(Names, Die, Name, OS, GetNameForDWARFReg); } + }; + for (const auto &CU : CUs) { + filterDieNames(CU.get()); + if (DumpNonSkeleton) { + // If we have split DWARF, then recurse down into the .dwo files as well. + DWARFDie CUDie = CU->getUnitDIE(false); + DWARFDie CUNonSkeletonDie = CU->getNonSkeletonUnitDIE(false); + // If we have a DWO file, we need to search it as well + if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) + filterDieNames(CUNonSkeletonDie.getDwarfUnit()); + } + } } static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel, @@ -499,7 +519,7 @@ static void findAllApple( /// information or probably display all matched entries, or something else... static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) { - auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup); + auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup, DumpNonSkeleton); if (!DIEsForAddr) return false;