kubamracek updated this revision to Diff 173603.
kubamracek added a comment.
Updating patch for the recently-landed StackFrameRecognizers.
https://reviews.llvm.org/D43886
Files:
include/lldb/API/SBThread.h
include/lldb/Target/StackFrameRecognizer.h
include/lldb/Target/Thread.h
source/API/SBThread.cpp
source/Commands/CommandObjectThread.cpp
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
source/Target/StackFrameRecognizer.cpp
source/Target/Thread.cpp
Index: source/Target/Thread.cpp
===================================================================
--- source/Target/Thread.cpp
+++ source/Target/Thread.cpp
@@ -29,6 +29,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
@@ -2190,3 +2191,18 @@
}
return error;
}
+
+ValueObjectSP Thread::GetCurrentException() {
+ StackFrameSP frame_sp(GetStackFrameAtIndex(0));
+ if (!frame_sp) return ValueObjectSP();
+
+ RecognizedStackFrameSP recognized_frame(frame_sp->GetRecognizedFrame());
+ if (!recognized_frame) return ValueObjectSP();
+
+ return recognized_frame->GetExceptionObject();
+}
+
+ThreadSP Thread::GetCurrentExceptionBacktrace() {
+ // TODO
+ return ThreadSP();
+}
Index: source/Target/StackFrameRecognizer.cpp
===================================================================
--- source/Target/StackFrameRecognizer.cpp
+++ source/Target/StackFrameRecognizer.cpp
@@ -53,8 +53,8 @@
class StackFrameRecognizerManagerImpl {
public:
- void AddRecognizer(StackFrameRecognizerSP recognizer, ConstString &module,
- ConstString &symbol, bool first_instruction_only) {
+ void AddRecognizer(StackFrameRecognizerSP recognizer, const ConstString &module,
+ const ConstString &symbol, bool first_instruction_only) {
m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(),
symbol, RegularExpressionSP(),
first_instruction_only});
@@ -156,7 +156,7 @@
}
void StackFrameRecognizerManager::AddRecognizer(
- StackFrameRecognizerSP recognizer, ConstString &module, ConstString &symbol,
+ StackFrameRecognizerSP recognizer, const ConstString &module, const ConstString &symbol,
bool first_instruction_only) {
GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
first_instruction_only);
Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
===================================================================
--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -29,6 +29,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
@@ -43,10 +44,12 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
@@ -377,6 +380,8 @@
}
}
+static void RegisterObjCExceptionRecognizer();
+
AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
const ModuleSP &objc_module_sp)
: AppleObjCRuntime(process), m_get_class_info_code(),
@@ -397,6 +402,7 @@
static const ConstString g_gdb_object_getClass("gdb_object_getClass");
m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(
g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+ RegisterObjCExceptionRecognizer();
}
bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
@@ -2596,3 +2602,57 @@
} else
this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
}
+
+#pragma mark Frame recognizers
+
+class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
+ public:
+ ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
+ ThreadSP thread_sp = frame_sp->GetThread();
+ ProcessSP process_sp = thread_sp->GetProcess();
+
+ const lldb::ABISP &abi = process_sp->GetABI();
+ if (!abi) return;
+
+ CompilerType voidstar = process_sp->GetTarget()
+ .GetScratchClangASTContext()
+ ->GetBasicType(lldb::eBasicTypeVoid)
+ .GetPointerType();
+
+ ValueList args;
+ Value input_value;
+ input_value.SetCompilerType(voidstar);
+ args.PushValue(input_value);
+
+ if (!abi->GetArgumentValues(*thread_sp, args)) return;
+
+ addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
+
+ Value value(exception_addr);
+ value.SetCompilerType(voidstar);
+ exception = ValueObjectConstResult::Create(frame_sp.get(), value,
+ ConstString("exception"));
+ exception = exception->GetDynamicValue(eDynamicDontRunTarget);
+ }
+
+ ValueObjectSP exception;
+
+ lldb::ValueObjectSP GetExceptionObject() override { return exception; }
+};
+
+class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
+ lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame) {
+ return lldb::RecognizedStackFrameSP(
+ new ObjCExceptionRecognizedStackFrame(frame));
+ };
+};
+
+static void RegisterObjCExceptionRecognizer() {
+ static llvm::once_flag g_once_flag;
+ llvm::call_once(g_once_flag, []() {
+ StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
+ ConstString("libobjc.A.dylib"), ConstString("objc_exception_throw"),
+ /*first_instruction_only*/ true);
+ });
+}
Index: source/Commands/CommandObjectThread.cpp
===================================================================
--- source/Commands/CommandObjectThread.cpp
+++ source/Commands/CommandObjectThread.cpp
@@ -1515,6 +1515,113 @@
};
//-------------------------------------------------------------------------
+// CommandObjectThreadException
+//-------------------------------------------------------------------------
+
+static OptionDefinition g_thread_exception_options[] = {
+ // clang-format off
+ { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many frames to display (-1 for all)" },
+ { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" },
+ // clang-format on
+};
+
+class CommandObjectThreadException : public CommandObjectIterateOverThreads {
+ public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'c': {
+ int32_t input_count = 0;
+ if (option_arg.getAsInteger(0, m_count)) {
+ m_count = UINT32_MAX;
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%c'", short_option);
+ } else if (input_count < 0)
+ m_count = UINT32_MAX;
+ } break;
+ case 's':
+ if (option_arg.getAsInteger(0, m_start))
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%c'", short_option);
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'",
+ short_option);
+ break;
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_count = UINT32_MAX;
+ m_start = 0;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_thread_exception_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ uint32_t m_count;
+ uint32_t m_start;
+ };
+
+ CommandObjectThreadException(CommandInterpreter &interpreter)
+ : CommandObjectIterateOverThreads(
+ interpreter, "thread exception",
+ "Display the current exception object for a thread. Defaults to "
+ "the current thread.",
+ "thread exception",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
+ m_options() {
+ m_add_return = false;
+ }
+
+ ~CommandObjectThreadException() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
+ ThreadSP thread_sp =
+ m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
+ if (!thread_sp) {
+ result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
+ tid);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream &strm = result.GetOutputStream();
+ ValueObjectSP exception_object_sp = thread_sp->GetCurrentException();
+ if (exception_object_sp) {
+ exception_object_sp->Dump(strm);
+ }
+
+ 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,
+ num_frames_with_source, stop_format);
+ }
+
+ return true;
+ }
+
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
// CommandObjectThreadReturn
//-------------------------------------------------------------------------
@@ -2059,6 +2166,9 @@
CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
LoadSubCommand("info",
CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
+ LoadSubCommand(
+ "exception",
+ CommandObjectSP(new CommandObjectThreadException(interpreter)));
LoadSubCommand("step-in",
CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
interpreter, "thread step-in",
Index: source/API/SBThread.cpp
===================================================================
--- source/API/SBThread.cpp
+++ source/API/SBThread.cpp
@@ -1466,6 +1466,20 @@
return LLDB_INVALID_INDEX32;
}
+SBThread SBThread::GetCurrentExceptionBacktrace() {
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (!thread_sp) return SBThread();
+
+ return SBThread(thread_sp->GetCurrentExceptionBacktrace());
+}
+
+SBValue SBThread::GetCurrentException() {
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (!thread_sp) return SBValue();
+
+ return SBValue(thread_sp->GetCurrentException());
+}
+
bool SBThread::SafeToCallFunctions() {
ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
if (thread_sp)
Index: include/lldb/Target/Thread.h
===================================================================
--- include/lldb/Target/Thread.h
+++ include/lldb/Target/Thread.h
@@ -1236,6 +1236,10 @@
//----------------------------------------------------------------------
virtual uint64_t GetExtendedBacktraceToken() { return LLDB_INVALID_ADDRESS; }
+ lldb::ThreadSP GetCurrentExceptionBacktrace();
+
+ lldb::ValueObjectSP GetCurrentException();
+
protected:
friend class ThreadPlan;
friend class ThreadList;
Index: include/lldb/Target/StackFrameRecognizer.h
===================================================================
--- include/lldb/Target/StackFrameRecognizer.h
+++ include/lldb/Target/StackFrameRecognizer.h
@@ -34,6 +34,9 @@
virtual lldb::ValueObjectListSP GetRecognizedArguments() {
return m_arguments;
}
+ virtual lldb::ValueObjectSP GetExceptionObject() {
+ return lldb::ValueObjectSP();
+ }
virtual ~RecognizedStackFrame(){};
protected:
@@ -101,7 +104,7 @@
class StackFrameRecognizerManager {
public:
static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
- ConstString &module, ConstString &symbol,
+ const ConstString &module, const ConstString &symbol,
bool first_instruction_only = true);
static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
Index: include/lldb/API/SBThread.h
===================================================================
--- include/lldb/API/SBThread.h
+++ include/lldb/API/SBThread.h
@@ -198,6 +198,10 @@
uint32_t GetExtendedBacktraceOriginatingIndexID();
+ SBThread GetCurrentExceptionBacktrace();
+
+ SBValue GetCurrentException();
+
bool SafeToCallFunctions();
#ifndef SWIG
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits