diff options
Diffstat (limited to 'lldb/source')
7 files changed, 196 insertions, 14 deletions
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 97a9df62566..2c859d5222d 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -1491,13 +1491,12 @@ SBValue SBThread::GetCurrentException() { return SBValue(thread_sp->GetCurrentException()); } -/* TODO(kubamracek) SBThread SBThread::GetCurrentExceptionBacktrace() { ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); if (!thread_sp) return SBThread(); return SBThread(thread_sp->GetCurrentExceptionBacktrace()); -}*/ +} bool SBThread::SafeToCallFunctions() { ThreadSP thread_sp(m_opaque_sp->GetThreadSP()); diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 57dd2a33226..e792887d4ff 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -1552,14 +1552,13 @@ class CommandObjectThreadException : public CommandObjectIterateOverThreads { exception_object_sp->Dump(strm); } - /* TODO(kubamracek) ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace(); if (exception_thread_sp && exception_thread_sp->IsValid()) { const uint32_t num_frames_with_source = 0; const bool stop_format = false; - exception_thread_sp->GetStatus(strm, m_options.m_start, m_options.m_count, + exception_thread_sp->GetStatus(strm, 0, UINT32_MAX, num_frames_with_source, stop_format); - }*/ + } return true; } diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 3f9ae937b73..8fcf33c758c 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -16,6 +16,9 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -549,6 +552,61 @@ bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop( break_site_id, m_cxx_exception_bp_sp->GetID()); } +ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread( + ThreadSP thread_sp) { + ClangASTContext *clang_ast_context = + m_process->GetTarget().GetScratchClangASTContext(); + CompilerType voidstar = + clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + + DiagnosticManager diagnostics; + ExecutionContext exe_ctx; + EvaluateExpressionOptions options; + + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetStopOthers(true); + options.SetTimeout(std::chrono::milliseconds(500)); + options.SetTryAllThreads(false); + thread_sp->CalculateExecutionContext(exe_ctx); + + const ModuleList &modules = m_process->GetTarget().GetImages(); + SymbolContextList contexts; + SymbolContext context; + + modules.FindSymbolsWithNameAndType( + ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts); + contexts.GetContextAtIndex(0, context); + Address addr = context.symbol->GetAddress(); + + Status error; + FunctionCaller *function_caller = + m_process->GetTarget().GetFunctionCallerForLanguage( + eLanguageTypeC, voidstar, addr, ValueList(), "caller", error); + + ExpressionResults func_call_ret; + Value results; + func_call_ret = function_caller->ExecuteFunction(exe_ctx, nullptr, options, + diagnostics, results); + if (func_call_ret != eExpressionCompleted || !error.Success()) { + return ValueObjectSP(); + } + + size_t ptr_size = m_process->GetAddressByteSize(); + addr_t result_ptr = results.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + addr_t exception_addr = + m_process->ReadPointerFromMemory(result_ptr - ptr_size, error); + + lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr, + *m_process); + ValueObjectSP exception = ValueObject::CreateValueObjectFromData( + "exception", exception_isw.GetAsData(m_process->GetByteOrder()), exe_ctx, + voidstar); + exception = exception->GetDynamicValue(eDynamicDontRunTarget); + + return exception; +} + TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo( const lldb_private::Address &vtable_addr) { std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex); diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index 149fe05fcc3..abed3706c6b 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -65,6 +65,9 @@ public: bool throw_bp) override; lldb::SearchFilterSP CreateExceptionSearchFilter() override; + + lldb::ValueObjectSP GetExceptionObjectForThread( + lldb::ThreadSP thread_sp) override; //------------------------------------------------------------------ // PluginInterface protocol diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index f55a7e8dda4..ed47b481a81 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -19,10 +19,13 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -35,6 +38,9 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" +#include "Plugins/Process/Utility/HistoryThread.h" +#include "Plugins/Language/ObjC/NSString.h" + #include <vector> using namespace lldb; @@ -459,6 +465,102 @@ lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() { } } +ValueObjectSP AppleObjCRuntime::GetExceptionObjectForThread( + ThreadSP thread_sp) { + auto cpp_runtime = m_process->GetCPPLanguageRuntime(); + if (!cpp_runtime) return ValueObjectSP(); + auto cpp_exception = cpp_runtime->GetExceptionObjectForThread(thread_sp); + if (!cpp_exception) return ValueObjectSP(); + + auto descriptor = GetClassDescriptor(*cpp_exception.get()); + if (!descriptor || !descriptor->IsValid()) return ValueObjectSP(); + + while (descriptor) { + ConstString class_name(descriptor->GetClassName()); + if (class_name == ConstString("NSException")) return cpp_exception; + descriptor = descriptor->GetSuperclass(); + } + + return ValueObjectSP(); +} + +ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException( + lldb::ValueObjectSP exception_sp) { + ValueObjectSP reserved_dict = + exception_sp->GetChildMemberWithName(ConstString("reserved"), true); + if (!reserved_dict) return ThreadSP(); + + reserved_dict = reserved_dict->GetSyntheticValue(); + if (!reserved_dict) return ThreadSP(); + + CompilerType objc_id = + exception_sp->GetTargetSP()->GetScratchClangASTContext()->GetBasicType( + lldb::eBasicTypeObjCID); + ValueObjectSP return_addresses; + + auto objc_object_from_address = [&exception_sp, &objc_id](uint64_t addr, + const char *name) { + Value value(addr); + value.SetCompilerType(objc_id); + auto object = ValueObjectConstResult::Create( + exception_sp->GetTargetSP().get(), value, ConstString(name)); + object = object->GetDynamicValue(eDynamicDontRunTarget); + return object; + }; + + for (size_t idx = 0; idx < reserved_dict->GetNumChildren(); idx++) { + ValueObjectSP dict_entry = reserved_dict->GetChildAtIndex(idx, true); + + DataExtractor data; + data.SetAddressByteSize(dict_entry->GetProcessSP()->GetAddressByteSize()); + Status error; + dict_entry->GetData(data, error); + if (error.Fail()) return ThreadSP(); + + lldb::offset_t data_offset = 0; + auto dict_entry_key = data.GetPointer(&data_offset); + auto dict_entry_value = data.GetPointer(&data_offset); + + auto key_nsstring = objc_object_from_address(dict_entry_key, "key"); + StreamString key_summary; + if (lldb_private::formatters::NSStringSummaryProvider( + *key_nsstring, key_summary, TypeSummaryOptions()) && + !key_summary.Empty()) { + if (key_summary.GetString() == "\"callStackReturnAddresses\"") { + return_addresses = objc_object_from_address(dict_entry_value, + "callStackReturnAddresses"); + break; + } + } + } + + if (!return_addresses) return ThreadSP(); + auto frames_value = + return_addresses->GetChildMemberWithName(ConstString("_frames"), true); + addr_t frames_addr = frames_value->GetValueAsUnsigned(0); + auto count_value = + return_addresses->GetChildMemberWithName(ConstString("_cnt"), true); + size_t count = count_value->GetValueAsUnsigned(0); + auto ignore_value = + return_addresses->GetChildMemberWithName(ConstString("_ignore"), true); + size_t ignore = ignore_value->GetValueAsUnsigned(0); + + size_t ptr_size = m_process->GetAddressByteSize(); + std::vector<lldb::addr_t> pcs; + for (size_t idx = 0; idx < count; idx++) { + Status error; + addr_t pc = m_process->ReadPointerFromMemory( + frames_addr + (ignore + idx) * ptr_size, error); + pcs.push_back(pc); + } + + if (pcs.empty()) return ThreadSP(); + + ThreadSP new_thread_sp(new HistoryThread(*m_process, 0, pcs, 0, false)); + m_process->GetExtendedThreadList().AddThread(new_thread_sp); + return new_thread_sp; +} + std::tuple<FileSpec, ConstString> AppleObjCRuntime::GetExceptionThrowLocation() { return std::make_tuple( diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index ac2f5c83ca7..86606460014 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -89,6 +89,12 @@ public: static std::tuple<FileSpec, ConstString> GetExceptionThrowLocation(); + lldb::ValueObjectSP GetExceptionObjectForThread( + lldb::ThreadSP thread_sp) override; + + lldb::ThreadSP GetBacktraceThreadFromException( + lldb::ValueObjectSP thread_sp) override; + uint32_t GetFoundationVersion(); virtual void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 65aca860fc3..3662f1bea62 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -23,6 +23,7 @@ #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrameRecognizer.h" @@ -2202,16 +2203,30 @@ Status Thread::StepOut() { } ValueObjectSP Thread::GetCurrentException() { - StackFrameSP frame_sp(GetStackFrameAtIndex(0)); - if (!frame_sp) return ValueObjectSP(); + if (auto frame_sp = GetStackFrameAtIndex(0)) + if (auto recognized_frame = frame_sp->GetRecognizedFrame()) + if (auto e = recognized_frame->GetExceptionObject()) + return e; + + // FIXME: For now, only ObjC exceptions are supported. This should really + // iterate over all language runtimes and ask them all to give us the current + // exception. + if (auto runtime = GetProcess()->GetObjCLanguageRuntime()) + if (auto e = runtime->GetExceptionObjectForThread(shared_from_this())) + return e; - RecognizedStackFrameSP recognized_frame(frame_sp->GetRecognizedFrame()); - if (!recognized_frame) return ValueObjectSP(); - - return recognized_frame->GetExceptionObject(); + return ValueObjectSP(); } -/* TODO(kubamracek) ThreadSP Thread::GetCurrentExceptionBacktrace() { - return ThreadSP(); -}*/ + ValueObjectSP exception = GetCurrentException(); + if (!exception) return ThreadSP(); + + // FIXME: For now, only ObjC exceptions are supported. This should really + // iterate over all language runtimes and ask them all to give us the current + // exception. + auto runtime = GetProcess()->GetObjCLanguageRuntime(); + if (!runtime) return ThreadSP(); + + return runtime->GetBacktraceThreadFromException(exception); +} |