static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) { if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) { const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>( target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) ->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { modules_for_macros.push_back(module); } if (target->GetEnableAutoImportClangModules()) { if (StackFrame *frame = exe_ctx.GetFramePtr()) { if (Block *block = frame->GetFrameBlock()) { SymbolContext sc; block->CalculateSymbolContext(&sc); if (sc.comp_unit) { StreamString error_stream; decl_vendor->AddModulesForCompileUnit( *sc.comp_unit, modules_for_macros, error_stream); } } } } } }
bool Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { AddressRange range; StackFrame *frame = exe_ctx.GetFramePtr(); if (frame) { SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); if (sc.function) { range = sc.function->GetAddressRange(); } else if (sc.symbol && sc.symbol->ValueIsAddress()) { range.GetBaseAddress() = sc.symbol->GetAddress(); range.SetByteSize (sc.symbol->GetByteSize()); } else { range.GetBaseAddress() = frame->GetFrameCodeAddress(); } if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); } return Disassemble (debugger, arch, plugin_name, flavor, exe_ctx, range, num_instructions, num_mixed_context_lines, options, strm); }
size_t Variable::AutoComplete (const ExecutionContext &exe_ctx, const char *partial_path_cstr, StringList &matches, bool &word_complete) { word_complete = false; std::string partial_path; std::string prefix_path; CompilerType compiler_type; if (partial_path_cstr && partial_path_cstr[0]) partial_path = partial_path_cstr; PrivateAutoComplete (exe_ctx.GetFramePtr(), partial_path, prefix_path, compiler_type, matches, word_complete); return matches.GetSize(); }
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) log->Printf("ClangUserExpression::ScanContext()"); m_target = exe_ctx.GetTargetPtr(); if (!(m_allow_cxx || m_allow_objc)) { if (log) log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); return; } StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { if (log) log->Printf(" [CUE::SC] Null stack frame"); return; } SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); if (!sym_ctx.function) { if (log) log->Printf(" [CUE::SC] Null function"); return; } // Find the block that defines the function represented by "sym_ctx" Block *function_block = sym_ctx.GetFunctionBlock(); if (!function_block) { if (log) log->Printf(" [CUE::SC] Null function block"); return; } clang::DeclContext *decl_context = function_block->GetClangDeclContext(); if (!decl_context) { if (log) log->Printf(" [CUE::SC] Null decl context"); return; } if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context)) { if (m_allow_cxx && method_decl->isInstance()) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); if (!this_var_sp || !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } m_cplusplus = true; m_needs_object_ptr = true; } } else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context)) { if (m_allow_objc) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } } m_objectivec = true; m_needs_object_ptr = true; if (!method_decl->isInstanceMethod()) m_static_method = true; } } else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context)) { // We might also have a function that said in the debug information that it captured an // object pointer. The best way to deal with getting to the ivars at present it by pretending // that this is a method of a class in whatever runtime the debug info says the object pointer // belongs to. Do that here. ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl); if (metadata && metadata->HasObjectPtr()) { lldb::LanguageType language = metadata->GetObjectPtrLanguage(); if (language == lldb::eLanguageTypeC_plus_plus) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); if (!this_var_sp || !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } m_cplusplus = true; m_needs_object_ptr = true; } else if (language == lldb::eLanguageTypeObjC) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } Type *self_type = self_variable_sp->GetType(); if (!self_type) { err.SetErrorString(selfErrorString); return; } ClangASTType self_clang_type = self_type->GetClangForwardType(); if (!self_clang_type) { err.SetErrorString(selfErrorString); return; } if (self_clang_type.IsObjCClassType()) { return; } else if (self_clang_type.IsObjCObjectPointerType()) { m_objectivec = true; m_needs_object_ptr = true; } else { err.SetErrorString(selfErrorString); return; } } else { m_objectivec = true; m_needs_object_ptr = true; } } } } }
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); if (Target *target = exe_ctx.GetTargetPtr()) { if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) { m_result_delegate.RegisterPersistentState(persistent_state); } else { error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); return false; } } else { error_stream.PutCString ("error: couldn't start parsing (no target)"); return false; } 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::string prefix = m_expr_prefix; if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) { const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { modules_for_macros.push_back(module); } if (m_target->GetEnableAutoImportClangModules()) { if (StackFrame *frame = exe_ctx.GetFramePtr()) { if (Block *block = frame->GetFrameBlock()) { SymbolContext sc; block->CalculateSymbolContext(&sc); if (sc.comp_unit) { StreamString error_stream; decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); } } } } } std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); lldb::LanguageType lang_type; if (m_in_cplusplus_method) lang_type = lldb::eLanguageTypeC_plus_plus; else if (m_in_objectivec_method) lang_type = lldb::eLanguageTypeObjC; else lang_type = lldb::eLanguageTypeC; if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_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()); ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); 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]() { ResetDeclMap(); }); if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); ResetDeclMap(); // 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); ResetDeclMap(); // 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); // } } ResetDeclMap(); // 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; } }
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; }
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 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; }
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 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; }