Path: blob/main/contrib/llvm-project/lldb/source/Target/LanguageRuntime.cpp
39587 views
//===-- LanguageRuntime.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Target/LanguageRuntime.h"9#include "lldb/Core/PluginManager.h"10#include "lldb/Core/SearchFilter.h"11#include "lldb/Interpreter/CommandInterpreter.h"12#include "lldb/Target/Language.h"13#include "lldb/Target/Target.h"1415using namespace lldb;16using namespace lldb_private;1718char LanguageRuntime::ID = 0;1920ExceptionSearchFilter::ExceptionSearchFilter(const lldb::TargetSP &target_sp,21lldb::LanguageType language,22bool update_module_list)23: SearchFilter(target_sp, FilterTy::Exception), m_language(language),24m_language_runtime(nullptr), m_filter_sp() {25if (update_module_list)26UpdateModuleListIfNeeded();27}2829bool ExceptionSearchFilter::ModulePasses(const lldb::ModuleSP &module_sp) {30UpdateModuleListIfNeeded();31if (m_filter_sp)32return m_filter_sp->ModulePasses(module_sp);33return false;34}3536bool ExceptionSearchFilter::ModulePasses(const FileSpec &spec) {37UpdateModuleListIfNeeded();38if (m_filter_sp)39return m_filter_sp->ModulePasses(spec);40return false;41}4243void ExceptionSearchFilter::Search(Searcher &searcher) {44UpdateModuleListIfNeeded();45if (m_filter_sp)46m_filter_sp->Search(searcher);47}4849void ExceptionSearchFilter::GetDescription(Stream *s) {50UpdateModuleListIfNeeded();51if (m_filter_sp)52m_filter_sp->GetDescription(s);53}5455void ExceptionSearchFilter::UpdateModuleListIfNeeded() {56ProcessSP process_sp(m_target_sp->GetProcessSP());57if (process_sp) {58bool refreash_filter = !m_filter_sp;59if (m_language_runtime == nullptr) {60m_language_runtime = process_sp->GetLanguageRuntime(m_language);61refreash_filter = true;62} else {63LanguageRuntime *language_runtime =64process_sp->GetLanguageRuntime(m_language);65if (m_language_runtime != language_runtime) {66m_language_runtime = language_runtime;67refreash_filter = true;68}69}7071if (refreash_filter && m_language_runtime) {72m_filter_sp = m_language_runtime->CreateExceptionSearchFilter();73}74} else {75m_filter_sp.reset();76m_language_runtime = nullptr;77}78}7980SearchFilterSP ExceptionSearchFilter::DoCreateCopy() {81return SearchFilterSP(82new ExceptionSearchFilter(TargetSP(), m_language, false));83}8485SearchFilter *ExceptionSearchFilter::CreateFromStructuredData(86Target &target, const StructuredData::Dictionary &data_dict,87Status &error) {88SearchFilter *result = nullptr;89return result;90}9192StructuredData::ObjectSP ExceptionSearchFilter::SerializeToStructuredData() {93StructuredData::ObjectSP result_sp;9495return result_sp;96}9798// The Target is the one that knows how to create breakpoints, so this function99// is meant to be used either by the target or internally in100// Set/ClearExceptionBreakpoints.101class ExceptionBreakpointResolver : public BreakpointResolver {102public:103ExceptionBreakpointResolver(lldb::LanguageType language, bool catch_bp,104bool throw_bp)105: BreakpointResolver(nullptr, BreakpointResolver::ExceptionResolver),106m_language(language), m_catch_bp(catch_bp), m_throw_bp(throw_bp) {}107108~ExceptionBreakpointResolver() override = default;109110Searcher::CallbackReturn SearchCallback(SearchFilter &filter,111SymbolContext &context,112Address *addr) override {113114if (SetActualResolver())115return m_actual_resolver_sp->SearchCallback(filter, context, addr);116else117return eCallbackReturnStop;118}119120lldb::SearchDepth GetDepth() override {121if (SetActualResolver())122return m_actual_resolver_sp->GetDepth();123else124return lldb::eSearchDepthTarget;125}126127void GetDescription(Stream *s) override {128Language *language_plugin = Language::FindPlugin(m_language);129if (language_plugin)130language_plugin->GetExceptionResolverDescription(m_catch_bp, m_throw_bp,131*s);132else133Language::GetDefaultExceptionResolverDescription(m_catch_bp, m_throw_bp,134*s);135136SetActualResolver();137if (m_actual_resolver_sp) {138s->Printf(" using: ");139m_actual_resolver_sp->GetDescription(s);140} else141s->Printf(" the correct runtime exception handler will be determined "142"when you run");143}144145void Dump(Stream *s) const override {}146147/// Methods for support type inquiry through isa, cast, and dyn_cast:148static inline bool classof(const BreakpointResolverName *) { return true; }149static inline bool classof(const BreakpointResolver *V) {150return V->getResolverID() == BreakpointResolver::ExceptionResolver;151}152153protected:154BreakpointResolverSP CopyForBreakpoint(BreakpointSP &breakpoint) override {155BreakpointResolverSP ret_sp(156new ExceptionBreakpointResolver(m_language, m_catch_bp, m_throw_bp));157ret_sp->SetBreakpoint(breakpoint);158return ret_sp;159}160161bool SetActualResolver() {162BreakpointSP breakpoint_sp = GetBreakpoint();163if (breakpoint_sp) {164ProcessSP process_sp = breakpoint_sp->GetTarget().GetProcessSP();165if (process_sp) {166bool refreash_resolver = !m_actual_resolver_sp;167if (m_language_runtime == nullptr) {168m_language_runtime = process_sp->GetLanguageRuntime(m_language);169refreash_resolver = true;170} else {171LanguageRuntime *language_runtime =172process_sp->GetLanguageRuntime(m_language);173if (m_language_runtime != language_runtime) {174m_language_runtime = language_runtime;175refreash_resolver = true;176}177}178179if (refreash_resolver && m_language_runtime) {180m_actual_resolver_sp = m_language_runtime->CreateExceptionResolver(181breakpoint_sp, m_catch_bp, m_throw_bp);182}183} else {184m_actual_resolver_sp.reset();185m_language_runtime = nullptr;186}187} else {188m_actual_resolver_sp.reset();189m_language_runtime = nullptr;190}191return (bool)m_actual_resolver_sp;192}193194lldb::BreakpointResolverSP m_actual_resolver_sp;195lldb::LanguageType m_language;196LanguageRuntime *m_language_runtime = nullptr;197bool m_catch_bp;198bool m_throw_bp;199};200201LanguageRuntime *LanguageRuntime::FindPlugin(Process *process,202lldb::LanguageType language) {203LanguageRuntimeCreateInstance create_callback;204for (uint32_t idx = 0;205(create_callback =206PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=207nullptr;208++idx) {209if (LanguageRuntime *runtime = create_callback(process, language))210return runtime;211}212return nullptr;213}214215LanguageRuntime::LanguageRuntime(Process *process) : Runtime(process) {}216217BreakpointPreconditionSP218LanguageRuntime::GetExceptionPrecondition(LanguageType language,219bool throw_bp) {220LanguageRuntimeCreateInstance create_callback;221for (uint32_t idx = 0;222(create_callback =223PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=224nullptr;225idx++) {226if (auto precondition_callback =227PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(228idx)) {229if (BreakpointPreconditionSP precond =230precondition_callback(language, throw_bp))231return precond;232}233}234return BreakpointPreconditionSP();235}236237BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(238Target &target, lldb::LanguageType language, bool catch_bp, bool throw_bp,239bool is_internal) {240BreakpointResolverSP resolver_sp(241new ExceptionBreakpointResolver(language, catch_bp, throw_bp));242SearchFilterSP filter_sp(243new ExceptionSearchFilter(target.shared_from_this(), language));244bool hardware = false;245bool resolve_indirect_functions = false;246BreakpointSP exc_breakpt_sp(247target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware,248resolve_indirect_functions));249if (exc_breakpt_sp) {250if (auto precond = GetExceptionPrecondition(language, throw_bp))251exc_breakpt_sp->SetPrecondition(precond);252253if (is_internal)254exc_breakpt_sp->SetBreakpointKind("exception");255}256257return exc_breakpt_sp;258}259260UnwindPlanSP261LanguageRuntime::GetRuntimeUnwindPlan(Thread &thread, RegisterContext *regctx,262bool &behaves_like_zeroth_frame) {263ProcessSP process_sp = thread.GetProcess();264if (!process_sp.get())265return UnwindPlanSP();266if (process_sp->GetDisableLangRuntimeUnwindPlans() == true)267return UnwindPlanSP();268for (const lldb::LanguageType lang_type : Language::GetSupportedLanguages()) {269if (LanguageRuntime *runtime = process_sp->GetLanguageRuntime(lang_type)) {270UnwindPlanSP plan_sp = runtime->GetRuntimeUnwindPlan(271process_sp, regctx, behaves_like_zeroth_frame);272if (plan_sp.get())273return plan_sp;274}275}276return UnwindPlanSP();277}278279void LanguageRuntime::InitializeCommands(CommandObject *parent) {280if (!parent)281return;282283if (!parent->IsMultiwordObject())284return;285286LanguageRuntimeCreateInstance create_callback;287288for (uint32_t idx = 0;289(create_callback =290PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) !=291nullptr;292++idx) {293if (LanguageRuntimeGetCommandObject command_callback =294PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(idx)) {295CommandObjectSP command =296command_callback(parent->GetCommandInterpreter());297if (command) {298// the CommandObject vended by a Language plugin cannot be created once299// and cached because we may create multiple debuggers and need one300// instance of the command each - the implementing function is meant to301// create a new instance of the command each time it is invoked.302parent->LoadSubCommand(command->GetCommandName().str().c_str(), command);303}304}305}306}307308309