[Lldb-commits] [lldb] 47d3c5f - [lldb] Cortex-M exception unwind API test cleanup
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 9 19:10:55 PDT 2025
Author: Jason Molenda
Date: 2025-10-09T19:10:42-07:00
New Revision: 47d3c5f3cb159fd261ab5c3efa55afae246c5e0d
URL: https://github.com/llvm/llvm-project/commit/47d3c5f3cb159fd261ab5c3efa55afae246c5e0d
DIFF: https://github.com/llvm/llvm-project/commit/47d3c5f3cb159fd261ab5c3efa55afae246c5e0d.diff
LOG: [lldb] Cortex-M exception unwind API test cleanup
This test, with a corefile created via yaml2macho-core plus an
ObjectFileJSON binary with symbol addresses and ranges, was failing
on some machines/CI because the wrong ABI was being picked.
The bytes of the functions were not included in the yaml or .json
binary. The unwind falls back to using the ABI plugin default
unwind plans. We have two armv7 ABIs - the Darwin ABI that always
uses r7 as the frame pointer, and the AAPCS ABI which uses r11 code.
In reality, armv7 code uses r11 in arm mode, r7 in thumb code. But
the ABI ArchDefaultUnwindPlan doesn't have any access to the Target's
ArchSpec or Process register state, to determine the correct processor
state (arm or thumb). And in fact, on Cortex-M targets, the
instructions are always thumb, so the arch default unwind plan
(hardcoded r11) is always wrong.
The corefile doesn't specify a vendor/os, only a cpu.
The object file json specifies the armv7m-apple-* triple, which will
select the correct ABI plugin, and the test runs.
In some cases, it looks like the Process ABI was fetched after
opening the corefile, but before the binary.json was loaded and
corrected the Target's ArchSpec. And we never re-evaluate the ABI
once it is set, in a Process. When we picked the AAPCS armv7 ABI,
we would try to use r11 as frame pointer, and the unwind would stop
after one stack frame.
I'm stepping around this problem by (1) adding the register bytes of
the prologues of every test function in the backtrace, and (2)
shortening the function ranges (in binary.json) to specify that the
functions are all just long enough for the prologue where execution
is stopped. The instruction emulation plugin will fail if it can't
get all of the bytes from the function instructions, so I hacked
the function sizes in the .json to cover the prologue plus one and
changed the addresses in the backtrace to fit within those ranges.
[ updated this commit to keep the @skipIfRemote on the API test
because two remote CI bots are failing for reasons I don't quite
see. ]
Added:
Modified:
lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py
lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml
lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json
Removed:
################################################################################
diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py
index 768dd6fe6867c..ebba4d1fbcb05 100644
--- a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py
+++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py
@@ -12,20 +12,6 @@
class TestCortexMExceptionUnwind(TestBase):
NO_DEBUG_INFO_TESTCASE = True
- # on the lldb-remote-linux-ubuntu CI, the binary.json's triple of
- # armv7m-apple is not being set in the Target triple, and we're
- # picking the wrong ABI plugin, ABISysV_arm.
- # ABISysV_arm::CreateDefaultUnwindPlan() doesn't have a way to detect
- # arm/thumb for a stack frame, or even the Target's triple for a
- # Cortex-M part that is always thumb. It hardcodes r11 as the frame
- # pointer register, which is correct for arm code but not thumb.
- # It is never correct # on a Cortex-M target.
- # The Darwin ABIMacOSX_arm diverges from AAPCS and always uses r7 for
- # the frame pointer -- the thumb convention -- whether executing arm or
- # thumb. So its CreateDefaultUnwindPlan picks the correct register for
- # the frame pointer, and we can walk the stack.
- # ABISysV_arm::CreateDefaultUnwindPlan will only get one frame and
- # not be able to continue.
@skipIfRemote
def test_no_fpu(self):
"""Test that we can backtrace correctly through an ARM Cortex-M Exception return stack"""
@@ -59,9 +45,8 @@ def test_no_fpu(self):
# frames above that. The topmost two stack frames
# were not interesting for this test, so I didn't
# create symbols for them.
- self.assertEqual(thread.GetNumFrames(), 6)
+ self.assertEqual(thread.GetNumFrames(), 3)
stackframe_names = [
- "exception_catcher",
"exception_catcher",
"exception_thrower",
"main",
diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml b/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml
index 9ce5ff49d9b6e..0b4e1f8fac3e2 100644
--- a/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml
+++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml
@@ -2,8 +2,8 @@ cpu: armv7m
threads:
- regsets:
- flavor: gpr
- registers: [{name: sp, value: 0x2000fe70}, {name: r7, value: 0x2000fe80},
- {name: pc, value: 0x0020392c}, {name: lr, value: 0x0020392d}]
+ registers: [{name: sp, value: 0x2000fe88}, {name: r7, value: 0x2000fe88},
+ {name: pc, value: 0x00203916}, {name: lr, value: 0x0020392d}]
memory-regions:
# stack memory fetched via
# (lldb) p/x $sp
@@ -14,7 +14,7 @@ memory-regions:
0x0000002a, 0x20010e58, 0x00203923, 0x00000001,
0x2000fe88, 0x00203911, 0x2000ffdc, 0xfffffff9,
0x00000102, 0x00000002, 0x000003f0, 0x0000002a,
- 0x20012620, 0x00203215, 0x00203366, 0x81000200,
+ 0x20012620, 0x00203215, 0x00202a92, 0x81000200,
0x00203215, 0x200128b0, 0x0024928d, 0x2000fecc,
0x002491ed, 0x20010e58, 0x20010e4c, 0x2000ffa0,
0x200107a0, 0x0000003c, 0x200116e8, 0x200108b0,
@@ -62,3 +62,26 @@ memory-regions:
0x98, 0xae, 0x28, 0x00
]
+ # exception_thrower
+ # (lldb) disass -b -c 12 -n exception_thrower
+ # 0x202a88 <+0>: 0xb5f0 push {r4, r5, r6, r7, lr}
+ # 0x202a8a <+2>: 0xaf03 add r7, sp, #0xc
+ # 0x202a8c <+4>: 0xe92d0f00 push.w {r8, r9, r10, r11}
+ # 0x202a90 <+8>: 0xb0c3 sub sp, #0x10c
+ # 0x202a92 <+10>: 0xf7ffffd9 bl 0x202a48
+ - addr: 0x202a88
+ UInt8: [
+ 0xf0, 0xb5, 0x03, 0xaf, 0x2d, 0xe9, 0x00, 0x0f,
+ 0xc3, 0xb0, 0xff, 0xf7, 0xd9, 0xff, 0xff, 0xf7
+ ]
+
+ # main:
+ # 0x202a7e <+0>: push {r7, lr}
+ # 0x202a80 <+2>: mov r7, sp
+ # 0x202a82 <+4>: bl 0x202a88 ; exception_thrower
+ # 0x202a86 <+8>: nop
+ - addr: 0x202a7e
+ UInt8: [
+ 0x80, 0xb5, 0x6f, 0x46, 0x00, 0xf0, 0x01, 0xf8,
+ 0x00, 0xbf
+ ]
diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json b/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json
index 8fcd5307ff82a..0de0169f7adb1 100644
--- a/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json
+++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json
@@ -1,5 +1,5 @@
{
- "triple": "armv7m-apple",
+ "triple": "armv7m--",
"uuid": "2D157DBA-53C9-3AC7-B5A1-9D336EC831CB",
"type": "executable",
"sections": [
@@ -28,13 +28,13 @@
{
"name": "exception_catcher",
"type": "code",
- "size": 44,
+ "size": 32,
"address": 2111760
},
{
"name": "exception_thrower",
"type": "code",
- "size": 2652,
+ "size": 16,
"address": 2108040
}
]
More information about the lldb-commits
mailing list