forked from OSchip/llvm-project
Handle the case when a variable is only valid in part of the enclosing scope
DWARF stores this information in the DW_AT_start_scope attribute. This CL add support for this attribute and also changes the functions displaying frame variables to only display the variables currently in scope. Differential revision: http://reviews.llvm.org/D17449 llvm-svn: 261858
This commit is contained in:
parent
2e4c72977c
commit
72ac8a840f
|
@ -202,7 +202,13 @@ namespace lldb_private {
|
|||
{
|
||||
m_entries.push_back (entry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Append (B base, S size)
|
||||
{
|
||||
m_entries.emplace_back(base, size);
|
||||
}
|
||||
|
||||
bool
|
||||
RemoveEntrtAtIndex (uint32_t idx)
|
||||
{
|
||||
|
@ -471,7 +477,13 @@ namespace lldb_private {
|
|||
{
|
||||
m_entries.push_back (entry);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Append (B base, S size)
|
||||
{
|
||||
m_entries.emplace_back(base, size);
|
||||
}
|
||||
|
||||
bool
|
||||
RemoveEntrtAtIndex (uint32_t idx)
|
||||
{
|
||||
|
|
|
@ -310,8 +310,9 @@ public:
|
|||
AppendBlockVariables (bool can_create,
|
||||
bool get_child_block_variables,
|
||||
bool stop_if_child_block_is_inlined_function,
|
||||
const std::function<bool(Variable*)>& filter,
|
||||
VariableList *variable_list);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Appends the variables from this block, and optionally from all
|
||||
/// parent blocks, to \a variable_list.
|
||||
|
@ -341,9 +342,10 @@ public:
|
|||
/// 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<bool(Variable*)>& filter,
|
||||
VariableList *variable_list);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -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,8 @@ class Variable : public UserID,
|
|||
public std::enable_shared_from_this<Variable>
|
||||
{
|
||||
public:
|
||||
typedef RangeVector<lldb::addr_t, lldb::addr_t> RangeList;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Constructors and Destructors
|
||||
//------------------------------------------------------------------
|
||||
|
@ -36,6 +39,7 @@ public:
|
|||
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 +182,14 @@ public:
|
|||
|
||||
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?
|
||||
|
|
|
@ -131,7 +131,11 @@ SBBlock::AppendVariables (bool can_create, bool get_parent_variables, lldb_priva
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -789,9 +789,10 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic)
|
|||
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 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -760,10 +760,11 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -4091,6 +4091,7 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
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; i<num_attributes; ++i)
|
||||
|
@ -4206,13 +4207,44 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
spec_die = debug_info->GetDIE(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,20 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
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());
|
||||
|
||||
|
||||
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));
|
||||
|
||||
|
|
|
@ -486,16 +486,24 @@ uint32_t
|
|||
Block::AppendBlockVariables (bool can_create,
|
||||
bool get_child_block_variables,
|
||||
bool stop_if_child_block_is_inlined_function,
|
||||
const std::function<bool(Variable*)>& 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 @@ Block::AppendBlockVariables (bool can_create,
|
|||
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 @@ Block::AppendVariables
|
|||
bool can_create,
|
||||
bool get_parent_variables,
|
||||
bool stop_if_block_is_inlined_function,
|
||||
const std::function<bool(Variable*)>& filter,
|
||||
VariableList *variable_list
|
||||
)
|
||||
{
|
||||
|
@ -528,12 +538,19 @@ Block::AppendVariables
|
|||
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::AppendVariables
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ Variable::Variable (lldb::user_id_t uid,
|
|||
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 @@ Variable::Variable (lldb::user_id_t uid,
|
|||
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,24 @@ Variable::IsInScope (StackFrame *frame)
|
|||
{
|
||||
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;
|
||||
|
||||
// If no scope range is specified then it means that the scope is the same as the
|
||||
// scope of the enclosing lexical block.
|
||||
if (m_scope_range.IsEmpty())
|
||||
return true;
|
||||
|
||||
addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress();
|
||||
return m_scope_range.FindEntryThatContains(file_address) != nullptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -540,7 +540,11 @@ StackFrame::GetVariableList (bool get_file_globals)
|
|||
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 @@ StackFrame::GetInScopeVariableList (bool get_file_globals)
|
|||
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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue