diff options
12 files changed, 133 insertions, 48 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h index 8de5fa03249..2554fd84ff6 100644 --- a/lldb/include/lldb/Expression/ClangExpressionVariable.h +++ b/lldb/include/lldb/Expression/ClangExpressionVariable.h @@ -65,17 +65,22 @@ struct ClangExpressionVariable ClangExpressionVariable(const ClangExpressionVariable &cev); //---------------------------------------------------------------------- - /// If the variable contains its own data, make a Value point at it + /// If the variable contains its own data, make a Value point at it. + /// If \a exe_ctx in not NULL, the value will be resolved in with + /// that execution context. /// /// @param[in] value /// The value to point at the data. /// + /// @param[in] exe_ctx + /// The execution context to use to resolve \a value. + /// /// @return /// True on success; false otherwise (in particular, if this variable /// does not contain its own data). //---------------------------------------------------------------------- bool - PointValueAtData(Value &value); + PointValueAtData(Value &value, ExecutionContext *exe_ctx); //---------------------------------------------------------------------- /// The following values should stay valid for the life of the variable diff --git a/lldb/include/lldb/Target/CPPLanguageRuntime.h b/lldb/include/lldb/Target/CPPLanguageRuntime.h index e4906f9d716..4d98f1d9cf1 100644 --- a/lldb/include/lldb/Target/CPPLanguageRuntime.h +++ b/lldb/include/lldb/Target/CPPLanguageRuntime.h @@ -39,6 +39,9 @@ public: virtual bool GetObjectDescription (Stream &str, ValueObject &object, ExecutionContextScope *exe_scope); + virtual bool + GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope); + protected: //------------------------------------------------------------------ // Classes that inherit from CPPLanguageRuntime can see and modify these diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index 3066b9258da..eff5a0a9abd 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -17,6 +17,8 @@ #include "lldb/lldb-include.h" #include "lldb/Core/PluginInterface.h" #include "lldb/lldb-private.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/Value.h" #include "lldb/Target/ExecutionContextScope.h" namespace lldb_private { @@ -37,6 +39,9 @@ public: virtual bool GetObjectDescription (Stream &str, ValueObject &object, ExecutionContextScope *exe_scope) = 0; + virtual bool + GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) = 0; + virtual lldb::ValueObjectSP GetDynamicValue (lldb::ValueObjectSP in_value, ExecutionContextScope *exe_scope) = 0; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 1b2fa64627b..9ad57b1b26f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -2431,7 +2431,6 @@ isa = PBXProject; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */; compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 1e2d0235598..0060a71570a 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Core/Value.h" #include "lldb/Core/InputReader.h" +#include "lldb/Core/ValueObjectVariable.h" #include "lldb/Expression/ClangExpressionVariable.h" #include "lldb/Expression/ClangUserExpression.h" #include "lldb/Expression/ClangFunction.h" @@ -24,6 +25,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Process.h" @@ -69,6 +71,10 @@ CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const c case 'f': error = Args::StringToFormat(option_arg, format); break; + + case 'o': + print_object = true; + break; default: error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); @@ -85,6 +91,7 @@ CommandObjectExpression::CommandOptions::ResetOptionValues () //language.Clear(); debug = false; format = eFormatDefault; + print_object = false; show_types = true; show_summary = true; } @@ -230,16 +237,36 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream { StreamString ss; - Error rc = expr_result->Print (ss, - m_exe_ctx, - m_options.format, - m_options.show_types, - m_options.show_summary, - m_options.debug); - - if (rc.Fail()) { - error_stream.Printf ("Couldn't print result : %s\n", rc.AsCString()); - return false; + if (m_options.print_object) + { + Value result_value; + if (expr_result->PointValueAtData(result_value, &m_exe_ctx)) + { + bool obj_result; + ObjCLanguageRuntime *runtime = m_exe_ctx.process->GetObjCLanguageRuntime(); + obj_result = runtime->GetObjectDescription (ss, result_value, m_exe_ctx.GetBestExecutionContextScope()); + if (!obj_result) + { + error_stream.Printf ("Could not get object description: %s.\n", ss.GetData()); + return false; + } + // Sometimes the description doesn't have a newline on the end. For now, I'll just add one here, if + ss.Printf("\n"); + } + } + else + { + Error rc = expr_result->Print (ss, + m_exe_ctx, + m_options.format, + m_options.show_types, + m_options.show_summary, + m_options.debug); + + if (rc.Fail()) { + error_stream.Printf ("Couldn't print result : %s\n", rc.AsCString()); + return false; + } } output_stream.PutCString(ss.GetString().c_str()); @@ -345,7 +372,8 @@ lldb::OptionDefinition CommandObjectExpression::CommandOptions::g_option_table[] = { //{ LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."}, -{ LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."}, +{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."}, +{ LLDB_OPT_SET_2, false, "object-description", 'o', no_argument, NULL, 0, NULL, "Print the object description of the value resulting from the expression"}, { LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."}, { LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, NULL, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."}, { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL } diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 4aed304a793..3229a427bec 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -50,6 +50,7 @@ public: lldb::Encoding encoding; lldb::Format format; bool debug; + bool print_object; bool show_types; bool show_summary; }; diff --git a/lldb/source/Expression/ClangExpressionVariable.cpp b/lldb/source/Expression/ClangExpressionVariable.cpp index 37fc6c2354b..f406583dd72 100644 --- a/lldb/source/Expression/ClangExpressionVariable.cpp +++ b/lldb/source/Expression/ClangExpressionVariable.cpp @@ -50,23 +50,14 @@ ClangExpressionVariable::Print (Stream &output_stream, { Error err; - if (!m_data_vars.get() || !m_data_vars->m_data) + Value val; + if (!PointValueAtData (val, &exe_ctx)) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Variable doesn't contain a value"); return err; } - Value val; - - clang::ASTContext *ast_context = m_user_type.GetASTContext(); - - val.SetContext (Value::eContextTypeOpaqueClangQualType, m_user_type.GetOpaqueQualType ()); - val.SetValueType (Value::eValueTypeHostAddress); - val.GetScalar() = (uint64_t)m_data_vars->m_data->GetBytes (); - - val.ResolveValue (&exe_ctx, ast_context); - if (val.GetContextType () == Value::eContextTypeInvalid && val.GetValueType () == Value::eValueTypeScalar && format == lldb::eFormatDefault) @@ -77,6 +68,8 @@ ClangExpressionVariable::Print (Stream &output_stream, return err; } + clang::ASTContext *ast_context = m_user_type.GetASTContext(); + // The expression result is more complex and requires special handling DataExtractor data; Error expr_error = val.GetValueAsData (&exe_ctx, ast_context, data, 0); @@ -165,14 +158,18 @@ ClangExpressionVariable::ClangExpressionVariable(const ClangExpressionVariable & } bool -ClangExpressionVariable::PointValueAtData(Value &value) +ClangExpressionVariable::PointValueAtData(Value &value, ExecutionContext *exe_ctx) { - if (!m_data_vars.get()) + if (!m_data_vars.get() || !m_data_vars->m_data) return false; value.SetContext(Value::eContextTypeOpaqueClangQualType, m_user_type.GetOpaqueQualType()); value.SetValueType(Value::eValueTypeHostAddress); value.GetScalar() = (uint64_t)m_data_vars->m_data->GetBytes(); + clang::ASTContext *ast_context = m_user_type.GetASTContext(); + + if (exe_ctx) + value.ResolveValue (exe_ctx, ast_context); return true; } diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index aaff16dbb6f..7f8d3ae77df 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -667,7 +667,8 @@ ClangFunction::ExecuteFunction ( // Thread we ran the function in may have gone away because we ran the target // Check that it's still there. exe_ctx.thread = exe_ctx.process->GetThreadList().FindThreadByIndexID(tid, true).get(); - exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex(0).get(); + if (exe_ctx.thread) + exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex(0).get(); // Also restore the current process'es selected frame & thread, since this function calling may // be done behind the user's back. diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.cpp index 346dc5411ca..e4acd960323 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.cpp @@ -10,6 +10,8 @@ #include "AppleObjCRuntimeV2.h" #include "AppleObjCTrampolineHandler.h" +#include "clang/AST/Type.h" + #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -38,6 +40,28 @@ bool AppleObjCRuntimeV2::GetObjectDescription (Stream &str, ValueObject &object, ExecutionContextScope *exe_scope) { + // ObjC objects can only be pointers: + if (!ClangASTContext::IsPointerType (object.GetClangType())) + return NULL; + + // Make the argument list: we pass one arg, the address of our pointer, to the print function. + Scalar scalar; + + if (!ClangASTType::GetValueAsScalar (object.GetClangAST(), + object.GetClangType(), + object.GetDataExtractor(), + 0, + object.GetByteSize(), + scalar)) + return NULL; + + Value val(scalar); + return GetObjectDescription(str, val, exe_scope); + +} +bool +AppleObjCRuntimeV2::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) +{ if (!m_read_objc_library) return false; @@ -50,32 +74,41 @@ AppleObjCRuntimeV2::GetObjectDescription (Stream &str, ValueObject &object, Exec // We need other parts of the exe_ctx, but the processes have to match. assert (m_process == exe_ctx.process); - // ObjC objects can only be pointers: - if (!ClangASTContext::IsPointerType (object.GetClangType())) - return NULL; - // Get the function address for the print function. const Address *function_address = GetPrintForDebuggerAddr(); if (!function_address) return false; - // Make the argument list: we pass one arg, the address of our pointer, to the print function. - Scalar scalar; - - if (!ClangASTType::GetValueAsScalar (object.GetClangAST(), - object.GetClangType(), - object.GetDataExtractor(), - 0, - object.GetByteSize(), - scalar)) - return NULL; - - Value val(scalar); - val.SetContext(Value::eContextTypeOpaqueClangQualType, - ClangASTContext::GetVoidPtrType(object.GetClangAST(), false)); - + if (value.GetClangType()) + { + clang::QualType value_type = clang::QualType::getFromOpaquePtr (value.GetClangType()); + if (!value_type->isObjCObjectPointerType()) + { + str.Printf ("Value doesn't point to an ObjC object.\n"); + return false; + } + // FIXME: If we use the real types here then we end up crashing in the expression parser. + // For now, forcing this to be a generic pointer makes it work... +#if 1 + ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext(); + if (value.GetContextType() == Value::eContextTypeOpaqueClangQualType) + { + value.SetContext(Value::eContextTypeOpaqueClangQualType, ast_context->GetVoidPtrType(false)); + } +#endif + } + else + { + // If it is not a pointer, see if we can make it into a pointer. + ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext(); + void *opaque_type_ptr = ast_context->GetBuiltInType_objc_id(); + if (opaque_type_ptr == NULL) + opaque_type_ptr = ast_context->GetVoidPtrType(false); + value.SetContext(Value::eContextTypeOpaqueClangQualType, opaque_type_ptr); + } + ValueList arg_value_list; - arg_value_list.PushValue(val); + arg_value_list.PushValue(value); // This is the return value: const char *target_triple = exe_ctx.process->GetTargetTriple().GetCString(); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.h index 17c94bcf538..fcd1ec26ee1 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.h @@ -31,6 +31,9 @@ public: // These are generic runtime functions: virtual bool + GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope); + + virtual bool GetObjectDescription (Stream &str, ValueObject &object, ExecutionContextScope *exe_scope); virtual lldb::ValueObjectSP diff --git a/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp index d694b7702b3..d0fc7af8609 100644 --- a/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/lldb/source/Target/CPPLanguageRuntime.cpp @@ -33,3 +33,10 @@ CPPLanguageRuntime::GetObjectDescription (Stream &str, ValueObject &object, Exec // C++ has no generic way to do this. return false; } + +bool +CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) +{ + // C++ has no generic way to do this. + return false; +} diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp index 0a136336a26..7f4de245116 100644 --- a/lldb/source/Target/ObjCLanguageRuntime.cpp +++ b/lldb/source/Target/ObjCLanguageRuntime.cpp @@ -6,9 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +#include "clang/AST/Type.h" #include "lldb/Core/Log.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" using namespace lldb; |