llvm-symbolizer: access the base address from the skeleton CU, not the split unit
authorDavid Blaikie <dblaikie@gmail.com>
Fri, 26 May 2023 00:59:40 +0000 (00:59 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Fri, 26 May 2023 00:59:40 +0000 (00:59 +0000)
In Split DWARF, if the unit had a non-trivial base address (a real
low_pc, rather than one with fixed value 0) then computing addresses
needs to access that base address to add to any base address-relative
values. But the code was trying to access the base address in the split
unit, when it's actually in the skeleton unit. So delegate to the
skeleton if it's available.

Fixes #62941

llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
llvm/test/tools/llvm-symbolizer/split-dwarf-base-addr.s [new file with mode: 0644]

index 2fc26fd..e2f17ca 100644 (file)
@@ -1049,7 +1049,7 @@ std::optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
   if (BaseAddr)
     return BaseAddr;
 
-  DWARFDie UnitDie = getUnitDIE();
+  DWARFDie UnitDie = (SU ? SU : this)->getUnitDIE();
   std::optional<DWARFFormValue> PC =
       UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
   BaseAddr = toSectionedAddress(PC);
diff --git a/llvm/test/tools/llvm-symbolizer/split-dwarf-base-addr.s b/llvm/test/tools/llvm-symbolizer/split-dwarf-base-addr.s
new file mode 100644 (file)
index 0000000..79481af
--- /dev/null
@@ -0,0 +1,351 @@
+# RUN: rm -rf %t
+# RUN: mkdir -p %t
+# RUN: llvm-mc %s -o %t/test.o -filetype=obj
+# RUN: cd %t
+
+# RUN: llvm-symbolizer -e test.o 0x30 | FileCheck %s
+
+# CHECK: f1()
+# CHECK: .{{/|\\}}test.cpp:6:3
+# CHECK: main
+# CHECK: .{{/|\\}}test.cpp:7:3
+
+
+       .text
+       .zero 42
+       .file   "test.cpp"
+       .file   0 "./" "test.cpp" md5 0x03b7c6de668697331888d80c6ad0d69e
+       .globl  main                            # -- Begin function main
+       .p2align        4, 0x90
+       .type   main,@function
+main:                                   # @main
+.Lfunc_begin0:
+       .cfi_startproc
+# %bb.0:                                # %entry
+       .loc    0 6 3 prologue_end              # test.cpp:6:3
+       incl    i(%rip)
+.Ltmp0:
+       .loc    0 3 3                           # test.cpp:3:3
+       incl    i(%rip)
+.Ltmp1:
+       .loc    0 8 1                           # test.cpp:8:1
+       xorl    %eax, %eax
+       retq
+.Ltmp2:
+.Lfunc_end0:
+       .size   main, .Lfunc_end0-main
+       .cfi_endproc
+                                        # -- End function
+       .type   i,@object                       # @i
+       .bss
+       .globl  i
+       .p2align        2, 0x0
+i:
+       .long   0                               # 0x0
+       .size   i, 4
+
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   74                              # DW_TAG_skeleton_unit
+       .byte   0                               # DW_CHILDREN_no
+       .byte   16                              # DW_AT_stmt_list
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   114                             # DW_AT_str_offsets_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   27                              # DW_AT_comp_dir
+       .byte   37                              # DW_FORM_strx1
+       .ascii  "\264B"                         # DW_AT_GNU_pubnames
+       .byte   25                              # DW_FORM_flag_present
+       .byte   118                             # DW_AT_dwo_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   115                             # DW_AT_addr_base
+       .byte   23                              # DW_FORM_sec_offset
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  5                               # DWARF version number
+       .byte   4                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   .debug_abbrev                   # Offset Into Abbrev. Section
+       .quad   6427667746655966506
+       .byte   1                               # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+       .long   .Lline_table_start0             # DW_AT_stmt_list
+       .long   .Lstr_offsets_base0             # DW_AT_str_offsets_base
+       .byte   0                               # DW_AT_comp_dir
+                                        # DW_AT_GNU_pubnames
+       .byte   1                               # DW_AT_dwo_name
+       .byte   1                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .long   .Laddr_table_base0              # DW_AT_addr_base
+.Ldebug_info_end0:
+       .section        .debug_str_offsets,"",@progbits
+       .long   12                              # Length of String Offsets Set
+       .short  5
+       .short  0
+.Lstr_offsets_base0:
+       .section        .debug_str,"MS",@progbits,1
+.Lskel_string0:
+       .asciz  "." # string offset=0
+.Lskel_string1:
+       .asciz  "test.o"                        # string offset=43
+       .section        .debug_str_offsets,"",@progbits
+       .long   .Lskel_string0
+       .long   .Lskel_string1
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   36                              # Length of String Offsets Set
+       .short  5
+       .short  0
+       .section        .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+       .asciz  "i"                             # string offset=0
+.Linfo_string1:
+       .asciz  "int"                           # string offset=2
+.Linfo_string2:
+       .asciz  "_Z2f1v"                        # string offset=6
+.Linfo_string3:
+       .asciz  "f1"                            # string offset=13
+.Linfo_string4:
+       .asciz  "main"                          # string offset=16
+.Linfo_string5:
+       .asciz  "clang version 17.0.0 (git@github.com:llvm/llvm-project.git 6963c61f0f6e4be2039cb45e824ea1e83a8f1526)" # string offset=21
+.Linfo_string6:
+       .asciz  "test.cpp"                      # string offset=122
+.Linfo_string7:
+       .asciz  "test.o"                        # string offset=131
+       .section        .debug_str_offsets.dwo,"e",@progbits
+       .long   0
+       .long   2
+       .long   6
+       .long   13
+       .long   16
+       .long   21
+       .long   122
+       .long   131
+       .section        .debug_info.dwo,"e",@progbits
+       .long   .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+       .short  5                               # DWARF version number
+       .byte   5                               # DWARF Unit Type
+       .byte   8                               # Address Size (in bytes)
+       .long   0                               # Offset Into Abbrev. Section
+       .quad   6427667746655966506
+       .byte   1                               # Abbrev [1] 0x14:0x39 DW_TAG_compile_unit
+       .byte   5                               # DW_AT_producer
+       .short  33                              # DW_AT_language
+       .byte   6                               # DW_AT_name
+       .byte   7                               # DW_AT_dwo_name
+       .byte   2                               # Abbrev [2] 0x1a:0xb DW_TAG_variable
+       .byte   0                               # DW_AT_name
+       .long   37                              # DW_AT_type
+                                        # DW_AT_external
+       .byte   0                               # DW_AT_decl_file
+       .byte   1                               # DW_AT_decl_line
+       .byte   2                               # DW_AT_location
+       .byte   161
+       .byte   0
+       .byte   3                               # Abbrev [3] 0x25:0x5 DW_TAG_volatile_type
+       .long   42                              # DW_AT_type
+       .byte   4                               # Abbrev [4] 0x2a:0x4 DW_TAG_base_type
+       .byte   1                               # DW_AT_name
+       .byte   5                               # DW_AT_encoding
+       .byte   4                               # DW_AT_byte_size
+       .byte   5                               # Abbrev [5] 0x2e:0x5 DW_TAG_subprogram
+       .byte   2                               # DW_AT_linkage_name
+       .byte   3                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   2                               # DW_AT_decl_line
+                                        # DW_AT_external
+                                        # DW_AT_inline
+       .byte   6                               # Abbrev [6] 0x33:0x19 DW_TAG_subprogram
+       .byte   1                               # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+       .byte   1                               # DW_AT_frame_base
+       .byte   87
+                                        # DW_AT_call_all_calls
+       .byte   4                               # DW_AT_name
+       .byte   0                               # DW_AT_decl_file
+       .byte   5                               # DW_AT_decl_line
+       .long   42                              # DW_AT_type
+                                        # DW_AT_external
+       .byte   7                               # Abbrev [7] 0x42:0x9 DW_TAG_inlined_subroutine
+       .long   46                              # DW_AT_abstract_origin
+       .byte   0                               # DW_AT_ranges
+       .byte   0                               # DW_AT_call_file
+       .byte   7                               # DW_AT_call_line
+       .byte   3                               # DW_AT_call_column
+       .byte   0                               # End Of Children Mark
+       .byte   0                               # End Of Children Mark
+.Ldebug_info_dwo_end0:
+       .section        .debug_abbrev.dwo,"e",@progbits
+       .byte   1                               # Abbreviation Code
+       .byte   17                              # DW_TAG_compile_unit
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   37                              # DW_AT_producer
+       .byte   37                              # DW_FORM_strx1
+       .byte   19                              # DW_AT_language
+       .byte   5                               # DW_FORM_data2
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   118                             # DW_AT_dwo_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   2                               # Abbreviation Code
+       .byte   52                              # DW_TAG_variable
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   73                              # DW_AT_type
+       .byte   19                              # DW_FORM_ref4
+       .byte   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   2                               # DW_AT_location
+       .byte   24                              # DW_FORM_exprloc
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   3                               # Abbreviation Code
+       .byte   53                              # DW_TAG_volatile_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   4                               # Abbreviation Code
+       .byte   36                              # DW_TAG_base_type
+       .byte   0                               # DW_CHILDREN_no
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .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   5                               # Abbreviation Code
+       .byte   46                              # DW_TAG_subprogram
+       .byte   0                               # DW_CHILDREN_no
+       .byte   110                             # DW_AT_linkage_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .byte   58                              # DW_AT_decl_file
+       .byte   11                              # DW_FORM_data1
+       .byte   59                              # DW_AT_decl_line
+       .byte   11                              # DW_FORM_data1
+       .byte   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   32                              # DW_AT_inline
+       .byte   33                              # DW_FORM_implicit_const
+       .byte   1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   6                               # Abbreviation Code
+       .byte   46                              # DW_TAG_subprogram
+       .byte   1                               # DW_CHILDREN_yes
+       .byte   17                              # DW_AT_low_pc
+       .byte   27                              # DW_FORM_addrx
+       .byte   18                              # DW_AT_high_pc
+       .byte   6                               # DW_FORM_data4
+       .byte   64                              # DW_AT_frame_base
+       .byte   24                              # DW_FORM_exprloc
+       .byte   122                             # DW_AT_call_all_calls
+       .byte   25                              # DW_FORM_flag_present
+       .byte   3                               # DW_AT_name
+       .byte   37                              # DW_FORM_strx1
+       .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   63                              # DW_AT_external
+       .byte   25                              # DW_FORM_flag_present
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   7                               # Abbreviation Code
+       .byte   29                              # DW_TAG_inlined_subroutine
+       .byte   0                               # DW_CHILDREN_no
+       .byte   49                              # DW_AT_abstract_origin
+       .byte   19                              # DW_FORM_ref4
+       .byte   85                              # DW_AT_ranges
+       .byte   35                              # DW_FORM_rnglistx
+       .byte   88                              # DW_AT_call_file
+       .byte   11                              # DW_FORM_data1
+       .byte   89                              # DW_AT_call_line
+       .byte   11                              # DW_FORM_data1
+       .byte   87                              # DW_AT_call_column
+       .byte   11                              # DW_FORM_data1
+       .byte   0                               # EOM(1)
+       .byte   0                               # EOM(2)
+       .byte   0                               # EOM(3)
+       .section        .debug_rnglists.dwo,"e",@progbits
+       .long   .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length
+.Ldebug_list_header_start0:
+       .short  5                               # Version
+       .byte   8                               # Address size
+       .byte   0                               # Segment selector size
+       .long   1                               # Offset entry count
+.Lrnglists_dwo_table_base0:
+       .long   .Ldebug_ranges0-.Lrnglists_dwo_table_base0
+.Ldebug_ranges0:
+       .byte   4                               # DW_RLE_offset_pair
+       .uleb128 .Ltmp0-.Lfunc_begin0           #   starting offset
+       .uleb128 .Ltmp1-.Lfunc_begin0           #   ending offset
+       .byte   0                               # DW_RLE_end_of_list
+.Ldebug_list_header_end0:
+       .section        .debug_addr,"",@progbits
+       .long   .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+       .short  5                               # DWARF version number
+       .byte   8                               # Address size
+       .byte   0                               # Segment selector size
+.Laddr_table_base0:
+       .quad   i
+       .quad   42
+.Ldebug_addr_end0:
+       .section        .debug_gnu_pubnames,"",@progbits
+       .long   .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info
+.LpubNames_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   40                              # Compilation Unit Length
+       .long   46                              # DIE offset
+       .byte   48                              # Attributes: FUNCTION, EXTERNAL
+       .asciz  "f1"                            # External Name
+       .long   26                              # DIE offset
+       .byte   32                              # Attributes: VARIABLE, EXTERNAL
+       .asciz  "i"                             # External Name
+       .long   51                              # DIE offset
+       .byte   48                              # Attributes: FUNCTION, EXTERNAL
+       .asciz  "main"                          # External Name
+       .long   0                               # End Mark
+.LpubNames_end0:
+       .section        .debug_gnu_pubtypes,"",@progbits
+       .long   .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info
+.LpubTypes_start0:
+       .short  2                               # DWARF Version
+       .long   .Lcu_begin0                     # Offset of Compilation Unit Info
+       .long   40                              # Compilation Unit Length
+       .long   42                              # DIE offset
+       .byte   144                             # Attributes: TYPE, STATIC
+       .asciz  "int"                           # External Name
+       .long   0                               # End Mark
+.LpubTypes_end0:
+       .ident  "clang version 17.0.0 (git@github.com:llvm/llvm-project.git 6963c61f0f6e4be2039cb45e824ea1e83a8f1526)"
+       .section        ".note.GNU-stack","",@progbits
+       .addrsig
+       .addrsig_sym i
+       .section        .debug_line,"",@progbits
+.Lline_table_start0: