bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { Error error; m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, lldb::eLanguageTypeC, VALID_POINTER_CHECK_NAME, error)); if (error.Fail()) return false; if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) return false; Process *process = exe_ctx.GetProcessPtr(); if (process) { ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime(); if (objc_language_runtime) { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) return false; } } return true; }
SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, ThreadPlan *new_plan) { SBError sb_error; Process *process = exe_ctx.GetProcessPtr(); if (!process) { sb_error.SetErrorString("No process in SBThread::ResumeNewPlan"); return sb_error; } Thread *thread = exe_ctx.GetThreadPtr(); if (!thread) { sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan"); return sb_error; } // User level plans should be Master Plans so they can be interrupted, other // plans executed, and // then a "continue" will resume the plan. if (new_plan != NULL) { new_plan->SetIsMasterPlan(true); new_plan->SetOkayToDiscard(false); } // Why do we need to set the current thread by ID here??? process->GetThreadList().SetSelectedThreadByID(thread->GetID()); if (process->GetTarget().GetDebugger().GetAsyncExecution()) sb_error.ref() = process->Resume(); else sb_error.ref() = process->ResumeSynchronous(NULL); return sb_error; }
bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, const RegisterInfo *reg_info) { if (reg_info) { RegisterValue reg_value; if (reg_ctx->ReadRegister(reg_info, reg_value)) { strm.Indent(); bool prefix_with_altname = (bool)m_command_options.alternate_name; bool prefix_with_name = !prefix_with_altname; reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8); if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)) { Process *process = exe_ctx.GetProcessPtr(); if (process && reg_info->byte_size == process->GetAddressByteSize()) { addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); if (reg_addr != LLDB_INVALID_ADDRESS) { Address so_reg_addr; if (exe_ctx.GetTargetRef() .GetSectionLoadList() .ResolveLoadAddress(reg_addr, so_reg_addr)) { strm.PutCString(" "); so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); } } } } strm.EOL(); return true; } } return false; }
bool DynamicCheckerFunctions::Install(Stream &error_stream, ExecutionContext &exe_ctx) { m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text, VALID_POINTER_CHECK_NAME)); if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) return false; Process *process = exe_ctx.GetProcessPtr(); if (process) { ObjCLanguageRuntime *objc_language_runtime = process->GetObjCLanguageRuntime(); if (objc_language_runtime) { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); if (!m_objc_object_check->Install(error_stream, exe_ctx)) return false; } } return true; }
bool ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) { // Read the return value - it is the last field in the struct: // FIXME: How does clang tell us there's no return value? We need to handle that case. // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject // to fetch the value. That way we can fetch any values we need. Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return false; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (process != jit_process_sp.get()) return false; Error error; ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error); if (error.Fail()) return false; ret_value.SetCompilerType(m_function_return_type); ret_value.SetValueType(Value::eValueTypeScalar); return true; }
lldb::ExpressionResults GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); Target *target = exe_ctx.GetTargetPtr(); if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, " "but is not constant =="); diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression needed to run but couldn't"); return execution_results; } } m_interpreter->set_use_dynamic(options.GetUseDynamic()); ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); Error err = m_interpreter->error(); m_interpreter.reset(); if (!result_val_sp) { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); result->m_live_sp = result->m_frozen_sp = result_val_sp; result->m_flags |= ExpressionVariable::EVIsProgramReference; PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); if (pv != nullptr) { result->SetName(pv->GetNextPersistentVariableName()); pv->AddVariable(result); } return lldb::eExpressionCompleted; }
bool ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) { Process *process = exe_ctx.GetProcessPtr(); if (!process) return false; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (process != jit_process_sp.get()) return false; if (!m_compiled) return false; if (m_JITted) return true; bool can_interpret = false; // should stay that way Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways)); if (!jit_error.Success()) return false; if (m_parser->GetGenerateDebugInfo()) { lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; jit_file.GetFilename() = const_func_name; jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); m_jit_module_wp = jit_module_sp; process->GetTarget().GetImages().Append(jit_module_sp); } } if (process && m_jit_start_addr) m_jit_process_wp = process->shared_from_this(); m_JITted = true; return true; }
bool FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { Process *process = exe_ctx.GetProcessPtr(); if (!process) return false; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (process != jit_process_sp.get()) return false; if (!m_compiled) return false; if (m_JITted) return true; bool can_interpret = false; // should stay that way Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways)); if (!jit_error.Success()) return false; if (m_parser->GetGenerateDebugInfo()) m_execution_unit_sp->CreateJITModule(FunctionName()); if (process && m_jit_start_addr) m_jit_process_wp = process->shared_from_this(); m_JITted = true; return true; }
bool ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) { Process *process = exe_ctx.GetProcessPtr(); if (!process) return false; if (process != m_jit_process_sp.get()) return false; if (!m_compiled) return false; if (m_JITted) return true; lldb::ClangExpressionVariableSP const_result; bool evaluated_statically = false; // should stay that way Error jit_error (m_parser->PrepareForExecution (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, NULL, evaluated_statically, const_result, eExecutionPolicyAlways)); if (!jit_error.Success()) return false; if (process && m_jit_alloc != LLDB_INVALID_ADDRESS) m_jit_process_sp = process->shared_from_this(); return true; }
bool ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) { // Read the return value - it is the last field in the struct: // FIXME: How does clang tell us there's no return value? We need to handle that case. // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject // to fetch the value. That way we can fetch any values we need. Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return false; if (process != m_jit_process_sp.get()) return false; Error error; ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error); if (error.Fail()) return false; ret_value.SetContext (Value::eContextTypeClangType, m_function_return_qual_type); ret_value.SetValueType(Value::eValueTypeScalar); return true; }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] error_stream /// A stream to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install (Stream &error_stream, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { error_stream.PutCString("error: already installed\n"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { error_stream.PutCString ("error: invalid process\n"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); if (!m_expr_decl_map->WillParse(exe_ctx, NULL)) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; } ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this); unsigned num_errors = parser.Parse (error_stream); if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); m_expr_decl_map.reset(); return false; } ////////////////////////////////// // JIT the output of the parser // bool can_interpret = false; // should stay that way Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_ap, exe_ctx, can_interpret, eExecutionPolicyAlways); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif m_expr_decl_map->DidParse(); m_expr_decl_map.reset(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
ExecutionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, bool unwind_on_error, bool ignore_breakpoints, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result, bool run_others, uint32_t timeout_usec) { // The expression log is quite verbose, and if you're just tracking the execution of the // expression, it's quite convenient to have these logs come out with the STEP log as well. Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; lldb::addr_t object_ptr = 0; lldb::addr_t cmd_ptr = 0; if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) { error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return eExecutionSetupError; } lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; if (m_can_interpret) { llvm::Module *module = m_execution_unit_ap->GetModule(); llvm::Function *function = m_execution_unit_ap->GetFunction(); if (!module || !function) { error_stream.Printf("Supposed to interpret, but nothing is there"); return eExecutionSetupError; } Error interpreter_error; llvm::SmallVector <lldb::addr_t, 3> args; if (m_needs_object_ptr) { args.push_back(object_ptr); if (m_objectivec) args.push_back(cmd_ptr); } args.push_back(struct_address); function_stack_bottom = m_stack_frame_bottom; function_stack_top = m_stack_frame_top; IRInterpreter::Interpret (*module, *function, args, *m_execution_unit_ap.get(), interpreter_error, function_stack_bottom, function_stack_top); if (!interpreter_error.Success()) { error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); return eExecutionDiscarded; } } else { const bool stop_others = true; const bool try_all_threads = run_others; Address wrapper_address (m_jit_start_addr); lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), wrapper_address, struct_address, stop_others, unwind_on_error, ignore_breakpoints, (m_needs_object_ptr ? &object_ptr : NULL), ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL), shared_ptr_to_me)); if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) return eExecutionSetupError; lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer(); function_stack_bottom = function_stack_pointer - Host::GetPageSize(); function_stack_top = function_stack_pointer; if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, stop_others, try_all_threads, unwind_on_error, ignore_breakpoints, timeout_usec, error_stream); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint) { const char *error_desc = NULL; if (call_plan_sp) { lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); if (real_stop_info_sp) error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); else error_stream.Printf ("Execution was interrupted."); if ((execution_result == eExecutionInterrupted && unwind_on_error) || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints)) error_stream.Printf ("\nThe process has been returned to the state before expression evaluation."); else error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation."); return execution_result; } else if (execution_result != eExecutionCompleted) { error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); return execution_result; } } if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) { return eExecutionCompleted; } else { return eExecutionSetupError; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); return eExecutionSetupError; } }
ExecutionResults ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, lldb::LanguageType language, ResultType desired_type, bool unwind_on_error, bool ignore_breakpoints, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, bool run_others, uint32_t timeout_usec) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); ExecutionResults execution_results = eExecutionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type)); StreamString error_stream; if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory)) { if (error_stream.GetString().empty()) error.SetErrorString ("expression failed to parse, unknown error"); else error.SetErrorString (error_stream.GetString().c_str()); } else { lldb::ClangExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) error.SetErrorString ("expression needed to run but couldn't"); } else { error_stream.GetString().clear(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, unwind_on_error, ignore_breakpoints, user_expression_sp, expr_result, run_others, timeout_usec); if (execution_results != eExecutionCompleted) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetErrorString ("expression failed to execute, unknown error"); else error.SetErrorString (error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (result_valobj_sp.get() == NULL) result_valobj_sp = ValueObjectConstResult::Create (NULL, error); return execution_results; }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; StackFrame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) { pc_addr_ptr = &frame->GetFrameCodeAddress(); } const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; const FormatEntity::Entry *disassembly_format = NULL; FormatEntity::Entry format; if (exe_ctx.HasTargetScope()) { disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); } else { FormatEntity::Parse("${addr}: ", format); disassembly_format = &format; } // First pass: step through the list of instructions, // find how long the initial addresses strings are, insert padding // in the second pass so the opcodes all line up nicely. size_t address_text_size = 0; for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); ModuleSP module_sp (addr.GetModule()); if (module_sp) { const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol; uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); if (resolved_mask) { StreamString strmstr; Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr); size_t cur_line = strmstr.GetSizeOfLastLine(); if (cur_line > address_text_size) address_text_size = cur_line; } sc.Clear(false); } } } for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } } else { sc.Clear(true); } } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size); strm.EOL(); } else { break; } } return true; }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] diagnostic_manager /// A diagnostic manager to report errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; ResetDeclMap(exe_ctx, keep_result_in_memory); if (!DeclMap()->WillParse(exe_ctx, NULL)) { diagnostic_manager.PutCString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); return false; } const bool generate_debug_info = true; ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); unsigned num_errors = parser.Parse(diagnostic_manager); if (num_errors) { ResetDeclMap(); return false; } ////////////////////////////////// // JIT the output of the parser // bool can_interpret = false; // should stay that way Error jit_error = parser.PrepareForExecution( m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { m_jit_process_wp = process->shared_from_this(); if (parser.GetGenerateDebugInfo()) m_execution_unit_sp->CreateJITModule(FunctionName()); } #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif DeclMap()->DidParse(); ResetDeclMap(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) { diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); } else { diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); } return false; } }
lldb_private::Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb_private::Error err; std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } ConstString function_name; if (execution_policy != eExecutionPolicyTopLevel) { // Find the actual name of the function (it's often mangled somehow) if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } } SymbolContext sc; if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) { sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); } else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) { sc.target_sp = target_sp; } LLVMUserExpression::IRPasses custom_passes; { auto lang = m_expr.Language(); if (log) log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, Language::GetNameForLanguageType(lang)); if (lang != lldb::eLanguageTypeUnknown) { auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang); if (runtime) runtime->GetIRPasses(custom_passes); } } if (custom_passes.EarlyPasses) { if (log) log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, m_expr.FunctionName()); custom_passes.EarlyPasses->run(*llvm_module_ap); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), sc, m_compiler->getTargetOpts().Features)); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = target->GetDebugger().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Process *process = exe_ctx.GetProcessPtr(); if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel) { lldb_private::Error interpret_error; bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } } if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (!process && execution_policy == eExecutionPolicyTopLevel) { err.SetErrorString( "Top-level code needs to be inserted into a runnable target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) { if (m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); DiagnosticManager install_diagnostics; if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { if (install_diagnostics.Diagnostics().size()) err.SetErrorString("couldn't install checkers, unknown error"); else err.SetErrorString(install_diagnostics.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); llvm::Module *module = execution_unit_sp->GetModule(); if (!module || !ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } if (custom_passes.LatePasses) { if (log) log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, m_expr.FunctionName()); custom_passes.LatePasses->run(*module); } } } if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel || !can_interpret) { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; }
size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx) { m_cursors.clear(); Frame *first_frame = exe_ctx.GetFramePtr(); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return 0; std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; struct Frame_i386 { uint32_t fp; uint32_t pc; }; RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); assert (reg_ctx); Cursor cursor; cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS); cursor.fp = reg_ctx->GetFP (0); Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) }; m_cursors.push_back(cursor); const size_t k_frame_size = sizeof(frame); Error error; while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0)) { // Read both the FP and PC (8 bytes) if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size) break; if (frame.pc >= 0x1000) { cursor.pc = frame.pc; cursor.fp = frame.fp; m_cursors.push_back (cursor); } } if (!m_cursors.empty()) { lldb::addr_t first_frame_pc = m_cursors.front().pc; if (first_frame_pc != LLDB_INVALID_ADDRESS) { const uint32_t resolve_scope = eSymbolContextModule | eSymbolContextCompUnit | eSymbolContextFunction | eSymbolContextSymbol; SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope)); const AddressRange *addr_range_ptr = NULL; AddressRange range; if (first_frame_sc.function) addr_range_ptr = &first_frame_sc.function->GetAddressRange(); else if (first_frame_sc.symbol) { range.GetBaseAddress() = first_frame_sc.symbol->GetAddress(); range.SetByteSize (first_frame_sc.symbol->GetByteSize()); addr_range_ptr = ⦥ } if (addr_range_ptr) { if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress()) { // We are at the first instruction, so we can recover the // previous PC by dereferencing the SP lldb::addr_t first_frame_sp = reg_ctx->GetSP (0); // Read the real second frame return address into frame.pc if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc)) { cursor.fp = m_cursors.front().fp; cursor.pc = frame.pc; // Set the new second frame PC // Insert the second frame m_cursors.insert(m_cursors.begin()+1, cursor); m_cursors.front().fp = first_frame_sp; } } } } } // uint32_t i=0; // printf(" PC FP\n"); // printf(" ------------------ ------------------ \n"); // for (i=0; i<m_cursors.size(); ++i) // { // printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp); // } return m_cursors.size(); }
lldb::ExpressionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result) { // The expression log is quite verbose, and if you're just tracking the execution of the // expression, it's quite convenient to have these logs come out with the STEP log as well. Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; lldb::addr_t object_ptr = 0; lldb::addr_t cmd_ptr = 0; if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) { error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return lldb::eExpressionSetupError; } lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; if (m_can_interpret) { llvm::Module *module = m_execution_unit_sp->GetModule(); llvm::Function *function = m_execution_unit_sp->GetFunction(); if (!module || !function) { error_stream.Printf("Supposed to interpret, but nothing is there"); return lldb::eExpressionSetupError; } Error interpreter_error; llvm::SmallVector <lldb::addr_t, 3> args; if (m_needs_object_ptr) { args.push_back(object_ptr); if (m_objectivec) args.push_back(cmd_ptr); } args.push_back(struct_address); function_stack_bottom = m_stack_frame_bottom; function_stack_top = m_stack_frame_top; IRInterpreter::Interpret (*module, *function, args, *m_execution_unit_sp.get(), interpreter_error, function_stack_bottom, function_stack_top); if (!interpreter_error.Success()) { error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); return lldb::eExpressionDiscarded; } } else { if (!exe_ctx.HasThreadScope()) { error_stream.Printf("ClangUserExpression::Execute called with no thread selected."); return lldb::eExpressionSetupError; } Address wrapper_address (m_jit_start_addr); llvm::SmallVector <lldb::addr_t, 3> args; if (m_needs_object_ptr) { args.push_back(object_ptr); if (m_objectivec) args.push_back(cmd_ptr); } args.push_back(struct_address); ThreadPlanCallUserExpression *user_expression_plan = new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), wrapper_address, args, options, shared_ptr_to_me); lldb::ThreadPlanSP call_plan_sp(user_expression_plan); if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) return lldb::eExpressionSetupError; lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); function_stack_top = function_stack_pointer; if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, options, error_stream); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) { const char *error_desc = NULL; if (call_plan_sp) { lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); if (real_stop_info_sp) error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); else error_stream.PutCString ("Execution was interrupted."); if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation."); else { if (execution_result == lldb::eExpressionHitBreakpoint) user_expression_plan->TransferExpressionOwnership(); error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, " "use \"thread return -x\" to return to the state before expression evaluation."); } return execution_result; } else if (execution_result == lldb::eExpressionStoppedForDebug) { error_stream.PutCString ("Execution was halted at the first instruction of the expression " "function because \"debug\" was requested.\n" "Use \"thread return -x\" to return to the state before expression evaluation."); return execution_result; } else if (execution_result != lldb::eExpressionCompleted) { error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); return execution_result; } } if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) { return lldb::eExpressionCompleted; } else { return lldb::eExpressionResultUnavailable; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, IRForTarget::StaticDataAllocator *data_allocator, bool &evaluated_statically, lldb::ClangExpressionVariableSP &const_result, ExecutionPolicy execution_policy) { func_allocation_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); std::auto_ptr<llvm::ExecutionEngine> execution_engine; Error err; llvm::Module *module = m_code_generator->ReleaseModule(); if (!module) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) std::string function_name; if (!FindFunctionInModule(function_name, module, m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName()); } ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = &target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), execution_policy, const_result, data_allocator, error_stream, function_name.c_str()); ir_for_target.runOnModule(*module); Error &interpreter_error(ir_for_target.getInterpreterError()); if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success()) { if (const_result) const_result->TransferAddress(); evaluated_statically = true; err.Clear(); return err; } Process *process = exe_ctx.GetProcessPtr(); if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); if (execution_policy == eExecutionPolicyAlways) err.SetErrorString("Execution needed to run in the target, but the target can't be run"); else err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString()); return err; } if (execution_policy != eExecutionPolicyNever && m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str()); if (!ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } } // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called // below so we don't need to free it. RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager(); std::string error_string; if (log) { std::string s; raw_string_ostream oss(s); module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } EngineBuilder builder(module); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(llvm::Reloc::PIC_) .setJITMemoryManager(jit_memory_manager) .setOptLevel(CodeGenOpt::Less) .setAllocateGVsWithCode(true) .setCodeModel(CodeModel::Small) .setUseMCJIT(true); execution_engine.reset(builder.create()); if (!execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } execution_engine->DisableLazyCompilation(); llvm::Function *function = module->getFunction (function_name.c_str()); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = execution_engine->getPointerToFunction(function); // Errors usually cause failures in the JIT, but if we're lucky we get here. if (!function) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str()); return err; } if (!fun_ptr) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str()); return err; } m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr)); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target"); return err; } jit_memory_manager->CommitAllocations(*process); jit_memory_manager->ReportAllocations(*execution_engine); jit_memory_manager->WriteData(*process); std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos != end; pos++) { (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr); if (!(*pos).m_name.compare(function_name.c_str())) { RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr); func_end = func_range.first + func_range.second; func_addr = (*pos).m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } } execution_engine.reset(); err.Clear(); return err; }
Error ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); const char *name = m_expr.FunctionName(); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos < end; pos++) { if (strstr(pos->m_name.c_str(), name)) { func_local_addr = pos->m_local_addr; func_remote_addr = pos->m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name); return ret; } if (log) log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr); if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name); return ret; } if (log) log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); Process *process = exe_ctx.GetProcessPtr(); Error err; process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } ArchSpec arch(target->GetArchitecture()); Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL); if (disassembler == NULL) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } if (!process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } DataExtractor extractor(buffer_sp, process->GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); if (log) { log->Printf("Function data has contents:"); extractor.PutToLog (log.get(), 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false); InstructionList &instruction_list = disassembler->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) { Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); instruction->Dump (&stream, max_opcode_byte_size, true, true, &exe_ctx); stream.PutChar('\n'); } return ret; }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); Frame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) pc_addr_ptr = &frame->GetFrameCodeAddress(); const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; for (size_t i=0; i<num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol)) { if (prev_sc.function || prev_sc.symbol) strm.EOL(); bool show_fullpaths = false; bool show_module = true; bool show_inlined_frames = true; sc.DumpStopContext (&strm, exe_scope, addr, show_fullpaths, show_module, show_inlined_frames); strm << ":\n"; } } else { sc.Clear(true); } } if ((options & eOptionMarkPCAddress) && pc_addr_ptr) { strm.PutCString(inst_is_at_pc ? "-> " : " "); } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx); strm.EOL(); } else { break; } } return true; }
lldb::ExpressionResults ClangFunction::ExecuteFunction( ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, Stream &errors, Value &results) { using namespace clang; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore // breakpoints, unwind on error, and don't try to debug it. EvaluateExpressionOptions real_options = options; real_options.SetDebug(false); real_options.SetUnwindOnError(true); real_options.SetIgnoreBreakpoints(true); lldb::addr_t args_addr; if (args_addr_ptr != NULL) args_addr = *args_addr_ptr; else args_addr = LLDB_INVALID_ADDRESS; if (CompileFunction(errors) != 0) return lldb::eExpressionSetupError; if (args_addr == LLDB_INVALID_ADDRESS) { if (!InsertFunction(exe_ctx, args_addr, errors)) return lldb::eExpressionSetupError; } Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, args_addr, real_options, errors); if (!call_plan_sp) return lldb::eExpressionSetupError; // We need to make sure we record the fact that we are running an expression here // otherwise this fact will fail to be recorded when fetching an Objective-C object description if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, real_options, errors); if (log) { if (return_value != lldb::eExpressionCompleted) { log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); } else { log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); } } if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); if (args_addr_ptr != NULL) *args_addr_ptr = args_addr; if (return_value != lldb::eExpressionCompleted) return return_value; FetchFunctionResults(exe_ctx, args_addr, results); if (args_addr_ptr == NULL) DeallocateFunctionResults(exe_ctx, args_addr); return lldb::eExpressionCompleted; }
bool ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); return false; } Error error; using namespace clang; ExecutionResults return_value = eExecutionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return return_value; if (process != m_jit_process_sp.get()) return false; if (args_addr_ref == LLDB_INVALID_ADDRESS) { args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); if (args_addr_ref == LLDB_INVALID_ADDRESS) return false; m_wrapper_args_addrs.push_back (args_addr_ref); } else { // Make sure this is an address that we've already handed out. if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) { return false; } } // TODO: verify fun_addr needs to be a callable address Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); int first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); // FIXME: We will need to extend this for Variadic functions. Error value_error; size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { errors.Printf ("Wrong number of arguments - was: %lu should be: %lu", num_args, m_arg_values.GetSize()); return false; } for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. int offset = m_member_offsets[i+1]; // Clang sizes are in bytes. Value *arg_value = arg_values.GetValueAtIndex(i); // FIXME: For now just do scalars: // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) if (arg_value->GetValueType() == Value::eValueTypeHostAddress && arg_value->GetContextType() == Value::eContextTypeClangType && ClangASTContext::IsPointerType(arg_value->GetClangType())) continue; const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext()); if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) return false; } return true; }
lldb::ExpressionResults UserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, full_prefix, language, desired_type, options, error)); if (error.Fail()) { if (log) log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info, 0)) { execution_results = lldb::eExpressionParseError; if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) *jit_module_sp_ptr = user_expression_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else { if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } error_stream.GetString().clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal() && expr_result && process) { process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); } if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }
bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; InstallContext(exe_ctx); ScanContext(exe_ctx, err); if (!err.Success()) { error_stream.Printf("warning: %s\n", err.AsCString()); } StreamString m_transformed_stream; //////////////////////////////////// // Generate the expression // ApplyObjcCastHack(m_expr_text); //ApplyUnicharHack(m_expr_text); std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str())); lldb::LanguageType lang_type; if (m_cplusplus) lang_type = lldb::eLanguageTypeC_plus_plus; else if(m_objectivec) lang_type = lldb::eLanguageTypeObjC; else lang_type = lldb::eLanguageTypeC; if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx)) { error_stream.PutCString ("error: couldn't construct expression body"); return false; } if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } ////////////////////////// // Parse the expression // m_materializer_ap.reset(new Materializer()); m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); class OnExit { public: typedef std::function <void (void)> Callback; OnExit (Callback const &callback) : m_callback(callback) { } ~OnExit () { m_callback(); } private: Callback m_callback; }; OnExit on_exit([this]() { m_expr_decl_map.reset(); }); if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get())) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. return false; } Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); ClangExpressionParser parser(exe_scope, *this, generate_debug_info); unsigned num_errors = parser.Parse (error_stream); if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. return false; } ////////////////////////////////////////////////////////////////////////////////////////// // Prepare the output of the parser for execution, evaluating it statically if possible // Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, m_can_interpret, execution_policy); if (generate_debug_info) { lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { ConstString const_func_name(FunctionName()); FileSpec jit_file; jit_file.GetFilename() = const_func_name; jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); m_jit_module_wp = jit_module_sp; target->GetImages().Append(jit_module_sp); } // lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); // StreamFile strm (stdout, false); // if (jit_obj_file) // { // jit_obj_file->GetSectionList(); // jit_obj_file->GetSymtab(); // jit_obj_file->Dump(&strm); // } // lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); // if (jit_sym_vendor) // { // lldb_private::SymbolContextList sc_list; // jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); // sc_list.Dump(&strm, target); // jit_sym_vendor->Dump(&strm); // } } m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. if (jit_error.Success()) { if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] error_stream /// A stream to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install (Stream &error_stream, ExecutionContext &exe_ctx) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { error_stream.PutCString("error: already installed\n"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { error_stream.PutCString ("error: invalid process\n"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); m_data_allocator.reset(new ProcessDataAllocator(*process)); if (!m_expr_decl_map->WillParse(exe_ctx)) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; } ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this); unsigned num_errors = parser.Parse (error_stream); if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); m_expr_decl_map.reset(); return false; } ////////////////////////////////// // JIT the output of the parser // lldb::ClangExpressionVariableSP const_result; bool evaluated_statically = false; // should stay that way Error jit_error = parser.PrepareForExecution (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), evaluated_statically, const_result, eExecutionPolicyAlways); if (log) { StreamString dump_string; m_data_allocator->Dump(dump_string); log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str()); } if (m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif m_expr_decl_map->DidParse(); m_expr_decl_map.reset(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
lldb::ExpressionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); const lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type)); StreamString error_stream; if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info)) { if (error_stream.GetString().empty()) error.SetExpressionError (lldb::eExpressionParseError, "expression failed to parse, unknown error"); else error.SetExpressionError (lldb::eExpressionParseError, error_stream.GetString().c_str()); } else { lldb::ClangExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else { if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } error_stream.GetString().clear(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal()) { process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); } if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, IRForTarget::StaticDataAllocator *data_allocator, bool &evaluated_statically, lldb::ClangExpressionVariableSP &const_result, ExecutionPolicy execution_policy) { func_allocation_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; llvm::Module *module = m_code_generator->ReleaseModule(); if (!module) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) std::string function_name; if (!FindFunctionInModule(function_name, module, m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName()); } ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = &target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), execution_policy, const_result, data_allocator, error_stream, function_name.c_str()); if (!ir_for_target.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't prepare the expression for execution in the target"); return err; } if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess()) { evaluated_statically = true; err.Clear(); return err; } Process *process = exe_ctx.GetProcessPtr(); if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); err.SetErrorString("Execution needed to run in the target, but the target can't be run"); return err; } if (execution_policy != eExecutionPolicyNever && m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str()); if (!ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } } // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called // below so we don't need to free it. RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager(); std::string error_string; if (log) { std::string s; raw_string_ostream oss(s); module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } #if defined (USE_STANDARD_JIT) m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, &error_string, jit_memory_manager, CodeGenOpt::Less, true, Reloc::Default, CodeModel::Small)); #else EngineBuilder builder(module); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(llvm::Reloc::PIC_) .setJITMemoryManager(jit_memory_manager) .setOptLevel(CodeGenOpt::Less) .setAllocateGVsWithCode(true) .setCodeModel(CodeModel::Small) .setUseMCJIT(true); m_execution_engine.reset(builder.create()); #endif if (!m_execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } m_execution_engine->DisableLazyCompilation(); llvm::Function *function = module->getFunction (function_name.c_str()); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = m_execution_engine->getPointerToFunction(function); // Errors usually cause failures in the JIT, but if we're lucky we get here. if (!function) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str()); return err; } if (!fun_ptr) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str()); return err; } m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr)); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target"); return err; } // Look over the regions allocated for the function compiled. The JIT // tries to allocate the functions & stubs close together, so we should try to // write them that way too... // For now I only write functions with no stubs, globals, exception tables, // etc. So I only need to write the functions. size_t alloc_size = 0; std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin(); std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end(); for (; fun_pos != fun_end; ++fun_pos) { size_t mem_size = fun_pos->second - fun_pos->first; if (log) log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size); alloc_size += mem_size; } Error alloc_error; func_allocation_addr = process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error); if (func_allocation_addr == LLDB_INVALID_ADDRESS) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error")); return err; } lldb::addr_t cursor = func_allocation_addr; for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++) { lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first; lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second; size_t size = lend - lstart; Error write_error; if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error")); return err; } jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor); cursor += size; } std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos != end; pos++) { (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr); if (!(*pos).m_name.compare(function_name.c_str())) { func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).second; func_addr = (*pos).m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } } err.Clear(); return err; }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr<IRExecutionUnit> &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) ConstString function_name; if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), m_compiler->getTargetOpts().Features)); ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = target->GetDebugger().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Error interpret_error; can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); Process *process = exe_ctx.GetProcessPtr(); if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || !can_interpret) { if (m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; }
lldb::ExpressionResults UserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); error.SetErrorString ("expression needed to run but couldn't"); return execution_results; } } if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; // We need to set the expression execution thread here, turns out parse can call functions in the process of // looking up symbols, which will escape the context set by exe_ctx passed to Execute. lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp); const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, full_prefix, language, desired_type, options, error)); if (error.Fail()) { if (log) log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } DiagnosticManager diagnostic_manager; bool parse_success = user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); // Calculate the fixed expression always, since we need it for errors. std::string tmp_fixed_expression; if (fixed_expression == nullptr) fixed_expression = &tmp_fixed_expression; const char *fixed_text = user_expression_sp->GetFixedText(); if (fixed_text != nullptr) fixed_expression->append(fixed_text); // If there is a fixed expression, try to parse it: if (!parse_success) { execution_results = lldb::eExpressionParseError; if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) { lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(), full_prefix, language, desired_type, options, error)); DiagnosticManager fixed_diagnostic_manager; parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); if (parse_success) { diagnostic_manager.Clear(); user_expression_sp = fixed_expression_sp; } else { // If the fixed expression failed to parse, don't tell the user about, that won't help. fixed_expression->clear(); } } if (!parse_success) { if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s", fixed_expression->c_str()); } else { if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } } } if (parse_success) { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) *jit_module_sp_ptr = user_expression_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else if (execution_policy == eExecutionPolicyTopLevel) { error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); return lldb::eExpressionCompleted; } else { if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); return lldb::eExpressionInterrupted; } if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); } return execution_results; }