lldb: Add support for printing variables with DW_AT_ranges on DW_TAG_subprograms
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 5 Jan 2021 06:48:54 +0000 (22:48 -0800)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 25 Jan 2021 02:39:06 +0000 (18:39 -0800)
Finishing out the support (to the best of my knowledge/based on current
testing running the whole check-lldb with a clang forcibly using
DW_AT_ranges on all DW_TAG_subprograms) for this feature.

Differential Revision: https://reviews.llvm.org/D94064

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/test/Shell/SymbolFile/DWARF/Inputs/subprogram_ranges.s
lldb/test/Shell/SymbolFile/DWARF/subprogram_ranges.test

index afad21a..3656c73 100644 (file)
@@ -35,6 +35,7 @@
 #include "lldb/Interpreter/OptionValueProperties.h"
 
 #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h"
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Symbol/Block.h"
 #include "lldb/Symbol/CompileUnit.h"
@@ -3040,8 +3041,12 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
     if (sc.function) {
       DWARFDIE function_die = GetDIE(sc.function->GetID());
 
-      const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress(
-          DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+      dw_addr_t func_lo_pc = LLDB_INVALID_ADDRESS;
+      DWARFRangeList ranges;
+      if (function_die.GetDIE()->GetAttributeAddressRanges(
+              function_die.GetCU(), ranges,
+              /*check_hi_lo_pc=*/true))
+        func_lo_pc = ranges.GetMinRangeBase(0);
       if (func_lo_pc != LLDB_INVALID_ADDRESS) {
         const size_t num_variables = ParseVariables(
             sc, function_die.GetFirstChild(), func_lo_pc, true, true);
index 1ff883c..4dd398d 100644 (file)
@@ -1,32 +1,53 @@
        .text
-       .file   "main.c"
+       .file   "subprogram_ranges.c"
        .globl  main                            # -- Begin function main
        .p2align        4, 0x90
        .type   main,@function
 main:                                   # @main
 .Lfunc_begin0:
-       .file   1 "/usr/local/google/home/blaikie/dev/scratch" "main.c"
-       .loc    1 1 0                           # main.c:1:0
+       .file   1 "/usr/local/google/home/blaikie/dev/scratch" "subprogram_ranges.c"
+       .loc    1 2 0                           # subprogram_ranges.c:2:0
        .cfi_startproc
 # %bb.0:                                # %entry
-       pushq   %rbp
-       .cfi_def_cfa_offset 16
-       .cfi_offset %rbp, -16
-       movq    %rsp, %rbp
-       .cfi_def_cfa_register %rbp
-       xorl    %eax, %eax
+       #DEBUG_VALUE: main:var <- 3
+       .loc    1 4 5 prologue_end              # subprogram_ranges.c:4:5
+       movl    $1, i(%rip)
 .Ltmp0:
-       .loc    1 2 7 prologue_end              # main.c:2:7
-       movl    $3, -4(%rbp)
-       .loc    1 3 1                           # main.c:3:1
-       popq    %rbp
-       .cfi_def_cfa %rsp, 8
+       #DEBUG_VALUE: main:var <- 5
+       .loc    1 6 5                           # subprogram_ranges.c:6:5
+       movl    $2, i(%rip)
+       .loc    1 7 1                           # subprogram_ranges.c:7:1
+       xorl    %eax, %eax
        retq
 .Ltmp1:
 .Lfunc_end0:
        .size   main, .Lfunc_end0-main
        .cfi_endproc
                                         # -- End function
+       .type   i,@object                       # @i
+       .bss
+       .globl  i
+       .p2align        2
+i:
+       .long   0                               # 0x0
+       .size   i, 4
+
+       .section        .debug_loc,"",@progbits
+.Ldebug_loc0:
+       .quad   .Lfunc_begin0-.Lfunc_begin0
+       .quad   .Ltmp0-.Lfunc_begin0
+       .short  3                               # Loc expr size
+       .byte   17                              # DW_OP_consts
+       .byte   3                               # 3
+       .byte   159                             # DW_OP_stack_value
+       .quad   .Ltmp0-.Lfunc_begin0
+       .quad   .Lfunc_end0-.Lfunc_begin0
+       .short  3                               # Loc expr size
+       .byte   17                              # DW_OP_consts
+       .byte   5                               # 5
+       .byte   159                             # DW_OP_stack_value
+       .quad   0
+       .quad   0
        .section        .debug_abbrev,"",@progbits
        .byte   1                               # Abbreviation Code
        .byte   17                              # DW_TAG_compile_unit
@@ -54,6 +75,8 @@ main:                                   # @main
        .byte   23                              # DW_FORM_sec_offset
        .byte   64                              # DW_AT_frame_base
        .byte   24                              # DW_FORM_exprloc
+       .ascii  "\227B"                         # DW_AT_GNU_all_call_sites
+       .byte   25                              # DW_FORM_flag_present
        .byte   3                               # DW_AT_name
        .byte   14                              # DW_FORM_strp
        .byte   58                              # DW_AT_decl_file
@@ -70,7 +93,7 @@ main:                                   # @main
        .byte   52                              # DW_TAG_variable
        .byte   0                               # DW_CHILDREN_no
        .byte   2                               # DW_AT_location
-       .byte   24                              # DW_FORM_exprloc
+       .byte   23                              # DW_FORM_sec_offset
        .byte   3                               # DW_AT_name
        .byte   14                              # DW_FORM_strp
        .byte   58                              # DW_AT_decl_file
@@ -100,7 +123,7 @@ main:                                   # @main
        .short  4                               # DWARF version number
        .long   .debug_abbrev                   # Offset Into Abbrev. Section
        .byte   8                               # Address Size (in bytes)
-       .byte   1                               # Abbrev [1] 0xb:0x47 DW_TAG_compile_unit
+       .byte   1                               # Abbrev [1] 0xb:0x48 DW_TAG_compile_unit
        .long   .Linfo_string0                  # DW_AT_producer
        .short  12                              # DW_AT_language
        .long   .Linfo_string1                  # DW_AT_name
@@ -108,25 +131,24 @@ main:                                   # @main
        .long   .Linfo_string2                  # DW_AT_comp_dir
        .quad   .Lfunc_begin0                   # DW_AT_low_pc
        .long   .Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
-       .byte   2                               # Abbrev [2] 0x2a:0x20 DW_TAG_subprogram
+       .byte   2                               # Abbrev [2] 0x2a:0x21 DW_TAG_subprogram
        .long   .Ldebug_ranges0                 # DW_AT_ranges
        .byte   1                               # DW_AT_frame_base
-       .byte   86
+       .byte   87
+                                        # DW_AT_GNU_all_call_sites
        .long   .Linfo_string3                  # DW_AT_name
        .byte   1                               # DW_AT_decl_file
-       .byte   1                               # DW_AT_decl_line
-       .long   74                              # DW_AT_type
+       .byte   2                               # DW_AT_decl_line
+       .long   75                              # DW_AT_type
                                         # DW_AT_external
-       .byte   3                               # Abbrev [3] 0x3b:0xe DW_TAG_variable
-       .byte   2                               # DW_AT_location
-       .byte   145
-       .byte   124
+       .byte   3                               # Abbrev [3] 0x3b:0xf DW_TAG_variable
+       .long   .Ldebug_loc0                    # DW_AT_location
        .long   .Linfo_string5                  # DW_AT_name
        .byte   1                               # DW_AT_decl_file
-       .byte   2                               # DW_AT_decl_line
-       .long   74                              # DW_AT_type
+       .byte   3                               # DW_AT_decl_line
+       .long   75                              # DW_AT_type
        .byte   0                               # End Of Children Mark
-       .byte   4                               # Abbrev [4] 0x4a:0x7 DW_TAG_base_type
+       .byte   4                               # Abbrev [4] 0x4b:0x7 DW_TAG_base_type
        .long   .Linfo_string4                  # DW_AT_name
        .byte   5                               # DW_AT_encoding
        .byte   4                               # DW_AT_byte_size
@@ -140,20 +162,20 @@ main:                                   # @main
        .quad   0
        .section        .debug_str,"MS",@progbits,1
 .Linfo_string0:
-       .asciz  "clang version 12.0.0 (git@github.com:llvm/llvm-project.git 1c15aa171b2f67d9198a8498945cbdb936c0cd3b)" # string offset=0
+       .asciz  "clang version 12.0.0 (git@github.com:llvm/llvm-project.git 439e8f6c05584c36ea3f79d9b83a78098d40e629)" # string offset=0
 .Linfo_string1:
-       .asciz  "main.c"                        # string offset=101
+       .asciz  "subprogram_ranges.c"           # string offset=101
 .Linfo_string2:
-       .asciz  "/usr/local/google/home/blaikie/dev/scratch" # string offset=108
+       .asciz  "/usr/local/google/home/blaikie/dev/scratch" # string offset=121
 .Linfo_string3:
-       .asciz  "main"                          # string offset=151
+       .asciz  "main"                          # string offset=164
 .Linfo_string4:
-       .asciz  "int"                           # string offset=156
+       .asciz  "int"                           # string offset=169
 .Linfo_string5:
-       .asciz  "var"                           # string offset=160
-       .ident  "clang version 12.0.0 (git@github.com:llvm/llvm-project.git 1c15aa171b2f67d9198a8498945cbdb936c0cd3b)"
+       .asciz  "var"                           # string offset=173
+       .ident  "clang version 12.0.0 (git@github.com:llvm/llvm-project.git 439e8f6c05584c36ea3f79d9b83a78098d40e629)"
        .section        ".note.GNU-stack","",@progbits
        .addrsig
+       .addrsig_sym i
        .section        .debug_line,"",@progbits
 .Lline_table_start0:
-
index 740cd35..858dfd7 100644 (file)
 # especially useful, but don't dismiss it as pointless just because it's a bit
 # weird.
 
+# * Using volatile writes to create instructions the location may be valid over
+# * Using two values for the variable so it is described by a location list,
+#   not a single location description
+# * Not using function calls, so that the function has no frame pointer
+#   initialization/no prologue instructions, so the location of "var" is valid
+#   at the start of the function, so 'image lookup -v -s main' will include it.
+#
+# Source:
+# __attribute__((nodebug)) volatile int i;
+# int main() {
+#   int var = 3;
+#   i = 1;
+#   var = 5;
+#   i = 2;
+# }
+
 b main
 # CHECK: (lldb) b main
-# CHECK-NEXT: Breakpoint 1: where = {{.*}}`main + 6 at main.c:2:7
+# CHECK-NEXT: Breakpoint 1: where = {{.*}}`main at subprogram_ranges.c:4:5
+
+image lookup -v -s main
+# CHECK: 1 symbols match 'main'
+# CHECK:  Variable: {{.*}}, name = "var", type = "int", {{.*}}, decl = subprogram_ranges.c:3