kubamracek created this revision.
kubamracek added reviewers: jasonmolenda, jingham.
Herald added a subscriber: mgorny.

This adds new APIs and commands to deal with exceptions (mostly Obj-C 
exceptions):

- SBThread and Thread get GetCurrentException API, which returns an 
SBValue/ValueObjectSP with the current exception for a thread. "Current" means 
an exception that is currently being thrown, caught or otherwise processed. In 
this patch, we only know about the exception when in objc_exception_throw, but 
subsequent patches will expand this.
- SBThread and Thread get GetCurrentExceptionBacktrace, which return an 
SBThread/ThreadSP containing a historical thread backtrace retrieved from the 
exception object. Currently unimplemented, subsequent patches will implement 
this.

To be able to extract the exception when inside objc_exception_throw, this 
patch introduces a concept of "frame recognizer" and "recognized frame". This 
should be an extensible mechanism that hardcodes knowledge about special frames 
(like objc_exception_throw) where we know the ABI, arguments or other special 
properties of that frame, even without source code. In this patch, we only 
handle objc_exception_throw frame.


https://reviews.llvm.org/D43886

Files:
  include/lldb/API/SBThread.h
  include/lldb/Target/FrameRecognizer.h
  include/lldb/Target/Platform.h
  include/lldb/Target/StackFrame.h
  include/lldb/Target/Thread.h
  lldb.xcodeproj/project.pbxproj
  packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
  source/API/SBThread.cpp
  source/Commands/CommandObjectThread.cpp
  source/Plugins/Platform/MacOSX/CMakeLists.txt
  source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.cpp
  source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.h
  source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  source/Plugins/Platform/MacOSX/PlatformDarwin.h
  source/Target/StackFrame.cpp
  source/Target/Thread.cpp

Index: source/Target/Thread.cpp
===================================================================
--- source/Target/Thread.cpp
+++ source/Target/Thread.cpp
@@ -2209,3 +2209,20 @@
   }
   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();
+
+  if (!recognized_frame->IsThrowingObjCException()) return ValueObjectSP();
+
+  return recognized_frame->GetObjCExceptionObject();
+}
+
+ThreadSP Thread::GetCurrentExceptionBacktrace() {
+  // TODO
+  return ThreadSP();
+}
Index: source/Target/StackFrame.cpp
===================================================================
--- source/Target/StackFrame.cpp
+++ source/Target/StackFrame.cpp
@@ -1918,3 +1918,14 @@
   }
   return true;
 }
+
+RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
+  if (!m_recognized_frame) {
+    lldb_private::FrameRecognizerSP recognizer_sp =
+        CalculateTarget()->GetPlatform()->GetFrameRecognizer();
+    if (recognizer_sp) {
+      m_recognized_frame = recognizer_sp->RecognizeFrame(CalculateStackFrame());
+    }
+  }
+  return m_recognized_frame;
+}
Index: source/Plugins/Platform/MacOSX/PlatformDarwin.h
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -85,6 +85,8 @@
   static std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef>
   ParseVersionBuildDir(llvm::StringRef str);
 
+  lldb_private::FrameRecognizerSP GetFrameRecognizer() override;
+
 protected:
   void ReadLibdispatchOffsetsAddress(lldb_private::Process *process);
 
@@ -137,6 +139,7 @@
 
   std::string m_developer_directory;
 
+  lldb_private::FrameRecognizerSP m_frame_recognizer;
 
 private:
   DISALLOW_COPY_AND_ASSIGN(PlatformDarwin);
Index: source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
===================================================================
--- source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -42,6 +42,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Threading.h"
+#include "Plugins/Platform/MacOSX/DarwinFrameRecognizer.h"
 
 #if defined(__APPLE__)
 #include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
@@ -1825,3 +1826,9 @@
   }
   return Status();
 }
+
+FrameRecognizerSP PlatformDarwin::GetFrameRecognizer() {
+  if (!m_frame_recognizer)
+    m_frame_recognizer.reset(new DarwinFrameRecognizer());
+  return m_frame_recognizer;
+}
Index: source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.h
===================================================================
--- /dev/null
+++ source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.h
@@ -0,0 +1,27 @@
+//===-- DarwinFrameRecognizer.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DarwinFrameRecognizer_h_
+#define liblldb_DarwinFrameRecognizer_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/FrameRecognizer.h"
+
+class DarwinFrameRecognizer
+    : public lldb_private::FrameRecognizer,
+      std::enable_shared_from_this<DarwinFrameRecognizer> {
+ public:
+  lldb_private::RecognizedStackFrameSP RecognizeFrame(
+      lldb::StackFrameSP frame) override;
+};
+
+#endif // liblldb_DarwinFrameRecognizer_h_
Index: source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Platform/MacOSX/DarwinFrameRecognizer.cpp
@@ -0,0 +1,79 @@
+//===-- DarwinFrameRecognizer.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DarwinFrameRecognizer.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class DarwinObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
+ public:
+  DarwinObjCExceptionRecognizedStackFrame(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();
+
+    lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr,
+                                                              *process_sp);
+    exception = ValueObject::CreateValueObjectFromData(
+        "exception", exception_isw.GetAsData(process_sp->GetByteOrder()),
+        *frame_sp, voidstar);
+    exception = exception->GetDynamicValue(eDynamicDontRunTarget);
+  }
+
+  ValueObjectSP exception;
+
+  bool IsThrowingObjCException() override { return true; }
+
+  lldb::ValueObjectSP GetObjCExceptionObject() override { return exception; }
+};
+
+RecognizedStackFrameSP DarwinFrameRecognizer::RecognizeFrame(
+    StackFrameSP frame) {
+  const SymbolContext &symctx =
+      frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction);
+  ConstString func = symctx.GetFunctionName();
+  ConstString mod = symctx.module_sp->GetFileSpec().GetFilename();
+
+  if (mod == ConstString("libobjc.A.dylib")) {
+    if (func == ConstString("objc_exception_throw")) {
+      return RecognizedStackFrameSP(
+          new DarwinObjCExceptionRecognizedStackFrame(frame));
+    }
+  }
+
+  return RecognizedStackFrameSP(new RecognizedStackFrame());
+}
Index: source/Plugins/Platform/MacOSX/CMakeLists.txt
===================================================================
--- source/Plugins/Platform/MacOSX/CMakeLists.txt
+++ source/Plugins/Platform/MacOSX/CMakeLists.txt
@@ -1,4 +1,5 @@
 list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
+  DarwinFrameRecognizer.cpp
   PlatformDarwin.cpp
   PlatformDarwinKernel.cpp
   PlatformMacOSX.cpp
Index: source/Commands/CommandObjectThread.cpp
===================================================================
--- source/Commands/CommandObjectThread.cpp
+++ source/Commands/CommandObjectThread.cpp
@@ -1511,6 +1511,113 @@
   CommandOptions m_options;
 };
 
+//-------------------------------------------------------------------------
+// CommandObjectThreadException
+//-------------------------------------------------------------------------
+
+static OptionDefinition g_thread_exception_options[] = {
+    // clang-format off
+  { LLDB_OPT_SET_1, false, "count",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,      "How many frames to display (-1 for all)" },
+  { LLDB_OPT_SET_1, false, "start",    's', OptionParser::eRequiredArgument, nullptr, 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
 //-------------------------------------------------------------------------
@@ -2054,6 +2161,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
@@ -1416,6 +1416,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: packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
===================================================================
--- packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
+++ packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
@@ -30,12 +30,20 @@
 
         lldbutil.run_break_set_by_file_and_line(
             self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
+        lldbutil.run_break_set_by_symbol(self, "objc_exception_throw")
 
         self.runCmd("run", RUN_SUCCEEDED)
 
         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                     substrs=['stopped', 'stop reason = breakpoint'])
 
+        self.expect('thread exception', substrs=[
+                '(NSException *) exception = ',
+                'name: "ThrownException" - reason: "SomeReason"',
+            ])
+
+        self.runCmd("continue")
+
         self.expect(
             'frame variable e1',
             substrs=[
Index: lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -784,6 +784,7 @@
 		8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */; };
 		9404957A1BEC497E00926025 /* NSError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495781BEC497E00926025 /* NSError.cpp */; };
 		9404957B1BEC497E00926025 /* NSException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495791BEC497E00926025 /* NSException.cpp */; };
+		8CFDB678204677DA0052B399 /* DarwinFrameRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CFDB676204677D10052B399 /* DarwinFrameRecognizer.cpp */; };
 		94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };
 		940B02F619DC96E700AD0F52 /* SBExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */; };
 		940B04D91A8984FF0045D5F7 /* argdumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940B04D81A8984FF0045D5F7 /* argdumper.cpp */; };
@@ -2695,6 +2696,9 @@
 		8CF02AE619DCBF8400B14BE0 /* ASanRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASanRuntime.h; sourceTree = "<group>"; };
 		8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntimeStopInfo.cpp; path = source/Target/InstrumentationRuntimeStopInfo.cpp; sourceTree = "<group>"; };
 		8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntimeStopInfo.h; path = include/lldb/Target/InstrumentationRuntimeStopInfo.h; sourceTree = "<group>"; };
+		8CFDB676204677D10052B399 /* DarwinFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DarwinFrameRecognizer.cpp; sourceTree = "<group>"; };
+		8CFDB677204677D10052B399 /* DarwinFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinFrameRecognizer.h; sourceTree = "<group>"; };
+		8CFDB67920467B390052B399 /* FrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FrameRecognizer.h; path = include/lldb/Target/FrameRecognizer.h; sourceTree = "<group>"; };
 		94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = "<group>"; };
 		94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = "<group>"; };
 		940495781BEC497E00926025 /* NSError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSError.cpp; path = Language/ObjC/NSError.cpp; sourceTree = "<group>"; };
@@ -5406,6 +5410,7 @@
 				26BC7DF210F1B81A00F91463 /* ExecutionContext.h */,
 				26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */,
 				26DAFD9711529BC7005A394E /* ExecutionContextScope.h */,
+				8CFDB67920467B390052B399 /* FrameRecognizer.h */,
 				26BC179B18C7F2CB00D2196D /* JITLoader.h */,
 				26BC179718C7F2B300D2196D /* JITLoader.cpp */,
 				26BC179C18C7F2CB00D2196D /* JITLoaderList.h */,
@@ -5604,6 +5609,8 @@
 				AF8AD6361BEC28C400150209 /* PlatformRemoteAppleWatch.h */,
 				2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */,
 				2675F6FF1332BE690067997B /* PlatformRemoteiOS.h */,
+				8CFDB676204677D10052B399 /* DarwinFrameRecognizer.cpp */,
+				8CFDB677204677D10052B399 /* DarwinFrameRecognizer.h */,
 			);
 			path = MacOSX;
 			sourceTree = "<group>";
@@ -7824,6 +7831,7 @@
 				2689010813353E6F00698AC0 /* ThreadPlanStepUntil.cpp in Sources */,
 				2689010A13353E6F00698AC0 /* ThreadPlanTracer.cpp in Sources */,
 				AF37E10A17C861F20061E18E /* ProcessRunLock.cpp in Sources */,
+				8CFDB678204677DA0052B399 /* DarwinFrameRecognizer.cpp in Sources */,
 				26474CAA18D0CB070073DEBA /* RegisterContextFreeBSD_mips64.cpp in Sources */,
 				94A5B3971AB9FE8D00A5EE7F /* EmulateInstructionMIPS64.cpp in Sources */,
 				256CBDC01ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp in Sources */,
Index: include/lldb/Target/Thread.h
===================================================================
--- include/lldb/Target/Thread.h
+++ include/lldb/Target/Thread.h
@@ -1249,6 +1249,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/StackFrame.h
===================================================================
--- include/lldb/Target/StackFrame.h
+++ include/lldb/Target/StackFrame.h
@@ -23,6 +23,7 @@
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/FrameRecognizer.h"
 #include "lldb/Target/StackID.h"
 #include "lldb/Utility/Status.h"
 #include "lldb/Utility/StreamString.h"
@@ -516,6 +517,8 @@
 
   void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
 
+  lldb_private::RecognizedStackFrameSP GetRecognizedFrame();
+
 protected:
   friend class StackFrameList;
 
@@ -553,6 +556,7 @@
   ValueObjectList m_variable_list_value_objects; // Value objects for each
                                                  // variable in
                                                  // m_variable_list_sp
+  RecognizedStackFrameSP m_recognized_frame;
   StreamString m_disassembly;
   std::recursive_mutex m_mutex;
 
Index: include/lldb/Target/Platform.h
===================================================================
--- include/lldb/Target/Platform.h
+++ include/lldb/Target/Platform.h
@@ -24,6 +24,7 @@
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Core/UserSettingsController.h"
 #include "lldb/Interpreter/Options.h"
+#include "lldb/Target/FrameRecognizer.h"
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/FileSpec.h"
@@ -872,6 +873,10 @@
   virtual size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
                                            lldb_private::Status &error);
 
+  virtual FrameRecognizerSP GetFrameRecognizer() {
+    return FrameRecognizerSP();
+  }
+
 protected:
   bool m_is_host;
   // Set to true when we are able to actually set the OS version while
Index: include/lldb/Target/FrameRecognizer.h
===================================================================
--- /dev/null
+++ include/lldb/Target/FrameRecognizer.h
@@ -0,0 +1,50 @@
+//===-- FrameRecognizer.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_FrameRecognizer_h_
+#define liblldb_FrameRecognizer_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-forward.h"
+#include "lldb/lldb-public.h"
+
+namespace lldb_private {
+
+class RecognizedStackFrame
+    : std::enable_shared_from_this<RecognizedStackFrame> {
+ public:
+  virtual bool IsThrowingObjCException() { return false; }
+
+  virtual lldb::ValueObjectSP GetObjCExceptionObject() {
+    return lldb::ValueObjectSP();
+  }
+
+  virtual ~RecognizedStackFrame(){};
+};
+
+typedef std::shared_ptr<RecognizedStackFrame> RecognizedStackFrameSP;
+
+class FrameRecognizer : std::enable_shared_from_this<FrameRecognizer> {
+ public:
+  virtual RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame) {
+    return RecognizedStackFrameSP(new RecognizedStackFrame());
+  };
+
+  virtual ~FrameRecognizer(){};
+};
+
+typedef std::shared_ptr<FrameRecognizer> FrameRecognizerSP;
+
+}  // namespace lldb_private
+
+#endif // liblldb_FrameRecognizer_h_
Index: include/lldb/API/SBThread.h
===================================================================
--- include/lldb/API/SBThread.h
+++ include/lldb/API/SBThread.h
@@ -184,6 +184,10 @@
 
   uint32_t GetExtendedBacktraceOriginatingIndexID();
 
+  SBThread GetCurrentExceptionBacktrace();
+
+  SBValue GetCurrentException();
+
   bool SafeToCallFunctions();
 
 #ifndef SWIG
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to