bool ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, lldb::TargetSP &target_sp, lldb::ProcessSP &process_sp, lldb::StackFrameSP &frame_sp) { lldb::ProcessSP expected_process_sp = m_process_wp.lock(); process_sp = exe_ctx.GetProcessSP(); if (process_sp != expected_process_sp) return false; process_sp = exe_ctx.GetProcessSP(); target_sp = exe_ctx.GetTargetSP(); frame_sp = exe_ctx.GetFrameSP(); if (m_address.IsValid()) { if (!frame_sp) return false; else return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); } return true; }
lldb::DisassemblerSP Disassembler::DisassembleRange ( const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &range, bool prefer_file_cache ) { lldb::DisassemblerSP disasm_sp; if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name); if (disasm_sp) { size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL, prefer_file_cache); if (bytes_disassembled == 0) disasm_sp.reset(); } } return disasm_sp; }
bool Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const Address &start_address, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { if (num_instructions > 0) { lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); if (disasm_sp.get()) { Address addr; ResolveAddress (exe_ctx, start_address, addr); const bool prefer_file_cache = false; size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, addr, num_instructions, prefer_file_cache); if (bytes_disassembled == 0) return false; bool result = PrintInstructions (disasm_sp.get(), debugger, arch, exe_ctx, num_instructions, num_mixed_context_lines, options, strm); // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. // I'll fix that but for now, just clear the list and it will go away nicely. disasm_sp->GetInstructionList().Clear(); return result; } } return false; }
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; }
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; }
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_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; }