Index: include/lldb/Core/RangeMap.h =================================================================== --- include/lldb/Core/RangeMap.h +++ include/lldb/Core/RangeMap.h @@ -202,7 +202,13 @@ { m_entries.push_back (entry); } - + + void + Append (B base, S size) + { + m_entries.emplace_back(base, size); + } + bool RemoveEntrtAtIndex (uint32_t idx) { Index: include/lldb/Symbol/Block.h =================================================================== --- include/lldb/Symbol/Block.h +++ include/lldb/Symbol/Block.h @@ -310,8 +310,9 @@ AppendBlockVariables (bool can_create, bool get_child_block_variables, bool stop_if_child_block_is_inlined_function, + const std::function& filter, VariableList *variable_list); - + //------------------------------------------------------------------ /// Appends the variables from this block, and optionally from all /// parent blocks, to \a variable_list. @@ -341,9 +342,10 @@ /// variable_list. //------------------------------------------------------------------ uint32_t - AppendVariables (bool can_create, - bool get_parent_variables, + AppendVariables (bool can_create, + bool get_parent_variables, bool stop_if_block_is_inlined_function, + const std::function& filter, VariableList *variable_list); //------------------------------------------------------------------ Index: include/lldb/Symbol/Variable.h =================================================================== --- include/lldb/Symbol/Variable.h +++ include/lldb/Symbol/Variable.h @@ -17,6 +17,7 @@ #include "lldb/lldb-private.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/Mangled.h" +#include "lldb/Core/RangeMap.h" #include "lldb/Core/UserID.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/Declaration.h" @@ -27,6 +28,9 @@ public std::enable_shared_from_this { public: + typedef RangeArray RangeList; + typedef RangeList::Entry Range; + //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ @@ -36,6 +40,7 @@ const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope, SymbolContextScope *owner_scope, + const RangeList& scope_range, Declaration* decl, const DWARFExpression& location, bool external, @@ -178,12 +183,14 @@ CompilerDecl GetDecl (); + protected: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of the variable lldb::SymbolFileTypeSP m_symfile_type_sp; // The type pointer of the variable (int, struct, class, etc) lldb::ValueType m_scope; // global, parameter, local SymbolContextScope *m_owner_scope; // The symbol file scope that this variable was defined in + RangeList m_scope_range; // The list of ranges inside the owner's scope where this variable is valid Declaration m_declaration; // Declaration location for this item. DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() uint8_t m_external:1, // Visible outside the containing compile unit? Index: source/API/SBBlock.cpp =================================================================== --- source/API/SBBlock.cpp +++ source/API/SBBlock.cpp @@ -131,7 +131,11 @@ if (IsValid()) { bool show_inline = true; - m_opaque_ptr->AppendVariables (can_create, get_parent_variables, show_inline, var_list); + m_opaque_ptr->AppendVariables (can_create, + get_parent_variables, + show_inline, + [](Variable*) { return true; }, + var_list); } } Index: source/API/SBFrame.cpp =================================================================== --- source/API/SBFrame.cpp +++ source/API/SBFrame.cpp @@ -789,9 +789,10 @@ const bool get_parent_variables = true; const bool stop_if_block_is_inlined_function = true; - if (sc.block->AppendVariables (can_create, + if (sc.block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, + [frame](Variable* v) { return v->IsInScope(frame); }, &variable_list)) { var_sp = variable_list.FindVariable (ConstString(name)); @@ -887,6 +888,7 @@ sc.block->AppendVariables(can_create, get_parent_variables, stop_if_block_is_inlined_function, + [frame](Variable* v) { return v->IsInScope(frame); }, &variable_list); if (value_type == eValueTypeVariableGlobal) { Index: source/Core/Address.cpp =================================================================== --- source/Core/Address.cpp +++ source/Core/Address.cpp @@ -760,10 +760,11 @@ bool stop_if_block_is_inlined_function = false; VariableList variable_list; sc.block->AppendVariables (can_create, - get_parent_variables, - stop_if_block_is_inlined_function, + get_parent_variables, + stop_if_block_is_inlined_function, + [](Variable*) { return true; }, &variable_list); - + const size_t num_variables = variable_list.GetSize(); for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) { Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4091,6 +4091,7 @@ bool location_is_const_value_data = false; bool has_explicit_location = false; DWARFFormValue const_value; + Variable::RangeList scope_ranges; //AccessType accessibility = eAccessNone; for (i=0; iGetDIE(DIERef(form_value)); break; } + case DW_AT_start_scope: + { + if (form_value.Form() == DW_FORM_sec_offset) + { + DWARFRangeList dwarf_scope_ranges; + const DWARFDebugRanges* debug_ranges = DebugRanges(); + debug_ranges->FindRanges(form_value.Unsigned(), dwarf_scope_ranges); + + // All DW_AT_start_scope are relative to the base address of the + // compile unit. We add the compile unit base address to make + // sure all the addresses are properly fixed up. + for (size_t i = 0, count = dwarf_scope_ranges.GetSize(); i < count; ++i) + { + const DWARFRangeList::Entry& range = dwarf_scope_ranges.GetEntryRef(i); + scope_ranges.Append(range.GetRangeBase() + die.GetCU()->GetBaseAddress(), + range.GetByteSize()); + } + } + else + { + // TODO: Handle the case when DW_AT_start_scope have form constant. The + // dwarf spec is a bit ambiguous about what is the expected behavior in + // case the enclosing block have a non coninious address range and the + // DW_AT_start_scope entry have a form constant. + GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_start_scope has unsupported form type (0x%x)\n", + die.GetID(), + form_value.Form()); + } + + scope_ranges.Sort(); + scope_ranges.CombineConsecutiveRanges(); + } case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: case DW_AT_description: case DW_AT_endianity: case DW_AT_segment: - case DW_AT_start_scope: case DW_AT_visibility: default: case DW_AT_abstract_origin: @@ -4392,19 +4424,33 @@ if (symbol_context_scope) { SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID())); - + if (const_value.Form() && type_sp && type_sp->GetType()) location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize()); - + + // If no scope_ranges were specified then copy them over from the parent block + Block* context_block = symbol_context_scope->CalculateSymbolContextBlock(); + if (scope_ranges.IsEmpty() && context_block) + { + for (size_t i = 0, count = context_block->GetNumRanges(); i < count; ++i) + { + AddressRange range; + if (context_block->GetRangeAtIndex(i, range)) + scope_ranges.Append(range.GetBaseAddress().GetFileAddress(), + range.GetByteSize()); + } + } + var_sp.reset (new Variable (die.GetID(), - name, + name, mangled, type_sp, - scope, - symbol_context_scope, - &decl, - location, - is_external, + scope, + symbol_context_scope, + scope_ranges, + &decl, + location, + is_external, is_artificial, is_static_member)); Index: source/Symbol/Block.cpp =================================================================== --- source/Symbol/Block.cpp +++ source/Symbol/Block.cpp @@ -486,16 +486,24 @@ Block::AppendBlockVariables (bool can_create, bool get_child_block_variables, bool stop_if_child_block_is_inlined_function, + const std::function& filter, VariableList *variable_list) { uint32_t num_variables_added = 0; VariableList *block_var_list = GetBlockVariableList (can_create).get(); if (block_var_list) { - num_variables_added += block_var_list->GetSize(); - variable_list->AddVariables (block_var_list); + for (size_t i = 0; i < block_var_list->GetSize(); ++i) + { + VariableSP variable = block_var_list->GetVariableAtIndex(i); + if (filter(variable.get())) + { + num_variables_added++; + variable_list->AddVariable(variable); + } + } } - + if (get_child_block_variables) { collection::const_iterator pos, end = m_children.end(); @@ -508,6 +516,7 @@ num_variables_added += child_block->AppendBlockVariables (can_create, get_child_block_variables, stop_if_child_block_is_inlined_function, + filter, variable_list); } } @@ -521,6 +530,7 @@ bool can_create, bool get_parent_variables, bool stop_if_block_is_inlined_function, + const std::function& filter, VariableList *variable_list ) { @@ -528,12 +538,19 @@ VariableListSP variable_list_sp(GetBlockVariableList(can_create)); bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; - if (variable_list_sp.get()) + if (variable_list_sp) { - num_variables_added = variable_list_sp->GetSize(); - variable_list->AddVariables(variable_list_sp.get()); + for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) + { + VariableSP variable = variable_list_sp->GetVariableAtIndex(i); + if (filter(variable.get())) + { + num_variables_added++; + variable_list->AddVariable(variable); + } + } } - + if (get_parent_variables) { if (stop_if_block_is_inlined_function && is_inlined_function) @@ -541,7 +558,11 @@ Block* parent_block = GetParent(); if (parent_block) - num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); + num_variables_added += parent_block->AppendVariables(can_create, + get_parent_variables, + stop_if_block_is_inlined_function, + filter, + variable_list); } return num_variables_added; } Index: source/Symbol/Variable.cpp =================================================================== --- source/Symbol/Variable.cpp +++ source/Symbol/Variable.cpp @@ -43,6 +43,7 @@ const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, SymbolContextScope *context, + const RangeList& scope_range, Declaration* decl_ptr, const DWARFExpression& location, bool external, @@ -54,6 +55,7 @@ m_symfile_type_sp(symfile_type_sp), m_scope(scope), m_owner_scope(context), + m_scope_range(scope_range), m_declaration(decl_ptr), m_location(location), m_external(external), @@ -356,14 +358,21 @@ { SymbolContext variable_sc; CalculateSymbolContext (&variable_sc); + // Check for static or global variable defined at the compile unit // level that wasn't defined in a block if (variable_sc.block == nullptr) - return true; - - if (variable_sc.block == deepest_frame_block) return true; - return variable_sc.block->Contains (deepest_frame_block); + + // Check if the variable is valid in the current block + if (variable_sc.block != deepest_frame_block && + !variable_sc.block->Contains(deepest_frame_block)) + { + return false; + } + + addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress(); + return m_scope_range.FindEntryThatContains(file_address) != nullptr; } } break; Index: source/Target/StackFrame.cpp =================================================================== --- source/Target/StackFrame.cpp +++ source/Target/StackFrame.cpp @@ -540,7 +540,11 @@ const bool can_create = true; const bool stop_if_child_block_is_inlined_function = true; m_variable_list_sp.reset(new VariableList()); - frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, m_variable_list_sp.get()); + frame_block->AppendBlockVariables(can_create, + get_child_variables, + stop_if_child_block_is_inlined_function, + [this](Variable* v) { return v->IsInScope(this); }, + m_variable_list_sp.get()); } } @@ -584,6 +588,7 @@ m_sc.block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, + [this](Variable* v) { return v->IsInScope(this); }, var_list_sp.get()); }