[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