jarin created this revision.
jarin added a reviewer: labath.
jarin added a project: LLDB.
Herald added a subscriber: JDevlieghere.
jarin requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added subscribers: lldb-commits, sstefan1.
This change fixes a problem introduced by clang change
described by https://reviews.llvm.org/D95617 and described by
https://bugs.llvm.org/show_bug.cgi?id=50076#c6, where inlined
functions omit the unused parameters both in the stack trace
and in `frame var` command. With this change, the parameters
are listed correctly in the stack trace and in `frame var`
command (the included test tests `frame var`).
This change adds parsing of formal parameters from the abstract
version of inlined functions and use those formal parameters if
they are missing from the concrete version.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D110571
Files:
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
Index: lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/DWARF/x86/unused-inlined-params.test
@@ -0,0 +1,34 @@
+# UNSUPPORTED: system-darwin, system-windows
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -filetype=obj %S/Inputs/unused-inlined-params.s \
+# RUN: -triple x86_64-pc-linux -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %s -o exit | FileCheck %s
+
+breakpoint set -n f
+process launch
+
+# CHECK: Process {{.*}} stopped
+
+# Let us check that unused parameters (of an inlined function) are listed.
+frame variable
+# CHECK-LABEL: frame variable
+# CHECK: (void *) unused1 = <
+# CHECK: (int) used = 42
+# CHECK: (int) unused2 = <
+# CHECK: (int) partial = 1
+# CHECK: (int) unused3 = <
+
+# Step out of the live range of the 'partial' parameter.
+next
+next
+# Check the variable contents.
+frame variable
+# CHECK-LABEL: frame variable
+# CHECK: (void *) unused1 = <
+# CHECK: (int) used = 43
+# CHECK: (int) unused2 = <
+# CHECK: (int) partial = <
+# CHECK: (int) unused3 = <
Index: lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/DWARF/x86/Inputs/unused-inlined-params.s
@@ -0,0 +1,423 @@
+# Generated from the following program (with some pruning):
+#
+# 1 #include <stdio.h>
+# 2
+# 3 __attribute__((always_inline))
+# 4 void f(void* unused1, int used, int unused2, int partial, int unused3) {
+# 5 used += partial;
+# 6 printf("%i", partial);
+# 7 printf("%i", used);
+# 8 }
+# 9
+# 10 int main(int argc, char** argv) {
+# 11 f(argv, 42, 1, argc, 2);
+# 12 return 0;
+# 13 }
+ .text
+ .file "unused-inlined-params.c"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin1:
+ .file 1 "/example" "unused-inlined-params.c"
+ .loc 1 10 0 # unused-inlined-params.c:10:0
+ .cfi_startproc
+# %bb.0:
+ #DEBUG_VALUE: main:argc <- $edi
+ #DEBUG_VALUE: main:argv <- $rsi
+ #DEBUG_VALUE: f:partial <- $edi
+ pushq %rbx
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbx, -16
+ movl %edi, %esi
+.Lline5:
+ #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi
+ #DEBUG_VALUE: f:unused3 <- undef
+ #DEBUG_VALUE: f:unused2 <- undef
+ #DEBUG_VALUE: f:used <- 42
+ #DEBUG_VALUE: f:unused1 <- undef
+ #DEBUG_VALUE: f:partial <- $esi
+ #DEBUG_VALUE: main:argc <- $esi
+ .loc 1 5 8 prologue_end # unused-inlined-params.c:5:8
+ leal 42(%rsi), %ebx
+.Lline6:
+ #DEBUG_VALUE: f:used <- $ebx
+ .loc 1 6 3 # unused-inlined-params.c:6:3
+ movl $.L.str, %edi
+ # kill: def $esi killed $esi killed $rsi
+ xorl %eax, %eax
+ callq printf
+.Lline7:
+ .loc 1 7 3 # unused-inlined-params.c:7:3
+ movl $.L.str, %edi
+ movl %ebx, %esi
+ xorl %eax, %eax
+ callq printf
+.Lline12:
+ .loc 1 12 3 # unused-inlined-params.c:12:3
+ xorl %eax, %eax
+ popq %rbx
+.Lreturn1:
+ .cfi_def_cfa_offset 8
+ retq
+.Lfunc_end1:
+ .size main, .Lfunc_end1-main
+ .cfi_endproc
+ # -- End function
+# Dummy printf implementation.
+printf:
+ retq
+
+# Simple implementation of _start - set up argc, argv and tail-call main.
+ .globl _start
+ .p2align 4, 0x90
+ .type _start,@function
+_start:
+ movl (%rsp), %edi
+ leaq 4(%rsp), %rsi
+ jmp main
+
+ .type .L.str,@object # @.str
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "%i"
+ .size .L.str, 3
+
+ .section .debug_loc,"",@progbits
+.Ldebug_loc_argc:
+ .quad .Lfunc_begin1-.Lfunc_begin1
+ .quad .Lline5-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 85 # super-register DW_OP_reg5
+ .quad .Lline5-.Lfunc_begin1
+ .quad .Lline7-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .quad 0
+ .quad 0
+.Ldebug_loc3:
+ .quad .Lfunc_begin1-.Lfunc_begin1
+ .quad .Lline5-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 84 # DW_OP_reg4
+ .quad .Lline5-.Lfunc_begin1
+ .quad .Lfunc_end1-.Lfunc_begin1
+ .short 4 # Loc expr size
+ .byte 243 # DW_OP_GNU_entry_value
+ .byte 1 # 1
+ .byte 84 # DW_OP_reg4
+ .byte 159 # DW_OP_stack_value
+ .quad 0
+ .quad 0
+.Ldebug_loc4:
+ .quad .Lfunc_begin1-.Lfunc_begin1
+ .quad .Lline5-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 85 # super-register DW_OP_reg5
+ .quad .Lline5-.Lfunc_begin1
+ .quad .Lline7-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 84 # super-register DW_OP_reg4
+ .quad 0
+ .quad 0
+.Ldebug_loc5:
+ .quad .Lline5-.Lfunc_begin1
+ .quad .Lline6-.Lfunc_begin1
+ .short 3 # Loc expr size
+ .byte 17 # DW_OP_consts
+ .byte 42 # 42
+ .byte 159 # DW_OP_stack_value
+ .quad .Lline6-.Lfunc_begin1
+ .quad .Lreturn1-.Lfunc_begin1
+ .short 1 # Loc expr size
+ .byte 83 # super-register DW_OP_reg3
+ .quad 0
+ .quad 0
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .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
+ .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 4 # 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 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .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 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 32 # DW_AT_inline
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .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 7 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # 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 9 # 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
+ .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
+ .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
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 10 # 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 11 # Abbreviation Code
+ .byte 29 # DW_TAG_inlined_subroutine
+ .byte 1 # DW_CHILDREN_yes
+ .byte 49 # DW_AT_abstract_origin
+ .byte 19 # DW_FORM_ref4
+ .byte 17 # DW_AT_low_pc
+ .byte 1 # DW_FORM_addr
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .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 12 # 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 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x11c DW_TAG_compile_unit
+ .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
+ .quad .Lfunc_begin1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+.Ldebug_info_f:
+ .byte 5 # Abbrev [5] 0x5f:0x40 DW_TAG_subprogram
+ .long .Linfo_string3 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ # DW_AT_prototyped
+ # DW_AT_external
+ .byte 1 # DW_AT_inline
+.Ldebug_info_param1:
+ .byte 6 # Abbrev [6] 0x67:0xb DW_TAG_formal_parameter
+ .long .Linfo_string4 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long .Ldebug_info_void_ptr-.Lcu_begin0
+ # DW_AT_type
+.Ldebug_info_param2:
+ .byte 6 # Abbrev [6] 0x72:0xb DW_TAG_formal_parameter
+ .long .Linfo_string5 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+.Ldebug_info_param3:
+ .byte 6 # Abbrev [6] 0x7d:0xb DW_TAG_formal_parameter
+ .long .Linfo_string7 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+.Ldebug_info_param4:
+ .byte 6 # Abbrev [6] 0x88:0xb DW_TAG_formal_parameter
+ .long .Linfo_string8 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+.Ldebug_info_param5:
+ .byte 6 # Abbrev [6] 0x93:0xb DW_TAG_formal_parameter
+ .long .Linfo_string9 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+ .byte 0 # End Of Children Mark
+.Ldebug_info_void_ptr:
+ .byte 7 # Abbrev [7] 0x9f:0x1 DW_TAG_pointer_type
+.Ldebug_info_int:
+ .byte 8 # Abbrev [8] 0xa0:0x7 DW_TAG_base_type
+ .long .Linfo_string6 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0xa7:0x6e DW_TAG_subprogram
+ .quad .Lfunc_begin1 # DW_AT_low_pc
+ .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 87
+ # DW_AT_GNU_all_call_sites
+ .long .Linfo_string10 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 10 # DW_AT_decl_line
+ # DW_AT_prototyped
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+ # DW_AT_external
+ .byte 10 # Abbrev [10] 0xc0:0xf DW_TAG_formal_parameter
+ .long .Ldebug_loc_argc # DW_AT_location
+ .long .Linfo_string11 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 10 # DW_AT_decl_line
+ .long .Ldebug_info_int-.Lcu_begin0 # DW_AT_type
+ .byte 10 # Abbrev [10] 0xcf:0xf DW_TAG_formal_parameter
+ .long .Ldebug_loc3 # DW_AT_location
+ .long .Linfo_string12 # DW_AT_name
+ .byte 1 # DW_AT_decl_file
+ .byte 10 # DW_AT_decl_line
+ .long .Ldebug_info_char_ptr_ptr-.Lcu_begin0
+ # DW_AT_type
+ .byte 11 # Abbrev [11] 0xde:0x36 DW_TAG_inlined_subroutine
+ .long .Ldebug_info_f-.Lcu_begin0
+ # DW_AT_abstract_origin
+ .quad .Lline5 # DW_AT_low_pc
+ .long .Lline12-.Lline5 # DW_AT_high_pc
+ .byte 1 # DW_AT_call_file
+ .byte 11 # DW_AT_call_line
+ .byte 3 # DW_AT_call_column
+ .byte 4 # Abbrev [4] 0xf7:0x9 DW_TAG_formal_parameter
+ .long .Ldebug_loc5 # DW_AT_location
+ .long .Ldebug_info_param2-.Lcu_begin0
+ # DW_AT_abstract_origin
+ .byte 4 # Abbrev [4] 0x105:0x9 DW_TAG_formal_parameter
+ .long .Ldebug_loc4 # DW_AT_location
+ .long .Ldebug_info_param4-.Lcu_begin0
+ # DW_AT_abstract_origin
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+.Ldebug_info_char_ptr_ptr:
+ .byte 12 # Abbrev [12] 0x115:0x5 DW_TAG_pointer_type
+ .long .Ldebug_info_char_ptr-.Lcu_begin0
+ # DW_AT_type
+.Ldebug_info_char_ptr:
+ .byte 12 # Abbrev [12] 0x11a:0x5 DW_TAG_pointer_type
+ .long .Ldebug_info_char-.Lcu_begin0 # DW_AT_type
+.Ldebug_info_char:
+ .byte 8 # Abbrev [8] 0x11f:0x7 DW_TAG_base_type
+ .long .Linfo_string13 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string1:
+ .asciz "unused-inlined-params.c" # string offset=30
+.Linfo_string2:
+ .asciz "/usr/local/google/home/jarin/projects/emsample/ccpp" # string offset=54
+.Linfo_string3:
+ .asciz "f" # string offset=106
+.Linfo_string4:
+ .asciz "unused1" # string offset=108
+.Linfo_string5:
+ .asciz "used" # string offset=116
+.Linfo_string6:
+ .asciz "int" # string offset=121
+.Linfo_string7:
+ .asciz "unused2" # string offset=125
+.Linfo_string8:
+ .asciz "partial" # string offset=133
+.Linfo_string9:
+ .asciz "unused3" # string offset=141
+.Linfo_string10:
+ .asciz "main" # string offset=149
+.Linfo_string11:
+ .asciz "argc" # string offset=154
+.Linfo_string12:
+ .asciz "argv" # string offset=159
+.Linfo_string13:
+ .asciz "char" # string offset=164
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -380,10 +380,9 @@
const DWARFDIE &die,
const lldb::addr_t func_low_pc);
- void
- ParseAndAppendGlobalVariable(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die,
- lldb_private::VariableList &cc_variable_list);
+ void ParseAndAppendGlobalVariable(
+ const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+ lldb_private::VariableList &cc_variable_list);
size_t ParseVariablesInFunctionContext(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3498,7 +3498,9 @@
return;
}
- // We haven't already parsed it, lets do that now.
+ // We haven't parsed the variable yet, lets do that now. Also, let us include
+ // the variable in the relevant compilation unit's variable list, if it
+ // exists.
VariableListSP variable_list_sp;
DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
dw_tag_t parent_tag = sc_parent_die.Tag();
@@ -3540,13 +3542,46 @@
if (!die || !sc.function)
return 0;
- const std::function<size_t(const DWARFDIE &, VariableListSP)>
+ using DIEVector = llvm::SmallVector<DWARFDIE, 2>;
+
+ const std::function<size_t(const DWARFDIE &, VariableListSP, DIEVector &,
+ size_t &)>
parse_recursive = [this, func_low_pc, &parse_recursive,
&sc](const DWARFDIE &die,
- VariableListSP variable_list_sp) -> size_t {
+ VariableListSP variable_list_sp,
+ DIEVector &abstract_formal_parameters,
+ size_t &abstract_parameter_index) -> size_t {
size_t vars_added = 0;
dw_tag_t tag = die.Tag();
+ // If we are parsing a formal parameter, let us make sure that we insert
+ // preceding abstract parameters if they were omitted from the concrete
+ // function instance.
+ if (tag == DW_TAG_formal_parameter) {
+ while (abstract_parameter_index <
+ abstract_formal_parameters.size()) {
+ const DWARFDIE &abstract_parameter =
+ abstract_formal_parameters[abstract_parameter_index++];
+ DWARFDIE parameter = die;
+ bool found = false;
+ while (parameter) {
+ parameter = parameter.GetReferencedDIE(DW_AT_abstract_origin);
+ if (parameter == abstract_parameter) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ VariableSP var_sp(ParseVariableDIE(sc, abstract_parameter, func_low_pc));
+ if (var_sp) {
+ variable_list_sp->AddVariableIfUnique(var_sp);
+ ++vars_added;
+ }
+ }
+ }
+
+ // If |die| is a variable, parse it and insert it.
if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
(tag == DW_TAG_formal_parameter)) {
VariableSP var_sp(ParseVariableDIE(sc, die, func_low_pc));
@@ -3560,7 +3595,8 @@
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
case DW_TAG_lexical_block: {
- // If we start a new block, compute a new block context and recurse.
+ // If we are starting a new block, compute a new block context and recurse
+ // in that context.
Block *block = sc.function->GetBlock(true).FindBlockByID(die.GetID());
if (block == nullptr) {
// This must be a specification or abstract origin with a
@@ -3584,11 +3620,46 @@
block_variable_list_sp = std::make_shared<VariableList>();
block->SetVariableList(block_variable_list_sp);
}
+
+ DIEVector block_abstract_formal_parameters;
+ if (tag == DW_TAG_inlined_subroutine) {
+ // Walk abstract origins until we find DW_TAG_subprogram and extract
+ // its formal parameters.
+ DWARFDIE abs_die = die;
+ while (abs_die && abs_die.Tag() != DW_TAG_subprogram) {
+ abs_die = abs_die.GetReferencedDIE(DW_AT_abstract_origin);
+ }
+ if (abs_die && abs_die.HasChildren()) {
+ for (DWARFDIE child = abs_die.GetFirstChild(); child;
+ child = child.GetSibling()) {
+ if (child.Tag() == DW_TAG_formal_parameter) {
+ block_abstract_formal_parameters.push_back(child);
+ }
+ }
+ }
+ }
+
+ size_t block_parameter_index = 0;
+ // Recursively parse children in the context of the block.
for (DWARFDIE child = die.GetFirstChild(); child;
child = child.GetSibling()) {
- vars_added += parse_recursive(child, block_variable_list_sp);
+ vars_added += parse_recursive(child, block_variable_list_sp,
+ block_abstract_formal_parameters,
+ block_parameter_index);
}
+ // If there any remaining abstract formal parameters, parse and insert
+ // them as well.
+ while (block_parameter_index < block_abstract_formal_parameters.size()) {
+ const DWARFDIE &abstract_parameter =
+ block_abstract_formal_parameters[block_parameter_index++];
+ VariableSP var_sp(
+ ParseVariableDIE(sc, abstract_parameter, func_low_pc));
+ if (var_sp) {
+ block_variable_list_sp->AddVariableIfUnique(var_sp);
+ ++vars_added;
+ }
+ }
break;
}
@@ -3596,9 +3667,10 @@
// Recurse to children with the same block context.
for (DWARFDIE child = die.GetFirstChild(); child;
child = child.GetSibling()) {
- vars_added += parse_recursive(child, variable_list_sp);
+ vars_added +=
+ parse_recursive(child, variable_list_sp, abstract_formal_parameters,
+ abstract_parameter_index);
}
-
break;
}
@@ -3608,7 +3680,11 @@
Block *block = sc.function->GetBlock(true).FindBlockByID(die.GetID());
const bool can_create = false;
VariableListSP variable_list_sp = block->GetBlockVariableList(can_create);
- return parse_recursive(die, variable_list_sp);
+ DIEVector block_abstract_formal_parameters;
+ size_t block_parameter_index = 0;
+ return parse_recursive(die, variable_list_sp,
+ block_abstract_formal_parameters,
+ block_parameter_index);
}
/// Collect call site parameters in a DW_TAG_call_site DIE.
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits