[Lldb-commits] [lldb] [lldb/crashlog] Make registers always available & fix x29/x30 parsing (PR #145104)

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Fri Jun 20 14:46:04 PDT 2025


https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/145104

>From c83fa6be0c41102d4c0df424574b215d4f83f5f2 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Fri, 20 Jun 2025 14:45:11 -0700
Subject: [PATCH 1/2] [lldb/crashlog] Fix register parsing for arm64 using
 alternative name

This patch addresses some register parsing issue where certain registers
would not be prefixed by 'x' but rather they where listed using their
alternate name (fp instead of x29, lr instead of x30, etc.)

rdar://149482608

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 .../python/crashlog_scripted_process.py       |  7 ++
 .../interactive_crashlog_arm64_register.test  | 80 +++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test

diff --git a/lldb/examples/python/crashlog_scripted_process.py b/lldb/examples/python/crashlog_scripted_process.py
index be0ed49d35904..229691c78a215 100644
--- a/lldb/examples/python/crashlog_scripted_process.py
+++ b/lldb/examples/python/crashlog_scripted_process.py
@@ -135,8 +135,15 @@ def create_register_ctx(self):
 
         for reg in self.register_info["registers"]:
             reg_name = reg["name"]
+            reg_alt_name = None
+            if "alt-name" in reg:
+                reg_alt_name = reg["alt-name"]
             if reg_name in self.backing_thread.registers:
                 self.register_ctx[reg_name] = self.backing_thread.registers[reg_name]
+            elif reg_alt_name and reg_alt_name in self.backing_thread.registers:
+                self.register_ctx[reg_name] = self.backing_thread.registers[
+                    reg_alt_name
+                ]
             else:
                 self.register_ctx[reg_name] = 0
 
diff --git a/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test
new file mode 100644
index 0000000000000..3f572c3300c0f
--- /dev/null
+++ b/lldb/test/Shell/ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test
@@ -0,0 +1,80 @@
+# REQUIRES: python, native && system-darwin
+
+# RUN: mkdir -p %t.dir
+# RUN: yaml2obj %S/Inputs/interactive_crashlog/multithread-test.yaml > %t.dir/multithread-test
+# RUN: %lldb -o 'command script import lldb.macosx.crashlog' \
+# RUN: -o 'crashlog -a -t %t.dir/multithread-test %S/Inputs/interactive_crashlog/multithread-test.ips' \
+# RUN: -o "thread list" -o "bt all" -o "register read" 2>&1 | FileCheck %s
+
+# CHECK: "crashlog" {{.*}} commands have been installed, use the "--help" options on these commands
+
+# CHECK: (lldb) process status
+# CHECK-NEXT: Process 22511 stopped
+# 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 (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]
+
+# CHECK: (lldb) thread list
+# 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 (code=1, address=0x0)
+
+# CHECK: (lldb) bt all
+# CHECK:  thread #1, queue = 'com.apple.main-thread'
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc40b84{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x0000000100ec5b3b multithread-test`main{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x00000002230f8da7{{.*}} [artificial]
+# CHECK-NEXT:  thread #2
+# CHECK-NEXT:    frame #0: 0x000000019cc42c9c{{.*}} [artificial]
+# 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 (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]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc7e06b{{.*}} [artificial]
+# CHECK:    frame #{{[0-9]+}}: 0x000000019cc78e2b{{.*}} [artificial]
+
+# CHECK: (lldb) register read
+# CHECK: General Purpose Registers:
+# CHECK:         x0 = 0x000000000000002a
+# CHECK:         x1 = 0x0000600001d291b0
+# CHECK:         x2 = 0x000000019cbbf000
+# CHECK:         x3 = 0x0000000000000000
+# CHECK:         x4 = 0x00000000000030a0
+# CHECK:         x5 = 0x00000000190008ff
+# CHECK:         x6 = 0x0000000000000000
+# CHECK:         x7 = 0x0000000000000000
+# CHECK:         x8 = 0x0000000000000001
+# CHECK:         x9 = 0x0000000000000000
+# CHECK:        x10 = 0xfffffffe634277cf
+# CHECK:        x11 = 0x0000010000000102
+# CHECK:        x12 = 0x0000010000000102
+# CHECK:        x13 = 0x0000010000000100
+# CHECK:        x14 = 0x0000010000000000
+# CHECK:        x15 = 0x0000000000000001
+# CHECK:        x16 = 0x000000019cc78ea8
+# CHECK:        x17 = 0x00000001fd0a7698
+# CHECK:        x18 = 0x0000000000000000
+# CHECK:        x19 = 0x000000016f04f000
+# CHECK:        x20 = 0x0000000000000000
+# CHECK:        x21 = 0x0000000000000000
+# CHECK:        x22 = 0x0000000000000000
+# CHECK:        x23 = 0x0000000000000000
+# CHECK:        x24 = 0x0000000000000000
+# CHECK:        x25 = 0x0000000000000000
+# CHECK:        x26 = 0x0000000000000000
+# CHECK:        x27 = 0x0000000000000000
+# CHECK:        x28 = 0x0000000000000000
+# CHECK:        x29 = 0x000000016f04ef00
+# CHECK:        x30 = 0x0000000100ec591c
+# CHECK:         sp = 0x000000016f04eee0
+# CHECK:         pc = 0x0000000100ec58f4
+# CHECK:       cpsr = 0x80001000

>From fdbeca51ae0b017fe88ec49e67c466d55a001f2e Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Fri, 20 Jun 2025 13:48:07 -0700
Subject: [PATCH 2/2] [lldb/crashlog] Always load register context for
 non-crashed threads

This patch change the current crashlog behavior to always load the
register context, even for the non-crashed threads.

This is cheap to compute since it doesn't requires any module loading
and can be helful to investigate some crashes.

rdar://149481943

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 lldb/examples/python/crashlog.py                  | 8 ++++----
 lldb/examples/python/crashlog_scripted_process.py | 5 -----
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/lldb/examples/python/crashlog.py b/lldb/examples/python/crashlog.py
index 5f07cda2892ab..bb20f3a25c1c1 100755
--- a/lldb/examples/python/crashlog.py
+++ b/lldb/examples/python/crashlog.py
@@ -777,10 +777,10 @@ def parse_threads(self, json_threads):
             if json_thread.get("triggered", False):
                 self.crashlog.crashed_thread_idx = idx
                 thread.crashed = True
-                if "threadState" in json_thread:
-                    thread.registers = self.parse_thread_registers(
-                        json_thread["threadState"]
-                    )
+            if "threadState" in json_thread:
+                thread.registers = self.parse_thread_registers(
+                    json_thread["threadState"]
+                )
             if "queue" in json_thread:
                 thread.queue = json_thread.get("queue")
             self.parse_frames(thread, json_thread.get("frames", []))
diff --git a/lldb/examples/python/crashlog_scripted_process.py b/lldb/examples/python/crashlog_scripted_process.py
index 229691c78a215..f54a8df0479e7 100644
--- a/lldb/examples/python/crashlog_scripted_process.py
+++ b/lldb/examples/python/crashlog_scripted_process.py
@@ -123,11 +123,6 @@ def get_process_metadata(self):
 
 class CrashLogScriptedThread(ScriptedThread):
     def create_register_ctx(self):
-        if not self.has_crashed:
-            return dict.fromkeys(
-                [*map(lambda reg: reg["name"], self.register_info["registers"])], 0
-            )
-
         if not self.backing_thread or not len(self.backing_thread.registers):
             return dict.fromkeys(
                 [*map(lambda reg: reg["name"], self.register_info["registers"])], 0



More information about the lldb-commits mailing list