diff options
19 files changed, 369 insertions, 144 deletions
diff --git a/lldb/include/lldb/Core/DataExtractor.h b/lldb/include/lldb/Core/DataExtractor.h index e0498fa28e7..e4ec102d1e8 100644 --- a/lldb/include/lldb/Core/DataExtractor.h +++ b/lldb/include/lldb/Core/DataExtractor.h @@ -124,8 +124,9 @@ public: /// @param[in] length /// 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. /// @@ -1086,7 +1087,7 @@ public: /// The number of bytes that this object now contains. //------------------------------------------------------------------ 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. diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index a5d7a5c5f40..fcf2b0b25d6 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -236,6 +236,9 @@ public: virtual bool IsPointerOrReferenceType (); + + virtual bool + IsPossibleCPlusPlusDynamicType (); virtual bool IsBaseClass () diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 60f278abba0..72b9c63ca52 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -304,6 +304,13 @@ public: void SetExpressionDeclMap (ClangExpressionDeclMap *decl_map); + bool + GetExpressionData (DataExtractor &data) const + { + data = m_data; + return data.GetByteSize() > 0; + } + protected: //------------------------------------------------------------------ /// Pretty-prints the location expression to a stream diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 337ea8186e0..6b0b4a89747 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -612,6 +612,11 @@ public: static bool 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 IsCStringType (lldb::clang_type_t clang_type, uint32_t &length); diff --git a/lldb/include/lldb/Symbol/Variable.h b/lldb/include/lldb/Symbol/Variable.h index 89a1bbcecc8..c6656cc6368 100644 --- a/lldb/include/lldb/Symbol/Variable.h +++ b/lldb/include/lldb/Symbol/Variable.h @@ -120,6 +120,21 @@ public: bool 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: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of hte variable @@ -129,7 +144,8 @@ protected: 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? - 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: Variable(const Variable& rhs); Variable& operator=(const Variable& rhs); diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index e7b8a5344ca..6679beaa242 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -3374,10 +3374,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 58; + DYLIB_CURRENT_VERSION = 59; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3423,11 +3423,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 58; + DYLIB_CURRENT_VERSION = 59; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3471,8 +3471,8 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; - DYLIB_CURRENT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; + DYLIB_CURRENT_VERSION = 59; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3510,9 +3510,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 58; + DYLIB_CURRENT_VERSION = 59; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3550,9 +3550,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 58; + DYLIB_CURRENT_VERSION = 59; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3620,7 +3620,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3651,11 +3651,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 58; + DYLIB_CURRENT_VERSION = 59; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3777,7 +3777,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3809,7 +3809,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 58; + CURRENT_PROJECT_VERSION = 59; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/lldb/resources/LLDB-Info.plist b/lldb/resources/LLDB-Info.plist index bb3eec65099..928ae78e053 100644 --- a/lldb/resources/LLDB-Info.plist +++ b/lldb/resources/LLDB-Info.plist @@ -17,7 +17,7 @@ <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> - <string>58</string> + <string>59</string> <key>CFBundleName</key> <string>${EXECUTABLE_NAME}</string> </dict> diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index f8facfd1ba4..4c8b152f6e7 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -87,7 +87,7 @@ CommandObjectExpression::CommandOptions::SetOptionValue (uint32_t option_idx, co else { if (result) - use_dynamic = eLazyBoolYes; + use_dynamic = eLazyBoolYes; else use_dynamic = eLazyBoolNo; } diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp index 8ce7b8f3224..bc26c8645e1 100644 --- a/lldb/source/Core/DataExtractor.cpp +++ b/lldb/source/Core/DataExtractor.cpp @@ -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 //---------------------------------------------------------------------- @@ -135,11 +144,11 @@ DataExtractor::operator= (const DataExtractor& rhs) { if (this != &rhs) { - m_start = rhs.m_start; - m_end = rhs.m_end; - m_byte_order= rhs.m_byte_order; + 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; + m_data_sp = rhs.m_data_sp; } return *this; } diff --git a/lldb/source/Core/Error.cpp b/lldb/source/Core/Error.cpp index 6614769f8a0..6e21fe7ee2b 100644 --- a/lldb/source/Core/Error.cpp +++ b/lldb/source/Core/Error.cpp @@ -302,7 +302,6 @@ Error::SetErrorString (const char *err_str) if (Success()) SetErrorToGenericError(); m_string = err_str; - m_string.append("\n"); } else m_string.clear(); diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 10247db11e2..ee44876a0ec 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -690,7 +690,12 @@ ValueObject::GetValueAsCString () GetBitfieldBitOffset())) // Bitfield bit offset m_value_str.swap(sstr.GetString()); else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); m_value_str.clear(); + } } } break; @@ -953,7 +958,13 @@ ValueObject::IsIntegerType (bool &is_signed) bool ValueObject::IsPointerOrReferenceType () { - return ClangASTContext::IsPointerOrReferenceType(GetClangType()); + return ClangASTContext::IsPointerOrReferenceType (GetClangType()); +} + +bool +ValueObject::IsPossibleCPlusPlusDynamicType () +{ + return ClangASTContext::IsPossibleCPlusPlusDynamicType (GetClangAST (), GetClangType()); } ValueObjectSP @@ -1149,9 +1160,11 @@ ValueObject::DumpValueObject 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(); if (dynamic_value) @@ -1196,7 +1209,7 @@ ValueObject::DumpValueObject 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) { - s.Printf (" error: %s\n", err_cstr); + s.Printf (" <%s>\n", err_cstr); } else { diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index ee50d45433f..a8d48891ab3 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -120,6 +120,9 @@ ValueObjectDynamicValue::UpdateValue () 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; } diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 882b7021f49..e2a281b7f95 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -88,7 +88,10 @@ ValueObjectVariable::GetClangAST () size_t ValueObjectVariable::GetByteSize() { - return m_variable_sp->GetType()->GetByteSize(); + Type *type = m_variable_sp->GetType(); + if (type) + return type->GetByteSize(); + return 0; } lldb::ValueType @@ -107,96 +110,109 @@ ValueObjectVariable::UpdateValue () Variable *variable = m_variable_sp.get(); DWARFExpression &expr = variable->LocationExpression(); - lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; - ExecutionContext exe_ctx (GetExecutionContextScope()); - if (exe_ctx.target) - { - m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); - m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); - } - - if (expr.IsLocationList()) + if (variable->GetLocationIsConstantValueData()) { - SymbolContext sc; - variable->CalculateSymbolContext (&sc); - if (sc.function) - loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target); + // expr doesn't contain DWARF bytes, it contains the constant variable + // value bytes themselves... + if (expr.GetExpressionData(m_data)) + m_value.SetContext(Value::eContextTypeVariable, variable); + else + m_error.SetErrorString ("empty constant data"); } - Value old_value(m_value); - if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error)) + else { - m_value.SetContext(Value::eContextTypeVariable, variable); - - Value::ValueType value_type = m_value.GetValueType(); + lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; + ExecutionContext exe_ctx (GetExecutionContextScope()); + + if (exe_ctx.target) + { + m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); + } - switch (value_type) + if (expr.IsLocationList()) { - default: - 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 sc; + variable->CalculateSymbolContext (&sc); + 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); + + Value::ValueType value_type = m_value.GetValueType(); + + switch (value_type) { - lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (file_addr != LLDB_INVALID_ADDRESS) + default: + 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; - variable->CalculateSymbolContext(&var_sc); - if (var_sc.module_sp) + lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (file_addr != LLDB_INVALID_ADDRESS) { - ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); - if (objfile) + SymbolContext var_sc; + variable->CalculateSymbolContext(&var_sc); + if (var_sc.module_sp) { - Address so_addr(file_addr, objfile->GetSectionList()); - lldb::addr_t load_addr = so_addr.GetLoadAddress (exe_ctx.target); - if (load_addr != LLDB_INVALID_ADDRESS) + ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); + if (objfile) { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_addr; + Address so_addr(file_addr, objfile->GetSectionList()); + 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); + 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; } - break; - } - SetValueIsValid (m_error.Success()); + SetValueIsValid (m_error.Success()); + } } return m_error.Success(); } diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 161fd957d5c..b038a5622e4 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -642,21 +642,25 @@ ReadRegisterValueAsScalar if (reg_value.GetScalarValue(value.GetScalar())) { 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) error_ptr->Clear(); return true; } else { + // If we get this error, then we need to implement a value + // buffer in the dwarf expression evaluation function... 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 { 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) - error_ptr->SetErrorStringWithFormat("Out of scope."); + error_ptr->SetErrorString ("variable not available"); return false; } diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 76a549a1735..00b450e9aab 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -37,7 +37,7 @@ static const char *vtable_demangled_prefix = "vtable for "; bool ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) { - return in_value.IsPointerOrReferenceType(); + return in_value.IsPossibleCPlusPlusDynamicType(); } bool diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 342de4c6e07..fa2d003c966 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4040,6 +4040,7 @@ SymbolFileDWARF::ParseVariableDIE DWARFExpression location; bool is_external = false; bool is_artificial = false; + bool location_is_const_value_data = false; AccessType accessibility = eAccessNone; 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_type: var_type = ResolveTypeUID(form_value.Reference(dwarf_cu)); 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: { if (form_value.BlockData()) @@ -4085,7 +4089,6 @@ SymbolFileDWARF::ParseVariableDIE 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_const_value: case DW_AT_declaration: case DW_AT_description: case DW_AT_endianity: @@ -4141,6 +4144,7 @@ SymbolFileDWARF::ParseVariableDIE is_external, is_artificial)); + var_sp->SetLocationIsConstantValueData (location_is_const_value_data); } } // Cache var_sp even if NULL (the variable was just a specification or diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 7759164e51c..cf55db8d243 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -87,11 +87,14 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type) if (tag_decl->hasExternalLexicalStorage()) { - ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) + if (ast) { - external_ast_source->CompleteType(tag_decl); - return !tag_type->isIncompleteType(); + ExternalASTSource *external_ast_source = ast->getExternalSource(); + if (external_ast_source) + { + external_ast_source->CompleteType(tag_decl); + return !tag_type->isIncompleteType(); + } } } return false; @@ -113,11 +116,14 @@ GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type) bool is_forward_decl = class_interface_decl->isForwardDecl(); if (is_forward_decl && class_interface_decl->hasExternalLexicalStorage()) { - ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) + if (ast) { - external_ast_source->CompleteType (class_interface_decl); - is_forward_decl = class_interface_decl->isForwardDecl(); + ExternalASTSource *external_ast_source = ast->getExternalSource(); + if (external_ast_source) + { + external_ast_source->CompleteType (class_interface_decl); + is_forward_decl = class_interface_decl->isForwardDecl(); + } } return is_forward_decl == false; } @@ -3980,6 +3986,121 @@ ClangASTContext::GetPointerBitSize () } 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 ClangASTContext::IsPointerOrReferenceType (clang_type_t clang_type, clang_type_t*target_type) { if (clang_type == NULL) diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index f264e142fef..7f841b4856a 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -156,40 +156,53 @@ Variable::CalculateSymbolContext (SymbolContext *sc) sc->Clear(); } - bool -Variable::IsInScope (StackFrame *frame) +Variable::LocationIsValidForFrame (StackFrame *frame) { - switch (m_scope) + // Is the variable is described by a single location? + if (!m_location.IsLocationList()) { - case eValueTypeVariableGlobal: - case eValueTypeVariableStatic: - // Globals and statics are always in scope. + // Yes it is, the location is valid. return true; + } - case eValueTypeVariableArgument: - case eValueTypeVariableLocal: - // Check if the location has a location list that describes the value - // of the variable with address ranges and different locations for each - // address range? - if (m_location.IsLocationList()) + if (frame) + { + Target *target = &frame->GetThread().GetProcess().GetTarget(); + + Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; + if (function) { - 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); + 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 m_location.LocationListContainsAddress (loclist_base_load_addr, + frame->GetFrameCodeAddress().GetLoadAddress (target)); } - else + } + return false; +} + +bool +Variable::IsInScope (StackFrame *frame) +{ + switch (m_scope) + { + case eValueTypeRegister: + case eValueTypeRegisterSet: + return frame != NULL; + + case eValueTypeConstResult: + return true; + + case eValueTypeVariableGlobal: + case eValueTypeVariableStatic: + case eValueTypeVariableArgument: + case eValueTypeVariableLocal: + if (frame) { // We don't have a location list, we just need to see if the block // that this variable was defined in is currently @@ -198,16 +211,19 @@ 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 == NULL) + return true; + if (variable_sc.block == deepest_frame_block) return true; - return variable_sc.block->Contains (deepest_frame_block); } } break; default: - assert (!"Unhandled case"); break; } return false; diff --git a/lldb/test/class_types/main.cpp b/lldb/test/class_types/main.cpp index 251e66c3c9f..4cee7f80637 100644 --- a/lldb/test/class_types/main.cpp +++ b/lldb/test/class_types/main.cpp @@ -32,7 +32,7 @@ public: { } - //virtual + virtual ~A() { } @@ -62,7 +62,7 @@ public: { } - //virtual + virtual ~B() { } @@ -93,7 +93,7 @@ public: printf("Within C::ctor() m_c_int=%d\n", m_c_int); // Set break point at this line. } - //virtual + virtual ~C() { } @@ -119,6 +119,14 @@ main (int argc, char const *argv[]) A a(12); B b(22,33); 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); if (conv) return b.GetIntegerB() - a.GetInteger() + c.GetInteger(); |