[Lldb-commits] [lldb] edc7735 - [lldb/crashlog] Improve exception reporting for interactive mode

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 11 22:29:18 PDT 2022


Author: Med Ismail Bennani
Date: 2022-08-11T22:29:06-07:00
New Revision: edc77353daa707712fc92a31edb5b27ad103ba30

URL: https://github.com/llvm/llvm-project/commit/edc77353daa707712fc92a31edb5b27ad103ba30
DIFF: https://github.com/llvm/llvm-project/commit/edc77353daa707712fc92a31edb5b27ad103ba30.diff

LOG: [lldb/crashlog] Improve exception reporting for interactive mode

This patch improve exception reporting when loading a crash report in a
scripted process. Now, we parse the `exception` dictionary from the
crash report use it the create a higher fidelity `MachException` stop info.

This patch also updates the test to reflect that change.

rdar://97096486

Differential Revision: https://reviews.llvm.org/D131086

Signed-off-by: Med Ismail Bennani <medismail.bennani at gmail.com>

Added: 
    

Modified: 
    lldb/examples/python/scripted_process/crashlog_scripted_process.py
    lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
    lldb/source/Plugins/Process/Utility/StopInfoMachException.h
    lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test
    lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test

Removed: 
    


################################################################################
diff  --git a/lldb/examples/python/scripted_process/crashlog_scripted_process.py b/lldb/examples/python/scripted_process/crashlog_scripted_process.py
index ffdd43d7c5d8a..e64b9b7822af1 100644
--- a/lldb/examples/python/scripted_process/crashlog_scripted_process.py
+++ b/lldb/examples/python/scripted_process/crashlog_scripted_process.py
@@ -17,6 +17,7 @@ def parse_crashlog(self):
         self.addr_mask = crash_log.addr_mask
         self.crashed_thread_idx = crash_log.crashed_thread_idx
         self.loaded_images = []
+        self.exception = crash_log.exception
 
         def load_images(self, images):
             #TODO: Add to self.loaded_images and load images in lldb
@@ -69,6 +70,7 @@ def __init__(self, target: lldb.SBTarget, args : lldb.SBStructuredData):
 
         self.pid = super().get_process_id()
         self.crashed_thread_idx = 0
+        self.exception = None
         self.parse_crashlog()
 
     def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo:
@@ -154,9 +156,12 @@ def get_state(self):
 
     def get_stop_reason(self) -> Dict[str, Any]:
         if not self.has_crashed:
-            return { "type": lldb.eStopReasonNone, "data": {  }}
+            return { "type": lldb.eStopReasonNone }
         # TODO: Investigate what stop reason should be reported when crashed
-        return { "type": lldb.eStopReasonException, "data": { "desc": "EXC_BAD_ACCESS" }}
+        stop_reason = { "type": lldb.eStopReasonException, "data": {  }}
+        if self.scripted_process.exception:
+            stop_reason['data']['mach_exception'] = self.scripted_process.exception
+        return stop_reason
 
     def get_register_context(self) -> str:
         if not self.register_ctx:

diff  --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 4623a50537eb6..04614ea3f6625 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -522,6 +522,78 @@ static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target,
   return nullptr;
 }
 
+#if defined(__APPLE__)
+const char *
+StopInfoMachException::MachException::Name(exception_type_t exc_type) {
+  switch (exc_type) {
+  case EXC_BAD_ACCESS:
+    return "EXC_BAD_ACCESS";
+  case EXC_BAD_INSTRUCTION:
+    return "EXC_BAD_INSTRUCTION";
+  case EXC_ARITHMETIC:
+    return "EXC_ARITHMETIC";
+  case EXC_EMULATION:
+    return "EXC_EMULATION";
+  case EXC_SOFTWARE:
+    return "EXC_SOFTWARE";
+  case EXC_BREAKPOINT:
+    return "EXC_BREAKPOINT";
+  case EXC_SYSCALL:
+    return "EXC_SYSCALL";
+  case EXC_MACH_SYSCALL:
+    return "EXC_MACH_SYSCALL";
+  case EXC_RPC_ALERT:
+    return "EXC_RPC_ALERT";
+#ifdef EXC_CRASH
+  case EXC_CRASH:
+    return "EXC_CRASH";
+#endif
+  case EXC_RESOURCE:
+    return "EXC_RESOURCE";
+#ifdef EXC_GUARD
+  case EXC_GUARD:
+    return "EXC_GUARD";
+#endif
+#ifdef EXC_CORPSE_NOTIFY
+  case EXC_CORPSE_NOTIFY:
+    return "EXC_CORPSE_NOTIFY";
+#endif
+#ifdef EXC_CORPSE_VARIANT_BIT
+  case EXC_CORPSE_VARIANT_BIT:
+    return "EXC_CORPSE_VARIANT_BIT";
+#endif
+  default:
+    break;
+  }
+  return NULL;
+}
+
+llvm::Optional<exception_type_t>
+StopInfoMachException::MachException::ExceptionCode(const char *name) {
+  return llvm::StringSwitch<llvm::Optional<exception_type_t>>(name)
+      .Case("EXC_BAD_ACCESS", EXC_BAD_ACCESS)
+      .Case("EXC_BAD_INSTRUCTION", EXC_BAD_INSTRUCTION)
+      .Case("EXC_ARITHMETIC", EXC_ARITHMETIC)
+      .Case("EXC_EMULATION", EXC_EMULATION)
+      .Case("EXC_SOFTWARE", EXC_SOFTWARE)
+      .Case("EXC_BREAKPOINT", EXC_BREAKPOINT)
+      .Case("EXC_SYSCALL", EXC_SYSCALL)
+      .Case("EXC_MACH_SYSCALL", EXC_MACH_SYSCALL)
+      .Case("EXC_RPC_ALERT", EXC_RPC_ALERT)
+#ifdef EXC_CRASH
+      .Case("EXC_CRASH", EXC_CRASH)
+#endif
+      .Case("EXC_RESOURCE", EXC_RESOURCE)
+#ifdef EXC_GUARD
+      .Case("EXC_GUARD", EXC_GUARD)
+#endif
+#ifdef EXC_CORPSE_NOTIFY
+      .Case("EXC_CORPSE_NOTIFY", EXC_CORPSE_NOTIFY)
+#endif
+      .Default(llvm::None);
+}
+#endif
+
 StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
     Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
     uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,

diff  --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
index 6467745a7bf21..da4569f359fc1 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -13,6 +13,11 @@
 
 #include "lldb/Target/StopInfo.h"
 
+#if defined(__APPLE__)
+// Needed for the EXC_* defines
+#include <mach/exception.h>
+#endif
+
 namespace lldb_private {
 
 class StopInfoMachException : public StopInfo {
@@ -37,6 +42,13 @@ class StopInfoMachException : public StopInfo {
 
   const char *GetDescription() override;
 
+#if defined(__APPLE__)
+  struct MachException {
+    static const char *Name(exception_type_t exc_type);
+    static llvm::Optional<exception_type_t> ExceptionCode(const char *name);
+  };
+#endif
+
   // Since some mach exceptions will be reported as breakpoints, signals,
   // or trace, we use this static accessor which will translate the mach
   // exception into the correct StopInfo.

diff  --git a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
index e28f66015dd59..5c49caedcfcc6 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp
@@ -9,6 +9,7 @@
 #include "ScriptedThread.h"
 
 #include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
 #include "lldb/Target/OperatingSystem.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/RegisterContext.h"
@@ -259,11 +260,46 @@ bool ScriptedThread::CalculateStopInfo() {
         StopInfo::CreateStopReasonWithSignal(*this, signal, description.data());
   } break;
   case lldb::eStopReasonException: {
-    llvm::StringRef description;
-    data_dict->GetValueForKeyAsString("desc", description);
-
+#if defined(__APPLE__)
+    StructuredData::Dictionary *mach_exception;
+    if (data_dict->GetValueForKeyAsDictionary("mach_exception",
+                                              mach_exception)) {
+      llvm::StringRef value;
+      mach_exception->GetValueForKeyAsString("type", value);
+      auto exc_type =
+          StopInfoMachException::MachException::ExceptionCode(value.data());
+
+      if (!exc_type)
+        return false;
+
+      uint32_t exc_data_size = 0;
+      llvm::SmallVector<uint64_t, 3> raw_codes;
+
+      StructuredData::Array *exc_rawcodes;
+      mach_exception->GetValueForKeyAsArray("rawCodes", exc_rawcodes);
+      if (exc_rawcodes) {
+        auto fetch_data = [&raw_codes](StructuredData::Object *obj) {
+          if (!obj)
+            return false;
+          raw_codes.push_back(obj->GetIntegerValue());
+          return true;
+        };
+
+        exc_rawcodes->ForEach(fetch_data);
+        exc_data_size = raw_codes.size();
+      }
+
+      stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException(
+          *this, *exc_type, exc_data_size,
+          exc_data_size >= 1 ? raw_codes[0] : 0,
+          exc_data_size >= 2 ? raw_codes[1] : 0,
+          exc_data_size >= 3 ? raw_codes[2] : 0);
+
+      break;
+    }
+#endif
     stop_info_sp =
-        StopInfo::CreateStopReasonWithException(*this, description.data());
+        StopInfo::CreateStopReasonWithException(*this, "EXC_BAD_ACCESS");
   } break;
   default:
     return ScriptedInterface::ErrorWithMessage<bool>(

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test
index 3faff2cec20f7..fccd71ce31f73 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/scripted_crashlog_json.test
@@ -10,11 +10,11 @@
 
 # CHECK: (lldb) process status
 # CHECK-NEXT: Process 22511 stopped
-# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:     frame #0: 0x0000000100ec58f4 multithread-test`bar
 
 # CHECK: (lldb) thread backtrace
-# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:   * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
 # CHECK-NEXT:     frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
 # CHECK-NEXT:     frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]
@@ -23,7 +23,7 @@
 # CHECK-NEXT: Process 22511 stopped
 # CHECK-NEXT:   thread #1: tid = 0x23c7fe, 0x000000019cc40b84{{.*}}, queue = 'com.apple.main-thread'
 # CHECK-NEXT:   thread #2: tid = 0x23c800, 0x000000019cc42c9c{{.*}}
-# CHECK-NEXT: * thread #3: tid = 0x23c801, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT: * thread #3: tid = 0x23c801, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 
 # CHECK: (lldb) bt all
 # CHECK:  thread #1, queue = 'com.apple.main-thread'
@@ -35,7 +35,7 @@
 # CHECK:    frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial]
 # CHECK:    frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial]
 # CHECK:    frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial]
-# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:  * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
 # CHECK-NEXT:    frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
 # CHECK-NEXT:    frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]

diff  --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
index 7e57b07bb1cfe..b120b9663a27c 100644
--- a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/skipped_status_interactive_crashlog.test
@@ -10,11 +10,11 @@
 
 process status
 # CHECK: Process 22511 stopped
-# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:     frame #0: 0x0000000100ec58f4 multithread-test`bar
 
 thread backtrace
-# CHECK: * thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK: * thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:   * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
 # CHECK-NEXT:     frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
 # CHECK-NEXT:     frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]
@@ -23,7 +23,7 @@ thread list
 # CHECK: Process 22511 stopped
 # CHECK-NEXT:   thread #1: tid = 0x23c7fe, 0x000000019cc40b84{{.*}}, queue = 'com.apple.main-thread'
 # CHECK-NEXT:   thread #2: tid = 0x23c800, 0x000000019cc42c9c{{.*}}
-# CHECK-NEXT: * thread #3: tid = 0x23c801, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT: * thread #3: tid = 0x23c801, 0x0000000100ec58f4 multithread-test`bar{{.*}}, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 
 bt all
 # CHECK:  thread #1, queue = 'com.apple.main-thread'
@@ -35,7 +35,7 @@ bt all
 # CHECK:    frame #{{[0-9]+}}: 0x0000000100ec5957 multithread-test`call_and_wait{{.*}} [artificial]
 # CHECK:    frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial]
 # CHECK:    frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial]
-# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS
+# CHECK-NEXT:* thread #3, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
 # CHECK-NEXT:  * frame #0: 0x0000000100ec58f4 multithread-test`bar{{.*}} [artificial]
 # CHECK-NEXT:    frame #1: 0x0000000100ec591b multithread-test`foo{{.*}} [artificial]
 # CHECK-NEXT:    frame #2: 0x0000000100ec5a87 multithread-test`compute_pow{{.*}} [artificial]


        


More information about the lldb-commits mailing list