bool AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope) { if (!m_read_objc_library) return false; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); Process *process = exe_ctx.GetProcessPtr(); if (!process) return false; // We need other parts of the exe_ctx, but the processes have to match. assert (m_process == process); // Get the function address for the print function. const Address *function_address = GetPrintForDebuggerAddr(); if (!function_address) return false; Target *target = exe_ctx.GetTargetPtr(); CompilerType compiler_type = value.GetCompilerType(); if (compiler_type) { if (!ClangASTContext::IsObjCObjectPointerType(compiler_type)) { strm.Printf ("Value doesn't point to an ObjC object.\n"); return false; } } else { // If it is not a pointer, see if we can make it into a pointer. ClangASTContext *ast_context = target->GetScratchClangASTContext(); CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID); if (!opaque_type) opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); //value.SetContext(Value::eContextTypeClangType, opaque_type_ptr); value.SetCompilerType (opaque_type); } ValueList arg_value_list; arg_value_list.PushValue(value); // This is the return value: ClangASTContext *ast_context = target->GetScratchClangASTContext(); CompilerType return_compiler_type = ast_context->GetCStringType(true); Value ret; // ret.SetContext(Value::eContextTypeClangType, return_compiler_type); ret.SetCompilerType (return_compiler_type); if (exe_ctx.GetFramePtr() == NULL) { Thread *thread = exe_ctx.GetThreadPtr(); if (thread == NULL) { exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread()); thread = exe_ctx.GetThreadPtr(); } if (thread) { exe_ctx.SetFrameSP(thread->GetSelectedFrame()); } } // Now we're ready to call the function: StreamString error_stream; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; if (!m_print_object_caller_up) { Error error; m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC, return_compiler_type, *function_address, arg_value_list, "objc-object-description", error)); if (error.Fail()) { m_print_object_caller_up.reset(); strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString()); return false; } m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); } else { m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, error_stream); } EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, &wrapper_struct_addr, options, error_stream, ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); return false; } addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); char buf[512]; size_t cstr_len = 0; size_t full_buffer_len = sizeof (buf) - 1; size_t curr_len = full_buffer_len; while (curr_len == full_buffer_len) { Error error; curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf), error); strm.Write (buf, curr_len); cstr_len += curr_len; } return cstr_len > 0; }
bool BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) { Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS); Mutex::Locker evaluation_locker(m_condition_mutex); size_t condition_hash; const char *condition_text = GetConditionText(&condition_hash); if (!condition_text) { m_user_expression_sp.reset(); return false; } if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { m_user_expression_sp.reset(new ClangUserExpression(condition_text, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); StreamString errors; if (!m_user_expression_sp->Parse(errors, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s", errors.GetData()); m_user_expression_sp.reset(); return false; } m_condition_hash = condition_hash; } // We need to make sure the user sees any parse errors in their condition, so we'll hook the // constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); Error expr_error; StreamString execution_errors; ExpressionVariableSP result_variable_sp; ExpressionResults result_code = m_user_expression_sp->Execute(execution_errors, exe_ctx, options, m_user_expression_sp, result_variable_sp); bool ret; if (result_code == eExpressionCompleted) { if (!result_variable_sp) { error.SetErrorString("Expression did not return a result"); return false; } result_value_sp = result_variable_sp->GetValueObject(); if (result_value_sp) { Scalar scalar_value; if (result_value_sp->ResolveValue (scalar_value)) { if (scalar_value.ULongLong(1) == 0) ret = false; else ret = true; if (log) log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); } else { ret = false; error.SetErrorString("Failed to get an integer result from the expression"); } } else { ret = false; error.SetErrorString("Failed to get any result from the expression"); } } else { ret = false; error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData()); } return ret; }
bool lldb_private::InferiorCallMmap (Process *process, addr_t &allocated_addr, addr_t addr, addr_t length, unsigned prot, unsigned flags, addr_t fd, addr_t offset) { Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL) return false; const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; const uint32_t count = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; EvaluateExpressionOptions options; options.SetStopOthers(true); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetDebug (false); options.SetTimeoutUsec(500000); addr_t prot_arg, flags_arg = 0; if (prot == eMmapProtNone) prot_arg = PROT_NONE; else { prot_arg = 0; if (prot & eMmapProtExec) prot_arg |= PROT_EXEC; if (prot & eMmapProtRead) prot_arg |= PROT_READ; if (prot & eMmapProtWrite) prot_arg |= PROT_WRITE; } const ArchSpec arch = process->GetTarget().GetArchitecture(); flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags); AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, mmap_range.GetBaseAddress(), clang_void_ptr_type, args, options)); if (call_plan_sp) { StreamFile error_strm; // This plan is a utility plan, so set it to discard itself when done. call_plan_sp->SetIsMasterPlan (true); call_plan_sp->SetOkayToDiscard(true); StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, error_strm); if (result == eExpressionCompleted) { allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (process->GetAddressByteSize() == 4) { if (allocated_addr == UINT32_MAX) return false; } else if (process->GetAddressByteSize() == 8) { if (allocated_addr == UINT64_MAX) return false; } return true; } } } } } } return false; }
bool lldb_private::InferiorCall (Process *process, const Address *address, addr_t &returned_func) { Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL || address == NULL) return false; EvaluateExpressionOptions options; options.SetStopOthers(true); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetDebug (false); options.SetTimeoutUsec(500000); ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, *address, clang_void_ptr_type, llvm::ArrayRef<addr_t>(), options)); if (call_plan_sp) { StreamString error_strm; // This plan is a utility plan, so set it to discard itself when done. call_plan_sp->SetIsMasterPlan (true); call_plan_sp->SetOkayToDiscard(true); StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, error_strm); if (result == eExpressionCompleted) { returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (process->GetAddressByteSize() == 4) { if (returned_func == UINT32_MAX) return false; } else if (process->GetAddressByteSize() == 8) { if (returned_func == UINT64_MAX) return false; } return true; } } } return false; }
bool lldb_private::InferiorCallMunmap (Process *process, addr_t addr, addr_t length) { Thread *thread = process->GetThreadList().GetSelectedThread().get(); if (thread == NULL) return false; const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; const uint32_t count = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; EvaluateExpressionOptions options; options.SetStopOthers(true); options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetDebug (false); options.SetTimeoutUsec(500000); AddressRange munmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) { lldb::addr_t args[] = { addr, length }; lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options)); if (call_plan_sp) { StreamFile error_strm; // This plan is a utility plan, so set it to discard itself when done. call_plan_sp->SetIsMasterPlan (true); call_plan_sp->SetOkayToDiscard(true); StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); ExpressionResults result = process->RunThreadPlan (exe_ctx, call_plan_sp, options, error_strm); if (result == eExpressionCompleted) { return true; } } } } } } return false; }
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, Status &error) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); std::lock_guard<std::mutex> guard(m_condition_mutex); size_t condition_hash; const char *condition_text = GetConditionText(&condition_hash); if (!condition_text) { m_user_expression_sp.reset(); return false; } error.Clear(); DiagnosticManager diagnostics; if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { LanguageType language = eLanguageTypeUnknown; // See if we can figure out the language from the frame, otherwise use the // default language: CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); if (comp_unit) language = comp_unit->GetLanguage(); m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage( condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr, error)); if (error.Fail()) { if (log) log->Printf("Error getting condition expression: %s.", error.AsCString()); m_user_expression_sp.reset(); return true; } if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat( "Couldn't parse conditional expression:\n%s", diagnostics.GetString().c_str()); m_user_expression_sp.reset(); return true; } m_condition_hash = condition_hash; } // We need to make sure the user sees any parse errors in their condition, so // we'll hook the constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetResultIsInternal( true); // Don't generate a user variable for condition expressions. Status expr_error; diagnostics.Clear(); ExpressionVariableSP result_variable_sp; ExpressionResults result_code = m_user_expression_sp->Execute( diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); bool ret; if (result_code == eExpressionCompleted) { if (!result_variable_sp) { error.SetErrorString("Expression did not return a result"); return false; } result_value_sp = result_variable_sp->GetValueObject(); if (result_value_sp) { ret = result_value_sp->IsLogicalTrue(error); if (log) { if (error.Success()) { log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); } else { error.SetErrorString( "Failed to get an integer result from the expression"); ret = false; } } } else { ret = false; error.SetErrorString("Failed to get any result from the expression"); } } else { ret = false; error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); } return ret; }