llvm-svn: 132304
This commit is contained in:
Greg Clayton
2011-05-30 00:49:24 +00:00
parent 5d2fbfed4d
commit 007d5be653
19 changed files with 369 additions and 144 deletions

View File

@@ -124,8 +124,9 @@ public:
/// @param[in] length /// @param[in] length
/// The length in bytes of the subset of data. /// The length in bytes of the subset of data.
//------------------------------------------------------------------ //------------------------------------------------------------------
DataExtractor (const DataExtractor& data, uint32_t offset = 0, uint32_t length = UINT32_MAX); DataExtractor (const DataExtractor& data, uint32_t offset, uint32_t length);
DataExtractor (const DataExtractor& rhs);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Assignment operator. /// Assignment operator.
/// ///
@@ -1086,7 +1087,7 @@ public:
/// The number of bytes that this object now contains. /// The number of bytes that this object now contains.
//------------------------------------------------------------------ //------------------------------------------------------------------
uint32_t uint32_t
SetData (const DataExtractor& data, uint32_t offset = 0, uint32_t length = UINT32_MAX); SetData (const DataExtractor& data, uint32_t offset, uint32_t length);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Adopt a subset of shared data in \a data_sp. /// Adopt a subset of shared data in \a data_sp.

View File

@@ -236,6 +236,9 @@ public:
virtual bool virtual bool
IsPointerOrReferenceType (); IsPointerOrReferenceType ();
virtual bool
IsPossibleCPlusPlusDynamicType ();
virtual bool virtual bool
IsBaseClass () IsBaseClass ()

View File

@@ -304,6 +304,13 @@ public:
void void
SetExpressionDeclMap (ClangExpressionDeclMap *decl_map); SetExpressionDeclMap (ClangExpressionDeclMap *decl_map);
bool
GetExpressionData (DataExtractor &data) const
{
data = m_data;
return data.GetByteSize() > 0;
}
protected: protected:
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Pretty-prints the location expression to a stream /// Pretty-prints the location expression to a stream

View File

@@ -612,6 +612,11 @@ public:
static bool static bool
IsPointerOrReferenceType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type = NULL); IsPointerOrReferenceType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type = NULL);
static bool
IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast,
lldb::clang_type_t clang_type,
lldb::clang_type_t *target_type = NULL);
static bool static bool
IsCStringType (lldb::clang_type_t clang_type, uint32_t &length); IsCStringType (lldb::clang_type_t clang_type, uint32_t &length);

View File

@@ -120,6 +120,21 @@ public:
bool bool
IsInScope (StackFrame *frame); IsInScope (StackFrame *frame);
bool
LocationIsValidForFrame (StackFrame *frame);
bool
GetLocationIsConstantValueData () const
{
return m_loc_is_const_data;
}
void
SetLocationIsConstantValueData (bool b)
{
m_loc_is_const_data = b;
}
protected: protected:
ConstString m_name; // The basename of the variable (no namespaces) ConstString m_name; // The basename of the variable (no namespaces)
Mangled m_mangled; // The mangled name of hte variable Mangled m_mangled; // The mangled name of hte variable
@@ -129,7 +144,8 @@ protected:
Declaration m_declaration; // Declaration location for this item. Declaration m_declaration; // Declaration location for this item.
DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() 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? uint8_t m_external:1, // Visible outside the containing compile unit?
m_artificial:1; // Non-zero if the variable is not explicitly declared in source m_artificial:1, // Non-zero if the variable is not explicitly declared in source
m_loc_is_const_data:1; // The m_location expression contains the constant variable value data, not a DWARF location
private: private:
Variable(const Variable& rhs); Variable(const Variable& rhs);
Variable& operator=(const Variable& rhs); Variable& operator=(const Variable& rhs);

View File

@@ -3374,10 +3374,10 @@
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3423,11 +3423,11 @@
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3471,8 +3471,8 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXECUTABLE_EXTENSION = a; EXECUTABLE_EXTENSION = a;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3510,9 +3510,9 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXECUTABLE_EXTENSION = a; EXECUTABLE_EXTENSION = a;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3550,9 +3550,9 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXECUTABLE_EXTENSION = a; EXECUTABLE_EXTENSION = a;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3620,7 +3620,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3651,11 +3651,11 @@
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 58; DYLIB_CURRENT_VERSION = 59;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3777,7 +3777,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -3809,7 +3809,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 58; CURRENT_PROJECT_VERSION = 59;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

View File

@@ -17,7 +17,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>58</string> <string>59</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
</dict> </dict>

View File

@@ -87,7 +87,7 @@ CommandObjectExpression::CommandOptions::SetOptionValue (uint32_t option_idx, co
else else
{ {
if (result) if (result)
use_dynamic = eLazyBoolYes; use_dynamic = eLazyBoolYes;
else else
use_dynamic = eLazyBoolNo; use_dynamic = eLazyBoolNo;
} }

View File

@@ -127,6 +127,15 @@ DataExtractor::DataExtractor (const DataExtractor& data, uint32_t offset, uint32
} }
} }
DataExtractor::DataExtractor (const DataExtractor& rhs) :
m_start (rhs.m_start),
m_end (rhs.m_end),
m_byte_order (rhs.m_byte_order),
m_addr_size (rhs.m_addr_size),
m_data_sp (rhs.m_data_sp)
{
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Assignment operator // Assignment operator
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@@ -135,11 +144,11 @@ DataExtractor::operator= (const DataExtractor& rhs)
{ {
if (this != &rhs) if (this != &rhs)
{ {
m_start = rhs.m_start; m_start = rhs.m_start;
m_end = rhs.m_end; m_end = rhs.m_end;
m_byte_order= rhs.m_byte_order; m_byte_order = rhs.m_byte_order;
m_addr_size = rhs.m_addr_size; m_addr_size = rhs.m_addr_size;
m_data_sp = rhs.m_data_sp; m_data_sp = rhs.m_data_sp;
} }
return *this; return *this;
} }

View File

@@ -302,7 +302,6 @@ Error::SetErrorString (const char *err_str)
if (Success()) if (Success())
SetErrorToGenericError(); SetErrorToGenericError();
m_string = err_str; m_string = err_str;
m_string.append("\n");
} }
else else
m_string.clear(); m_string.clear();

View File

@@ -690,7 +690,12 @@ ValueObject::GetValueAsCString ()
GetBitfieldBitOffset())) // Bitfield bit offset GetBitfieldBitOffset())) // Bitfield bit offset
m_value_str.swap(sstr.GetString()); m_value_str.swap(sstr.GetString());
else else
{
m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)",
m_data.GetByteSize(),
GetByteSize());
m_value_str.clear(); m_value_str.clear();
}
} }
} }
break; break;
@@ -953,7 +958,13 @@ ValueObject::IsIntegerType (bool &is_signed)
bool bool
ValueObject::IsPointerOrReferenceType () ValueObject::IsPointerOrReferenceType ()
{ {
return ClangASTContext::IsPointerOrReferenceType(GetClangType()); return ClangASTContext::IsPointerOrReferenceType (GetClangType());
}
bool
ValueObject::IsPossibleCPlusPlusDynamicType ()
{
return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType());
} }
ValueObjectSP ValueObjectSP
@@ -1149,9 +1160,11 @@ ValueObject::DumpValueObject
bool flat_output bool flat_output
) )
{ {
if (valobj && valobj->UpdateValueIfNeeded ()) if (valobj)
{ {
if (use_dynamic != lldb::eNoDynamicValues) bool update_success = valobj->UpdateValueIfNeeded ();
if (update_success && use_dynamic != lldb::eNoDynamicValues)
{ {
ValueObject *dynamic_value = valobj->GetDynamicValue(use_dynamic).get(); ValueObject *dynamic_value = valobj->GetDynamicValue(use_dynamic).get();
if (dynamic_value) if (dynamic_value)
@@ -1196,7 +1209,7 @@ ValueObject::DumpValueObject
if (!scope_already_checked && !valobj->IsInScope()) if (!scope_already_checked && !valobj->IsInScope())
{ {
err_cstr = "error: out of scope"; err_cstr = "out of scope";
} }
} }
@@ -1210,7 +1223,7 @@ ValueObject::DumpValueObject
if (err_cstr) if (err_cstr)
{ {
s.Printf (" error: %s\n", err_cstr); s.Printf (" <%s>\n", err_cstr);
} }
else else
{ {

View File

@@ -120,6 +120,9 @@ ValueObjectDynamicValue::UpdateValue ()
if (!m_parent->UpdateValueIfNeeded()) if (!m_parent->UpdateValueIfNeeded())
{ {
// The dynamic value failed to get an error, pass the error along
if (m_error.Success() && m_parent->GetError().Fail())
m_error = m_parent->GetError();
return false; return false;
} }

View File

@@ -88,7 +88,10 @@ ValueObjectVariable::GetClangAST ()
size_t size_t
ValueObjectVariable::GetByteSize() ValueObjectVariable::GetByteSize()
{ {
return m_variable_sp->GetType()->GetByteSize(); Type *type = m_variable_sp->GetType();
if (type)
return type->GetByteSize();
return 0;
} }
lldb::ValueType lldb::ValueType
@@ -107,96 +110,109 @@ ValueObjectVariable::UpdateValue ()
Variable *variable = m_variable_sp.get(); Variable *variable = m_variable_sp.get();
DWARFExpression &expr = variable->LocationExpression(); DWARFExpression &expr = variable->LocationExpression();
lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
ExecutionContext exe_ctx (GetExecutionContextScope());
if (exe_ctx.target) if (variable->GetLocationIsConstantValueData())
{ {
m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); // expr doesn't contain DWARF bytes, it contains the constant variable
m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); // value bytes themselves...
if (expr.GetExpressionData(m_data))
m_value.SetContext(Value::eContextTypeVariable, variable);
else
m_error.SetErrorString ("empty constant data");
} }
else
if (expr.IsLocationList())
{ {
SymbolContext sc; lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
variable->CalculateSymbolContext (&sc); ExecutionContext exe_ctx (GetExecutionContextScope());
if (sc.function)
loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target); if (exe_ctx.target)
}
Value old_value(m_value);
if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
{
m_value.SetContext(Value::eContextTypeVariable, variable);
Value::ValueType value_type = m_value.GetValueType();
switch (value_type)
{ {
default: m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
assert(!"Unhandled expression result value kind..."); m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
break; }
case Value::eValueTypeScalar: if (expr.IsLocationList())
// The variable value is in the Scalar value inside the m_value. {
// We can point our m_data right to it. SymbolContext sc;
m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); variable->CalculateSymbolContext (&sc);
break; if (sc.function)
loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target);
}
Value old_value(m_value);
if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
{
m_value.SetContext(Value::eContextTypeVariable, variable);
case Value::eValueTypeFileAddress: Value::ValueType value_type = m_value.GetValueType();
case Value::eValueTypeLoadAddress:
case Value::eValueTypeHostAddress:
// The DWARF expression result was an address in the inferior
// process. If this variable is an aggregate type, we just need
// the address as the main value as all child variable objects
// will rely upon this location and add an offset and then read
// their own values as needed. If this variable is a simple
// type, we read all data for it into m_data.
// Make sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can. switch (value_type)
if (value_type == Value::eValueTypeFileAddress && exe_ctx.process)
{ {
lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); default:
if (file_addr != LLDB_INVALID_ADDRESS) assert(!"Unhandled expression result value kind...");
break;
case Value::eValueTypeScalar:
// The variable value is in the Scalar value inside the m_value.
// We can point our m_data right to it.
m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
break;
case Value::eValueTypeFileAddress:
case Value::eValueTypeLoadAddress:
case Value::eValueTypeHostAddress:
// The DWARF expression result was an address in the inferior
// process. If this variable is an aggregate type, we just need
// the address as the main value as all child variable objects
// will rely upon this location and add an offset and then read
// their own values as needed. If this variable is a simple
// type, we read all data for it into m_data.
// Make sure this type has a value before we try and read it
// If we have a file address, convert it to a load address if we can.
if (value_type == Value::eValueTypeFileAddress && exe_ctx.process)
{ {
SymbolContext var_sc; lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
variable->CalculateSymbolContext(&var_sc); if (file_addr != LLDB_INVALID_ADDRESS)
if (var_sc.module_sp)
{ {
ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); SymbolContext var_sc;
if (objfile) variable->CalculateSymbolContext(&var_sc);
if (var_sc.module_sp)
{ {
Address so_addr(file_addr, objfile->GetSectionList()); ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
lldb::addr_t load_addr = so_addr.GetLoadAddress (exe_ctx.target); if (objfile)
if (load_addr != LLDB_INVALID_ADDRESS)
{ {
m_value.SetValueType(Value::eValueTypeLoadAddress); Address so_addr(file_addr, objfile->GetSectionList());
m_value.GetScalar() = load_addr; lldb::addr_t load_addr = so_addr.GetLoadAddress (exe_ctx.target);
if (load_addr != LLDB_INVALID_ADDRESS)
{
m_value.SetValueType(Value::eValueTypeLoadAddress);
m_value.GetScalar() = load_addr;
}
} }
} }
} }
} }
if (ClangASTContext::IsAggregateType (GetClangType()))
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
// say we are changed if our location has changed.
SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
}
else
{
// Copy the Value and set the context to use our Variable
// so it can extract read its value into m_data appropriately
Value value(m_value);
value.SetContext(Value::eContextTypeVariable, variable);
m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
}
break;
} }
if (ClangASTContext::IsAggregateType (GetClangType())) SetValueIsValid (m_error.Success());
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
// say we are changed if our location has changed.
SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
}
else
{
// Copy the Value and set the context to use our Variable
// so it can extract read its value into m_data appropriately
Value value(m_value);
value.SetContext(Value::eContextTypeVariable, variable);
m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
}
break;
} }
SetValueIsValid (m_error.Success());
} }
return m_error.Success(); return m_error.Success();
} }

View File

@@ -642,21 +642,25 @@ ReadRegisterValueAsScalar
if (reg_value.GetScalarValue(value.GetScalar())) if (reg_value.GetScalarValue(value.GetScalar()))
{ {
value.SetValueType (Value::eValueTypeScalar); value.SetValueType (Value::eValueTypeScalar);
value.SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_info)); value.SetContext (Value::eContextTypeRegisterInfo,
const_cast<RegisterInfo *>(reg_info));
if (error_ptr) if (error_ptr)
error_ptr->Clear(); error_ptr->Clear();
return true; return true;
} }
else else
{ {
// If we get this error, then we need to implement a value
// buffer in the dwarf expression evaluation function...
if (error_ptr) if (error_ptr)
error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg); error_ptr->SetErrorStringWithFormat ("register %s can't be converted to a scalar value",
reg_info->name);
} }
} }
else else
{ {
if (error_ptr) if (error_ptr)
error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg); error_ptr->SetErrorStringWithFormat("register %s is not available", reg_info->name);
} }
} }
} }
@@ -817,7 +821,7 @@ DWARFExpression::Evaluate
} }
} }
if (error_ptr) if (error_ptr)
error_ptr->SetErrorStringWithFormat("Out of scope."); error_ptr->SetErrorString ("variable not available");
return false; return false;
} }

View File

@@ -37,7 +37,7 @@ static const char *vtable_demangled_prefix = "vtable for ";
bool bool
ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{ {
return in_value.IsPointerOrReferenceType(); return in_value.IsPossibleCPlusPlusDynamicType();
} }
bool bool

View File

@@ -4040,6 +4040,7 @@ SymbolFileDWARF::ParseVariableDIE
DWARFExpression location; DWARFExpression location;
bool is_external = false; bool is_external = false;
bool is_artificial = false; bool is_artificial = false;
bool location_is_const_value_data = false;
AccessType accessibility = eAccessNone; AccessType accessibility = eAccessNone;
for (i=0; i<num_attributes; ++i) for (i=0; i<num_attributes; ++i)
@@ -4057,6 +4058,9 @@ SymbolFileDWARF::ParseVariableDIE
case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
case DW_AT_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); break; case DW_AT_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); break;
case DW_AT_external: is_external = form_value.Unsigned() != 0; break; case DW_AT_external: is_external = form_value.Unsigned() != 0; break;
case DW_AT_const_value:
location_is_const_value_data = true;
// Fall through...
case DW_AT_location: case DW_AT_location:
{ {
if (form_value.BlockData()) if (form_value.BlockData())
@@ -4085,7 +4089,6 @@ SymbolFileDWARF::ParseVariableDIE
case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break; case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break;
case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_const_value:
case DW_AT_declaration: case DW_AT_declaration:
case DW_AT_description: case DW_AT_description:
case DW_AT_endianity: case DW_AT_endianity:
@@ -4141,6 +4144,7 @@ SymbolFileDWARF::ParseVariableDIE
is_external, is_external,
is_artificial)); is_artificial));
var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
} }
} }
// Cache var_sp even if NULL (the variable was just a specification or // Cache var_sp even if NULL (the variable was just a specification or

View File

@@ -87,11 +87,14 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type)
if (tag_decl->hasExternalLexicalStorage()) if (tag_decl->hasExternalLexicalStorage())
{ {
ExternalASTSource *external_ast_source = ast->getExternalSource(); if (ast)
if (external_ast_source)
{ {
external_ast_source->CompleteType(tag_decl); ExternalASTSource *external_ast_source = ast->getExternalSource();
return !tag_type->isIncompleteType(); if (external_ast_source)
{
external_ast_source->CompleteType(tag_decl);
return !tag_type->isIncompleteType();
}
} }
} }
return false; return false;
@@ -113,11 +116,14 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type)
bool is_forward_decl = class_interface_decl->isForwardDecl(); bool is_forward_decl = class_interface_decl->isForwardDecl();
if (is_forward_decl && class_interface_decl->hasExternalLexicalStorage()) if (is_forward_decl && class_interface_decl->hasExternalLexicalStorage())
{ {
ExternalASTSource *external_ast_source = ast->getExternalSource(); if (ast)
if (external_ast_source)
{ {
external_ast_source->CompleteType (class_interface_decl); ExternalASTSource *external_ast_source = ast->getExternalSource();
is_forward_decl = class_interface_decl->isForwardDecl(); if (external_ast_source)
{
external_ast_source->CompleteType (class_interface_decl);
is_forward_decl = class_interface_decl->isForwardDecl();
}
} }
return is_forward_decl == false; return is_forward_decl == false;
} }
@@ -3979,6 +3985,121 @@ ClangASTContext::GetPointerBitSize ()
return ast->getTypeSize(ast->VoidPtrTy); return ast->getTypeSize(ast->VoidPtrTy);
} }
bool
ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_type_t clang_type, clang_type_t *dynamic_pointee_type)
{
QualType pointee_qual_type;
if (clang_type)
{
QualType qual_type (QualType::getFromOpaquePtr(clang_type));
const clang::Type::TypeClass type_class = qual_type->getTypeClass();
bool success = false;
switch (type_class)
{
case clang::Type::Pointer:
pointee_qual_type = cast<PointerType>(qual_type)->getPointeeType();
success = true;
break;
case clang::Type::LValueReference:
case clang::Type::RValueReference:
pointee_qual_type = cast<ReferenceType>(qual_type)->getPointeeType();
success = true;
break;
case clang::Type::Typedef:
return ClangASTContext::IsPossibleCPlusPlusDynamicType (ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type);
default:
break;
}
if (success)
{
// Check to make sure what we are pointing too is a possible dynamic C++ type
// We currently accept any "void *" (in case we have a class that has been
// watered down to an opaque pointer) and virtual C++ classes.
const clang::Type::TypeClass pointee_type_class = pointee_qual_type->getTypeClass();
switch (pointee_type_class)
{
case clang::Type::Builtin:
switch (cast<clang::BuiltinType>(pointee_qual_type)->getKind())
{
case clang::BuiltinType::UnknownAny:
case clang::BuiltinType::Void:
if (dynamic_pointee_type)
*dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr();
return true;
case clang::BuiltinType::NullPtr:
case clang::BuiltinType::Bool:
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::WChar_U:
case clang::BuiltinType::Char16:
case clang::BuiltinType::Char32:
case clang::BuiltinType::UShort:
case clang::BuiltinType::UInt:
case clang::BuiltinType::ULong:
case clang::BuiltinType::ULongLong:
case clang::BuiltinType::UInt128:
case clang::BuiltinType::Char_S:
case clang::BuiltinType::SChar:
case clang::BuiltinType::WChar_S:
case clang::BuiltinType::Short:
case clang::BuiltinType::Int:
case clang::BuiltinType::Long:
case clang::BuiltinType::LongLong:
case clang::BuiltinType::Int128:
case clang::BuiltinType::Float:
case clang::BuiltinType::Double:
case clang::BuiltinType::LongDouble:
case clang::BuiltinType::Dependent:
case clang::BuiltinType::Overload:
case clang::BuiltinType::ObjCId:
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCSel:
case clang::BuiltinType::BoundMember:
break;
}
break;
case clang::Type::Record:
{
CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl();
if (cxx_record_decl)
{
if (GetCompleteQualType (ast, pointee_qual_type))
{
success = cxx_record_decl->isPolymorphic() || cxx_record_decl->isAbstract();
}
else
{
// We failed to get the complete type, so we have to
// treat this as a void * which we might possibly be
// able to complete
success = true;
}
if (success)
{
if (dynamic_pointee_type)
*dynamic_pointee_type = pointee_qual_type.getAsOpaquePtr();
return true;
}
}
}
break;
default:
break;
}
}
}
if (dynamic_pointee_type)
*dynamic_pointee_type = NULL;
return false;
}
bool bool
ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type) ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type)
{ {

View File

@@ -156,40 +156,53 @@ Variable::CalculateSymbolContext (SymbolContext *sc)
sc->Clear(); sc->Clear();
} }
bool
Variable::LocationIsValidForFrame (StackFrame *frame)
{
// Is the variable is described by a single location?
if (!m_location.IsLocationList())
{
// Yes it is, the location is valid.
return true;
}
if (frame)
{
Target *target = &frame->GetThread().GetProcess().GetTarget();
Function *function = frame->GetSymbolContext(eSymbolContextFunction).function;
if (function)
{
addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
return false;
// It is a location list. We just need to tell if the location
// list contains the current address when converted to a load
// address
return m_location.LocationListContainsAddress (loclist_base_load_addr,
frame->GetFrameCodeAddress().GetLoadAddress (target));
}
}
return false;
}
bool bool
Variable::IsInScope (StackFrame *frame) Variable::IsInScope (StackFrame *frame)
{ {
switch (m_scope) switch (m_scope)
{ {
case eValueTypeVariableGlobal: case eValueTypeRegister:
case eValueTypeVariableStatic: case eValueTypeRegisterSet:
// Globals and statics are always in scope. return frame != NULL;
case eValueTypeConstResult:
return true; return true;
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
case eValueTypeVariableArgument: case eValueTypeVariableArgument:
case eValueTypeVariableLocal: case eValueTypeVariableLocal:
// Check if the location has a location list that describes the value if (frame)
// of the variable with address ranges and different locations for each
// address range?
if (m_location.IsLocationList())
{
SymbolContext sc;
CalculateSymbolContext(&sc);
// Currently we only support functions that have things with
// locations lists. If this expands, we will need to add support
assert (sc.function);
Target *target = &frame->GetThread().GetProcess().GetTarget();
addr_t loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
return false;
// It is a location list. We just need to tell if the location
// list contains the current address when converted to a load
// address
return m_location.LocationListContainsAddress (loclist_base_load_addr, frame->GetFrameCodeAddress().GetLoadAddress (target));
}
else
{ {
// We don't have a location list, we just need to see if the block // We don't have a location list, we just need to see if the block
// that this variable was defined in is currently // that this variable was defined in is currently
@@ -198,16 +211,19 @@ Variable::IsInScope (StackFrame *frame)
{ {
SymbolContext variable_sc; SymbolContext variable_sc;
CalculateSymbolContext (&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 == NULL)
return true;
if (variable_sc.block == deepest_frame_block) if (variable_sc.block == deepest_frame_block)
return true; return true;
return variable_sc.block->Contains (deepest_frame_block); return variable_sc.block->Contains (deepest_frame_block);
} }
} }
break; break;
default: default:
assert (!"Unhandled case");
break; break;
} }
return false; return false;

View File

@@ -32,7 +32,7 @@ public:
{ {
} }
//virtual virtual
~A() ~A()
{ {
} }
@@ -62,7 +62,7 @@ public:
{ {
} }
//virtual virtual
~B() ~B()
{ {
} }
@@ -93,7 +93,7 @@ public:
printf("Within C::ctor() m_c_int=%d\n", m_c_int); // Set break point at this line. printf("Within C::ctor() m_c_int=%d\n", m_c_int); // Set break point at this line.
} }
//virtual virtual
~C() ~C()
{ {
} }
@@ -119,6 +119,14 @@ main (int argc, char const *argv[])
A a(12); A a(12);
B b(22,33); B b(22,33);
C c(44,55,66); C c(44,55,66);
A *c_as_a = &c;
B *c_as_b = &c;
void *a_as_void_ptr = &a;
void *b_as_void_ptr = &b;
void *c_as_void_ptr = &c;
const void *a_as_const_void_ptr = &a;
const void *b_as_const_void_ptr = &b;
const void *c_as_const_void_ptr = &c;
Conversion conv(1); Conversion conv(1);
if (conv) if (conv)
return b.GetIntegerB() - a.GetInteger() + c.GetInteger(); return b.GetIntegerB() - a.GetInteger() + c.GetInteger();