From 932c395059ba284a529934be82639eaa9b5eaf07 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 27 Sep 2017 09:33:36 +0000 Subject: [PATCH] [dwarfdump] Add support for -debug-loc=OFFSET This patch adds support for passing an offset to -debug-loc. Differential revision: https://reviews.llvm.org/D38237 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314286 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h | 14 +- lib/DebugInfo/DWARF/DWARFContext.cpp | 4 +- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 50 +++- .../llvm-dwarfdump/X86/debug_loc_offset.test | 17 ++ test/tools/llvm-dwarfdump/X86/debugloc.s | 277 ++++++++++++++++++ 5 files changed, 353 insertions(+), 9 deletions(-) create mode 100644 test/tools/llvm-dwarfdump/X86/debug_loc_offset.test create mode 100644 test/tools/llvm-dwarfdump/X86/debugloc.s diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index 892627bd527..a6d319a9045 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -58,12 +58,16 @@ private: public: /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo) const; + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + Optional Offset) const; /// Parse the debug_loc section accessible via the 'data' parameter using the /// address size also given in 'data' to interpret the address ranges. void parse(const DWARFDataExtractor &data); - + + /// Return the location list at the given offset or nullptr. + LocationList const *getLocationListAtOffset(uint64_t Offset) const; + Optional parseOneLocationList(DWARFDataExtractor Data, uint32_t *Offset); }; @@ -94,7 +98,11 @@ private: public: void parse(DataExtractor data); - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo) const; + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + Optional Offset) const; + + /// Return the location list at the given offset or nullptr. + LocationList const *getLocationListAtOffset(uint64_t Offset) const; static Optional parseOneLocationList(DataExtractor Data, uint32_t *Offset); diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 156c65ad92a..8bb47c94d54 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -291,11 +291,11 @@ void DWARFContext::dump( if (shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo()); + getDebugLoc()->dump(OS, getRegisterInfo(), DumpOffset); } if (shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, DObj->getLocDWOSection().Data)) { - getDebugLocDWO()->dump(OS, getRegisterInfo()); + getDebugLocDWO()->dump(OS, getRegisterInfo(), DumpOffset); } if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, diff --git a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index 68bc0e51306..58f88536f31 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -50,11 +50,32 @@ void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, } } -void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const { - for (const LocationList &L : Locations) { +DWARFDebugLoc::LocationList const * +DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { + auto It = std::lower_bound( + Locations.begin(), Locations.end(), Offset, + [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); + if (It != Locations.end() && It->Offset == Offset) + return &(*It); + return nullptr; +} + +void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + Optional Offset) const { + auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); L.dump(OS, IsLittleEndian, AddressSize, MRI, 12); OS << "\n\n"; + }; + + if (Offset) { + if (auto *L = getLocationListAtOffset(*Offset)) + DumpLocationList(*L); + return; + } + + for (const LocationList &L : Locations) { + DumpLocationList(L); } } @@ -161,6 +182,16 @@ void DWARFDebugLocDWO::parse(DataExtractor data) { } } +DWARFDebugLocDWO::LocationList const * +DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const { + auto It = std::lower_bound( + Locations.begin(), Locations.end(), Offset, + [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); + if (It != Locations.end() && It->Offset == Offset) + return &(*It); + return nullptr; +} + void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, @@ -173,10 +204,21 @@ void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, } } -void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const { - for (const LocationList &L : Locations) { +void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + Optional Offset) const { + auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12); OS << "\n\n"; + }; + + if (Offset) { + if (auto *L = getLocationListAtOffset(*Offset)) + DumpLocationList(*L); + return; + } + + for (const LocationList &L : Locations) { + DumpLocationList(L); } } diff --git a/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test b/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test new file mode 100644 index 00000000000..da403735c96 --- /dev/null +++ b/test/tools/llvm-dwarfdump/X86/debug_loc_offset.test @@ -0,0 +1,17 @@ +RUN: llvm-mc %S/debugloc.s -filetype obj -triple x86_64-linux-elf -o - \ +RUN: | llvm-dwarfdump --debug-loc=0 - \ +RUN: | FileCheck %s --check-prefix=CHECK-A + +# CHECK-A: .debug_loc contents: +# CHECK-A: 0x00000000: +# CHECK-A-NEXT: 0x0000000000000000 - 0x0000000000000003: DW_OP_reg5 RDI +# CHECK-A-NEXT: 0x0000000000000003 - 0x0000000000000004: DW_OP_reg0 RAX + +RUN: llvm-mc %S/debugloc.s -filetype obj -triple x86_64-linux-elf -o - \ +RUN: | llvm-dwarfdump --debug-loc=0x36 - \ +RUN: | FileCheck %s --check-prefix=CHECK-B + +# CHECK-B: .debug_loc contents: +# CHECK-B: 0x00000036: +# CHECK-B-NEXT: 0x0000000000000010 - 0x0000000000000013: DW_OP_reg5 RDI +# CHECK-B-NEXT: 0x0000000000000013 - 0x0000000000000014: DW_OP_reg0 RAX diff --git a/test/tools/llvm-dwarfdump/X86/debugloc.s b/test/tools/llvm-dwarfdump/X86/debugloc.s new file mode 100644 index 00000000000..9dc266a1264 --- /dev/null +++ b/test/tools/llvm-dwarfdump/X86/debugloc.s @@ -0,0 +1,277 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-linux-elf -o - \ +# RUN: | llvm-dwarfdump --debug-loc - \ +# RUN: | FileCheck %s + +# CHECK: .debug_loc contents: + +# CHECK: 0x00000000: +# CHECK-NEXT: 0x0000000000000000 - 0x0000000000000003: DW_OP_reg5 RDI +# CHECK-NEXT: 0x0000000000000003 - 0x0000000000000004: DW_OP_reg0 RAX + +# CHECK: 0x00000036: +# CHECK-NEXT: 0x0000000000000010 - 0x0000000000000013: DW_OP_reg5 RDI +# CHECK-NEXT: 0x0000000000000013 - 0x0000000000000014: DW_OP_reg0 RAX + +# Source: +# int* foo(int* i) { return i; } +# int* bar(int* i) { return i; } +# Compile with: +# clang -g -O3 test.c -S -o debugloc.s + + .text + .file "test.c" + .globl foo + .align 16, 0x90 + .type foo,@function +foo: # @foo +.Lfunc_begin0: + .file 1 "test.c" + .loc 1 1 0 # test.c:1:0 + .cfi_startproc +# BB#0: + #DEBUG_VALUE: foo:i <- %RDI + .loc 1 2 3 prologue_end # test.c:2:3 + movq %rdi, %rax +.Ltmp0: + #DEBUG_VALUE: foo:i <- %RAX + retq +.Ltmp1: +.Lfunc_end0: + .size foo, .Lfunc_end0-foo + .cfi_endproc + + .globl bar + .align 16, 0x90 + .type bar,@function +bar: # @bar +.Lfunc_begin1: + .loc 1 5 0 # test.c:5:0 + .cfi_startproc +# BB#0: + #DEBUG_VALUE: bar:i <- %RDI + .loc 1 6 3 prologue_end # test.c:6:3 + movq %rdi, %rax +.Ltmp2: + #DEBUG_VALUE: bar:i <- %RAX + retq +.Ltmp3: +.Lfunc_end1: + .size bar, .Lfunc_end1-bar + .cfi_endproc + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)" # string offset=0 +.Linfo_string1: + .asciz "test.c" # string offset=54 +.Linfo_string2: + .asciz "/tmp" # string offset=61 +.Linfo_string3: + .asciz "foo" # string offset=66 +.Linfo_string4: + .asciz "int" # string offset=70 +.Linfo_string5: + .asciz "bar" # string offset=74 +.Linfo_string6: + .asciz "i" # string offset=78 + .section .debug_loc,"",@progbits +.Ldebug_loc0: + .quad .Lfunc_begin0-.Lfunc_begin0 + .quad .Ltmp0-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # DW_OP_reg5 + .quad .Ltmp0-.Lfunc_begin0 + .quad .Lfunc_end0-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 80 # DW_OP_reg0 + .quad 0 + .quad 0 +.Ldebug_loc1: + .quad .Lfunc_begin1-.Lfunc_begin0 + .quad .Ltmp2-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # DW_OP_reg5 + .quad .Ltmp2-.Lfunc_begin0 + .quad .Lfunc_end1-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 80 # DW_OP_reg0 + .quad 0 + .quad 0 + .section .debug_abbrev,"",@progbits +.Lsection_abbrev: + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\341\177" # DW_AT_APPLE_optimized + .byte 25 # DW_FORM_flag_present + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\347\177" # DW_AT_APPLE_omit_frame_ptr + .byte 25 # DW_FORM_flag_present + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 39 # DW_AT_prototyped + .byte 25 # DW_FORM_flag_present + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .ascii "\341\177" # DW_AT_APPLE_optimized + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lsection_info: +.Lcu_begin0: + .long 133 # Length of Unit + .short 4 # DWARF version number + .long .Lsection_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x7e DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + # DW_AT_APPLE_optimized + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + # DW_AT_APPLE_omit_frame_ptr + .byte 1 # DW_AT_frame_base + .byte 87 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_prototyped + .long 124 # DW_AT_type + # DW_AT_external + # DW_AT_APPLE_optimized + .byte 3 # Abbrev [3] 0x43:0xf DW_TAG_formal_parameter + .long .Ldebug_loc0 # DW_AT_location + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 124 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 2 # Abbrev [2] 0x53:0x29 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + # DW_AT_APPLE_omit_frame_ptr + .byte 1 # DW_AT_frame_base + .byte 87 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + # DW_AT_prototyped + .long 124 # DW_AT_type + # DW_AT_external + # DW_AT_APPLE_optimized + .byte 3 # Abbrev [3] 0x6c:0xf DW_TAG_formal_parameter + .long .Ldebug_loc1 # DW_AT_location + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .long 124 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x7c:0x5 DW_TAG_pointer_type + .long 129 # DW_AT_type + .byte 5 # Abbrev [5] 0x81:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark + .section .debug_ranges,"",@progbits +.Ldebug_range: + .section .debug_macinfo,"",@progbits + .byte 0 # End Of Macro List Mark + .section .debug_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_begin0 # Length of Public Names Info +.LpubNames_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 137 # Compilation Unit Length + .long 42 # DIE offset + .asciz "foo" # External Name + .long 83 # DIE offset + .asciz "bar" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_begin0 # Length of Public Types Info +.LpubTypes_begin0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 137 # Compilation Unit Length + .long 129 # DIE offset + .asciz "int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + + .ident "clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: