@@ -3092,7 +3092,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
3092
3092
sc.comp_unit ->SetVariableList (variables);
3093
3093
3094
3094
m_index->GetGlobalVariables (*dwarf_cu, [&](DWARFDIE die) {
3095
- VariableSP var_sp (ParseVariableDIE (sc, die, LLDB_INVALID_ADDRESS ));
3095
+ VariableSP var_sp (ParseVariableDIECached (sc, die));
3096
3096
if (var_sp) {
3097
3097
variables->AddVariableIfUnique (var_sp);
3098
3098
++vars_added;
@@ -3106,6 +3106,26 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
3106
3106
return 0 ;
3107
3107
}
3108
3108
3109
+ VariableSP SymbolFileDWARF::ParseVariableDIECached (const SymbolContext &sc,
3110
+ const DWARFDIE &die) {
3111
+ if (!die)
3112
+ return nullptr ;
3113
+
3114
+ DIEToVariableSP &die_to_variable = die.GetDWARF ()->GetDIEToVariable ();
3115
+
3116
+ VariableSP var_sp = die_to_variable[die.GetDIE ()];
3117
+ if (var_sp)
3118
+ return var_sp;
3119
+
3120
+ var_sp = ParseVariableDIE (sc, die, LLDB_INVALID_ADDRESS);
3121
+ if (var_sp) {
3122
+ die_to_variable[die.GetDIE ()] = var_sp;
3123
+ if (DWARFDIE spec_die = die.GetReferencedDIE (DW_AT_specification))
3124
+ die_to_variable[spec_die.GetDIE ()] = var_sp;
3125
+ }
3126
+ return var_sp;
3127
+ }
3128
+
3109
3129
VariableSP SymbolFileDWARF::ParseVariableDIE (const SymbolContext &sc,
3110
3130
const DWARFDIE &die,
3111
3131
const lldb::addr_t func_low_pc) {
@@ -3115,9 +3135,6 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3115
3135
if (!die)
3116
3136
return nullptr ;
3117
3137
3118
- if (VariableSP var_sp = GetDIEToVariable ()[die.GetDIE ()])
3119
- return var_sp; // Already been parsed!
3120
-
3121
3138
const dw_tag_t tag = die.Tag ();
3122
3139
ModuleSP module = GetObjectFile ()->GetModule ();
3123
3140
@@ -3127,8 +3144,6 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3127
3144
3128
3145
DWARFAttributes attributes;
3129
3146
const size_t num_attributes = die.GetAttributes (attributes);
3130
- DWARFDIE spec_die;
3131
- VariableSP var_sp;
3132
3147
const char *name = nullptr ;
3133
3148
const char *mangled = nullptr ;
3134
3149
Declaration decl;
@@ -3175,9 +3190,6 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3175
3190
case DW_AT_location:
3176
3191
location_form = form_value;
3177
3192
break ;
3178
- case DW_AT_specification:
3179
- spec_die = form_value.Reference ();
3180
- break ;
3181
3193
case DW_AT_start_scope:
3182
3194
// TODO: Implement this.
3183
3195
break ;
@@ -3188,6 +3200,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3188
3200
case DW_AT_description:
3189
3201
case DW_AT_endianity:
3190
3202
case DW_AT_segment:
3203
+ case DW_AT_specification:
3191
3204
case DW_AT_visibility:
3192
3205
default :
3193
3206
case DW_AT_abstract_origin:
@@ -3380,7 +3393,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3380
3393
location.Update_DW_OP_addr (exe_file_addr);
3381
3394
} else {
3382
3395
// Variable didn't make it into the final executable
3383
- return var_sp ;
3396
+ return nullptr ;
3384
3397
}
3385
3398
}
3386
3399
}
@@ -3426,35 +3439,25 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
3426
3439
}
3427
3440
}
3428
3441
3429
- if (symbol_context_scope) {
3430
- auto type_sp = std::make_shared<SymbolFileType>(
3431
- *this , GetUID (type_die_form.Reference ()));
3432
-
3433
- if (use_type_size_for_value && type_sp->GetType ())
3434
- location.UpdateValue (
3435
- const_value_form.Unsigned (),
3436
- type_sp->GetType ()->GetByteSize (nullptr ).getValueOr (0 ),
3437
- die.GetCU ()->GetAddressByteSize ());
3438
-
3439
- var_sp = std::make_shared<Variable>(
3440
- die.GetID (), name, mangled, type_sp, scope, symbol_context_scope,
3441
- scope_ranges, &decl, location, is_external, is_artificial,
3442
- location_is_const_value_data, is_static_member);
3443
- } else {
3442
+ if (!symbol_context_scope) {
3444
3443
// Not ready to parse this variable yet. It might be a global or static
3445
3444
// variable that is in a function scope and the function in the symbol
3446
3445
// context wasn't filled in yet
3447
- return var_sp ;
3446
+ return nullptr ;
3448
3447
}
3449
- // Cache var_sp even if NULL (the variable was just a specification or was
3450
- // missing vital information to be able to be displayed in the debugger
3451
- // (missing location due to optimization, etc)) so we don't re-parse this
3452
- // DIE over and over later...
3453
- GetDIEToVariable ()[die.GetDIE ()] = var_sp;
3454
- if (spec_die)
3455
- GetDIEToVariable ()[spec_die.GetDIE ()] = var_sp;
3456
3448
3457
- return var_sp;
3449
+ auto type_sp = std::make_shared<SymbolFileType>(
3450
+ *this , GetUID (type_die_form.Reference ()));
3451
+
3452
+ if (use_type_size_for_value && type_sp->GetType ())
3453
+ location.UpdateValue (const_value_form.Unsigned (),
3454
+ type_sp->GetType ()->GetByteSize (nullptr ).getValueOr (0 ),
3455
+ die.GetCU ()->GetAddressByteSize ());
3456
+
3457
+ return std::make_shared<Variable>(
3458
+ die.GetID (), name, mangled, type_sp, scope, symbol_context_scope,
3459
+ scope_ranges, &decl, location, is_external, is_artificial,
3460
+ location_is_const_value_data, is_static_member);
3458
3461
}
3459
3462
3460
3463
DWARFDIE
@@ -3518,7 +3521,9 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable(
3518
3521
return ;
3519
3522
}
3520
3523
3521
- // We haven't already parsed it, lets do that now.
3524
+ // We haven't parsed the variable yet, lets do that now. Also, let us include
3525
+ // the variable in the relevant compilation unit's variable list, if it
3526
+ // exists.
3522
3527
VariableListSP variable_list_sp;
3523
3528
DWARFDIE sc_parent_die = GetParentSymbolContextDIE (die);
3524
3529
dw_tag_t parent_tag = sc_parent_die.Tag ();
@@ -3545,7 +3550,7 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable(
3545
3550
return ;
3546
3551
}
3547
3552
3548
- var_sp = ParseVariableDIE (sc, die, LLDB_INVALID_ADDRESS );
3553
+ var_sp = ParseVariableDIECached (sc, die);
3549
3554
if (!var_sp)
3550
3555
return ;
3551
3556
@@ -3554,32 +3559,109 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable(
3554
3559
variable_list_sp->AddVariableIfUnique (var_sp);
3555
3560
}
3556
3561
3562
+ DIEArray
3563
+ SymbolFileDWARF::MergeBlockAbstractParameters (const DWARFDIE &block_die,
3564
+ DIEArray &&variable_dies) {
3565
+ // DW_TAG_inline_subroutine objects may omit DW_TAG_formal_parameter in
3566
+ // instances of the function when they are unused (i.e., the parameter's
3567
+ // location list would be empty). The current DW_TAG_inline_subroutine may
3568
+ // refer to another DW_TAG_subprogram that might actually have the definitions
3569
+ // of the parameters and we need to include these so they show up in the
3570
+ // variables for this function (for example, in a stack trace). Let us try to
3571
+ // find the abstract subprogram that might contain the parameter definitions
3572
+ // and merge with the concrete parameters.
3573
+
3574
+ // Nothing to merge if the block is not an inlined function.
3575
+ if (block_die.Tag () != DW_TAG_inlined_subroutine) {
3576
+ return std::move (variable_dies);
3577
+ }
3578
+
3579
+ // Nothing to merge if the block does not have abstract parameters.
3580
+ DWARFDIE abs_die = block_die.GetReferencedDIE (DW_AT_abstract_origin);
3581
+ if (!abs_die || abs_die.Tag () != DW_TAG_subprogram ||
3582
+ !abs_die.HasChildren ()) {
3583
+ return std::move (variable_dies);
3584
+ }
3585
+
3586
+ // For each abstract parameter, if we have its concrete counterpart, insert
3587
+ // it. Otherwise, insert the abstract parameter.
3588
+ DIEArray::iterator concrete_it = variable_dies.begin ();
3589
+ DWARFDIE abstract_child = abs_die.GetFirstChild ();
3590
+ DIEArray merged;
3591
+ bool did_merge_abstract = false ;
3592
+ for (; abstract_child; abstract_child = abstract_child.GetSibling ()) {
3593
+ if (abstract_child.Tag () == DW_TAG_formal_parameter) {
3594
+ if (concrete_it == variable_dies.end () ||
3595
+ GetDIE (*concrete_it).Tag () != DW_TAG_formal_parameter) {
3596
+ // We arrived at the end of the concrete parameter list, so all
3597
+ // the remaining abstract parameters must have been omitted.
3598
+ // Let us insert them to the merged list here.
3599
+ merged.push_back (*abstract_child.GetDIERef ());
3600
+ did_merge_abstract = true ;
3601
+ continue ;
3602
+ }
3603
+
3604
+ DWARFDIE origin_of_concrete =
3605
+ GetDIE (*concrete_it).GetReferencedDIE (DW_AT_abstract_origin);
3606
+ if (origin_of_concrete == abstract_child) {
3607
+ // The current abstract paramater is the origin of the current
3608
+ // concrete parameter, just push the concrete parameter.
3609
+ merged.push_back (*concrete_it);
3610
+ ++concrete_it;
3611
+ } else {
3612
+ // Otherwise, the parameter must have been omitted from the concrete
3613
+ // function, so insert the abstract one.
3614
+ merged.push_back (*abstract_child.GetDIERef ());
3615
+ did_merge_abstract = true ;
3616
+ }
3617
+ }
3618
+ }
3619
+
3620
+ // Shortcut if no merging happened.
3621
+ if (!did_merge_abstract)
3622
+ return std::move (variable_dies);
3623
+
3624
+ // We inserted all the abstract parameters (or their concrete counterparts).
3625
+ // Let us insert all the remaining concrete variables to the merged list.
3626
+ // During the insertion, let us check there are no remaining concrete
3627
+ // formal parameters. If that's the case, then just bailout from the merge -
3628
+ // the variable list is malformed.
3629
+ for (; concrete_it != variable_dies.end (); ++concrete_it) {
3630
+ if (GetDIE (*concrete_it).Tag () == DW_TAG_formal_parameter) {
3631
+ return std::move (variable_dies);
3632
+ }
3633
+ merged.push_back (*concrete_it);
3634
+ }
3635
+ return std::move (merged);
3636
+ }
3637
+
3557
3638
size_t SymbolFileDWARF::ParseVariablesInFunctionContext (
3558
3639
const SymbolContext &sc, const DWARFDIE &die,
3559
3640
const lldb::addr_t func_low_pc) {
3560
3641
if (!die || !sc.function )
3561
3642
return 0 ;
3562
3643
3563
- VariableList empty_variable_list;
3564
- // Since |die| corresponds to a Block instance, the recursive call will get
3565
- // a variable list from the block. |empty_variable_list| should remain empty.
3644
+ DIEArray dummy_block_variables; // The recursive call should not add anything
3645
+ // to this vector because |die| should be a
3646
+ // subprogram, so all variables will be added
3647
+ // to the subprogram's list.
3566
3648
return ParseVariablesInFunctionContextRecursive (sc, die, func_low_pc,
3567
- empty_variable_list );
3649
+ dummy_block_variables );
3568
3650
}
3569
3651
3652
+ // This method parses all the variables in the blocks in the subtree of |die|,
3653
+ // and inserts them to the variable list for all the nested blocks.
3654
+ // The uninserted variables for the current block are accumulated in
3655
+ // |accumulator|.
3570
3656
size_t SymbolFileDWARF::ParseVariablesInFunctionContextRecursive (
3571
3657
const lldb_private::SymbolContext &sc, const DWARFDIE &die,
3572
- const lldb::addr_t func_low_pc, VariableList &variable_list ) {
3658
+ lldb::addr_t func_low_pc, DIEArray &accumulator ) {
3573
3659
size_t vars_added = 0 ;
3574
3660
dw_tag_t tag = die.Tag ();
3575
3661
3576
3662
if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) ||
3577
3663
(tag == DW_TAG_formal_parameter)) {
3578
- VariableSP var_sp (ParseVariableDIE (sc, die, func_low_pc));
3579
- if (var_sp) {
3580
- variable_list.AddVariableIfUnique (var_sp);
3581
- ++vars_added;
3582
- }
3664
+ accumulator.push_back (*die.GetDIERef ());
3583
3665
}
3584
3666
3585
3667
switch (tag) {
@@ -3611,29 +3693,45 @@ size_t SymbolFileDWARF::ParseVariablesInFunctionContextRecursive(
3611
3693
block_variable_list_sp = std::make_shared<VariableList>();
3612
3694
block->SetVariableList (block_variable_list_sp);
3613
3695
}
3696
+
3697
+ DIEArray block_variables;
3614
3698
for (DWARFDIE child = die.GetFirstChild (); child;
3615
3699
child = child.GetSibling ()) {
3616
3700
vars_added += ParseVariablesInFunctionContextRecursive (
3617
- sc, child, func_low_pc, *block_variable_list_sp );
3701
+ sc, child, func_low_pc, block_variables );
3618
3702
}
3619
-
3703
+ block_variables =
3704
+ MergeBlockAbstractParameters (die, std::move (block_variables));
3705
+ vars_added += PopulateBlockVariableList (*block_variable_list_sp, sc,
3706
+ block_variables, func_low_pc);
3620
3707
break ;
3621
3708
}
3622
3709
3623
3710
default :
3624
- // Recurse to children with the same variable list .
3711
+ // Recurse to children with the same variable accumulator .
3625
3712
for (DWARFDIE child = die.GetFirstChild (); child;
3626
3713
child = child.GetSibling ()) {
3627
3714
vars_added += ParseVariablesInFunctionContextRecursive (
3628
- sc, child, func_low_pc, variable_list );
3715
+ sc, child, func_low_pc, accumulator );
3629
3716
}
3630
-
3631
3717
break ;
3632
3718
}
3633
3719
3634
3720
return vars_added;
3635
3721
}
3636
3722
3723
+ size_t SymbolFileDWARF::PopulateBlockVariableList (
3724
+ VariableList &variable_list, const lldb_private::SymbolContext &sc,
3725
+ llvm::ArrayRef<DIERef> variable_dies, lldb::addr_t func_low_pc) {
3726
+ // Parse the variable DIEs and insert them to the list.
3727
+ for (auto &die : variable_dies) {
3728
+ if (VariableSP var_sp = ParseVariableDIE (sc, GetDIE (die), func_low_pc)) {
3729
+ variable_list.AddVariableIfUnique (var_sp);
3730
+ }
3731
+ }
3732
+ return variable_dies.size ();
3733
+ }
3734
+
3637
3735
// / Collect call site parameters in a DW_TAG_call_site DIE.
3638
3736
static CallSiteParameterArray
3639
3737
CollectCallSiteParameters (ModuleSP module , DWARFDIE call_site_die) {
0 commit comments