[Lldb-commits] [lldb] [lldb] Provide lr value in faulting frame on arm64 (PR #138805)
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Fri May 9 19:29:17 PDT 2025
https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/138805
>From 4fc9acd03a58a3617b113352c48e5dd2fdb58eda Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Tue, 6 May 2025 22:37:17 -0700
Subject: [PATCH 01/17] [lldb] Provide lr value in faulting frame on arm64
When a frameless function faults or is interrupted asynchronously,
the UnwindPlan MAY have no register location rule for the return
address register (lr on arm64); the value is simply live in the
lr register when it was interrupted, and the frame below this on
the stack -- e.g. sigtramp on a Unix system -- has the full
register context, including that register.
RegisterContextUnwind::SavedLocationForRegister, when asked to find
the caller's pc value, will first see if there is a pc register
location. If there isn't, on a Return Address Register architecture
like arm/mips/riscv, we rewrite the register request from "pc" to
"RA register", and search for a location.
On frame 0 (the live frame) and an interrupted frame, the UnwindPlan
may have no register location rule for the RA Reg, that is valid.
A frameless function that never calls another may simply keep the
return address in the live register the whole way. Our instruction
emulation unwind plans explicitly add a rule (see Pavel's May 2024
change https://github.com/llvm/llvm-project/pull/91321 ), but an
UnwindPlan sourced from debug_frame may not.
I've got a case where this exactly happens - clang debug_frame for
arm64 where there is no register location for the lr in a frameless
function. There is a fault in the middle of this frameless function
and we only get the lr value from the fault handler below this frame
if lr has a register location of `IsSame`, in line with Pavel's
2024 change.
Similar to how we see a request of the RA Reg from frame 0 after
failing to find an unwind location for the pc register, the same
style of special casing is needed when this is a function that
was interrupted.
Without this change, we can find the pc of the frame that was
executing when it was interrupted, but we need $lr to find its
caller, and we don't descend down to the trap handler to get that
value, truncating the stack.
rdar://145614545
---
lldb/source/Target/RegisterContextUnwind.cpp | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 3ed49e12476dd..23a86bee2518b 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -1377,6 +1377,7 @@ RegisterContextUnwind::SavedLocationForRegister(
}
}
+ // Check if the active_row has a register location listed.
if (regnum.IsValid() &&
active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
unwindplan_regloc)) {
@@ -1390,11 +1391,10 @@ RegisterContextUnwind::SavedLocationForRegister(
// This is frame 0 and we're retrieving the PC and it's saved in a Return
// Address register and it hasn't been saved anywhere yet -- that is,
// it's still live in the actual register. Handle this specially.
-
if (!have_unwindplan_regloc && return_address_reg.IsValid() &&
- IsFrameZero()) {
- if (return_address_reg.GetAsKind(eRegisterKindLLDB) !=
- LLDB_INVALID_REGNUM) {
+ return_address_reg.GetAsKind(eRegisterKindLLDB) !=
+ LLDB_INVALID_REGNUM) {
+ if (IsFrameZero()) {
lldb_private::UnwindLLDB::ConcreteRegisterLocation new_regloc;
new_regloc.type = UnwindLLDB::ConcreteRegisterLocation::
eRegisterInLiveRegisterContext;
@@ -1408,6 +1408,17 @@ RegisterContextUnwind::SavedLocationForRegister(
return_address_reg.GetAsKind(eRegisterKindLLDB),
return_address_reg.GetAsKind(eRegisterKindLLDB));
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ } else if (BehavesLikeZerothFrame()) {
+ // This function was interrupted asynchronously -- it faulted,
+ // an async interrupt, a timer fired, a debugger expression etc.
+ // The caller's pc is in the Return Address register, but the
+ // UnwindPlan for this function may have no location rule for
+ // the RA reg.
+ // This means that the caller's return address is in the RA reg
+ // when the function was interrupted--descend down one stack frame
+ // to retrieve it from the trap handler's saved context.
+ unwindplan_regloc.SetSame();
+ have_unwindplan_regloc = true;
}
}
>From b10162deb49ecddca6439665c2b8ea1995fdd81f Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Wed, 7 May 2025 23:24:17 -0700
Subject: [PATCH 02/17] Add the sources for an API test case to be written
---
.../interrupt-and-trap-funcs.s | 92 +++++++++++++++++++
.../macosx/unwind-frameless-faulted/main.c | 6 ++
2 files changed, 98 insertions(+)
create mode 100644 lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
create mode 100644 lldb/test/API/macosx/unwind-frameless-faulted/main.c
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
new file mode 100644
index 0000000000000..23eb35c2b31ca
--- /dev/null
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -0,0 +1,92 @@
+#define DW_CFA_register 0x9
+#define ehframe_x22 22
+#define ehframe_x23 23
+#define ehframe_pc 32
+
+ .section __TEXT,__text,regular,pure_instructions
+
+//--------------------------------------
+// to_be_interrupted() a frameless function that does a non-ABI
+// function call ("is interrupted/traps" simulated) to trap().
+// Before it branches to trap(), it puts its return address in
+// x23. trap() knows to branch back to $x23 when it has finished.
+//--------------------------------------
+ .globl _to_be_interrupted
+ .p2align 2
+_to_be_interrupted:
+ .cfi_startproc
+
+ // This is a garbage entry to ensure that eh_frame is emitted,
+ // it isn't used for anything. If there's no eh_frame, lldb
+ // can do an assembly emulation scan and add a rule for $lr
+ // which won't expose the issue at hand.
+ .cfi_escape DW_CFA_register, ehframe_x22, ehframe_x23
+ mov x24, x0
+ add x24, x24, #1
+
+ adrp x23, L_.return at PAGE ; put return address in x4
+ add x23, x23, L_.return at PAGEOFF
+
+ b _trap ; branch to trap handler, fake async interrupt
+
+L_.return:
+ mov x0, x24
+ ret
+ .cfi_endproc
+
+
+
+//--------------------------------------
+// trap() trap handler function, sets up stack frame
+// with special unwind rule for the pc value of the
+// "interrupted" stack frame (it's in x23), then calls
+// break_to_debugger().
+//--------------------------------------
+ .globl _trap
+ .p2align 2
+_trap:
+ .cfi_startproc
+ .cfi_signal_frame
+
+ // The pc value when we were interrupted is in x23
+ .cfi_escape DW_CFA_register, ehframe_pc, ehframe_x23
+
+ // standard prologue save of fp & lr so we can call puts()
+ sub sp, sp, #32
+ stp x29, x30, [sp, #16]
+ add x29, sp, #16
+ .cfi_def_cfa w29, 16
+ .cfi_offset w30, -8
+ .cfi_offset w29, -16
+
+ bl _break_to_debugger
+
+ ldp x29, x30, [sp, #16]
+ add sp, sp, #32
+
+ // jump back to $x23 to resume execution of to_be_interrupted
+ br x23
+ .cfi_endproc
+
+//--------------------------------------
+// break_to_debugger() executes a BRK instruction
+//--------------------------------------
+ .globl _break_to_debugger
+ .p2align 2
+_break_to_debugger:
+ .cfi_startproc
+
+ // standard prologue save of fp & lr so we can call puts()
+ sub sp, sp, #32
+ stp x29, x30, [sp, #16]
+ add x29, sp, #16
+ .cfi_def_cfa w29, 16
+ .cfi_offset w30, -8
+ .cfi_offset w29, -16
+
+ brk #0xf000 ;; __builtin_debugtrap aarch64 instruction
+
+ ldp x29, x30, [sp, #16]
+ add sp, sp, #32
+ ret
+ .cfi_endproc
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/main.c b/lldb/test/API/macosx/unwind-frameless-faulted/main.c
new file mode 100644
index 0000000000000..e121809f25478
--- /dev/null
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/main.c
@@ -0,0 +1,6 @@
+int to_be_interrupted(int);
+int main() {
+ int c = 10;
+ c = to_be_interrupted(c);
+ return c;
+}
>From 508b9cb404072263a6ed52a75b3b7aad5d949510 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Wed, 7 May 2025 23:24:58 -0700
Subject: [PATCH 03/17] Add a log msg when a frame is marked as a trap handler
via the UnwindPlan. And use the trap handler flag for zeroth frame so we can
properly unwind a frameless function that was interrupted while in the trap
handler function.
---
lldb/source/Target/RegisterContextUnwind.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 51c0f56e9bc1e..cf4b96c6eda9f 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -248,6 +248,7 @@ void RegisterContextUnwind::InitializeZerothFrame() {
active_row =
m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
+ PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
if (active_row && log) {
StreamString active_row_strm;
active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread,
@@ -1933,6 +1934,7 @@ void RegisterContextUnwind::PropagateTrapHandlerFlagFromUnwindPlan(
}
m_frame_type = eTrapHandlerFrame;
+ UnwindLogMsg("This frame is marked as a trap handler via its UnwindPlan");
if (m_current_offset_backed_up_one != m_current_offset) {
// We backed up the pc by 1 to compute the symbol context, but
>From d8843fe86c0eaaa1483bed0317f832b7630d8548 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Wed, 7 May 2025 23:28:40 -0700
Subject: [PATCH 04/17] Update assembly a bit.
---
.../interrupt-and-trap-funcs.s | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index 23eb35c2b31ca..708ad9ed56a1c 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -51,7 +51,8 @@ _trap:
// The pc value when we were interrupted is in x23
.cfi_escape DW_CFA_register, ehframe_pc, ehframe_x23
- // standard prologue save of fp & lr so we can call puts()
+ // standard prologue save of fp & lr so we can call
+ // break_to_debugger()
sub sp, sp, #32
stp x29, x30, [sp, #16]
add x29, sp, #16
@@ -76,17 +77,7 @@ _trap:
_break_to_debugger:
.cfi_startproc
- // standard prologue save of fp & lr so we can call puts()
- sub sp, sp, #32
- stp x29, x30, [sp, #16]
- add x29, sp, #16
- .cfi_def_cfa w29, 16
- .cfi_offset w30, -8
- .cfi_offset w29, -16
-
brk #0xf000 ;; __builtin_debugtrap aarch64 instruction
- ldp x29, x30, [sp, #16]
- add sp, sp, #32
ret
.cfi_endproc
>From 1d90aa48c92d9f8ef43c889223c0804ac1491d53 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 18:18:14 -0700
Subject: [PATCH 05/17] Add unwind rules for x0 (volatile) and x20
(non-voltile) to trap() and break_to_debugger() for fun, and add unwind
instructions for the epilogue of trap().
When stopped in `break_to_debugger`,
```
* frame #0: 0x00000001000003e8 a.out`break_to_debugger + 4
frame #1: 0x00000001000003d8 a.out`trap + 16
frame #2: 0x00000001000003c0 a.out`to_be_interrupted + 20
frame #3: 0x0000000100000398 a.out`main + 32
```
Normally we can't provide a volatile register (e.g. x0) up
the stack. And we can provide a non-volatile register (e.g. x20)
up the stack. I added an IsSame rule for trap() and break_to_debugger()
for x0, so it CAN be passed up the stack. And I added an Undefined
rule for x20 to trap() so it CAN'T be provided up the stack.
If a user selects `to_be_interrupted` and does `register read`,
they'll get x0 and they won't get x20. From `main`, they will not
get x0 or x20 (x0 because `to_be_interrupted` doesn't have an IsSame
rule).
---
.../interrupt-and-trap-funcs.s | 25 ++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index 708ad9ed56a1c..b50c4734f18f3 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -1,4 +1,6 @@
#define DW_CFA_register 0x9
+#define ehframe_x0 0
+#define ehframe_x20 20
#define ehframe_x22 22
#define ehframe_x23 23
#define ehframe_pc 32
@@ -7,9 +9,9 @@
//--------------------------------------
// to_be_interrupted() a frameless function that does a non-ABI
-// function call ("is interrupted/traps" simulated) to trap().
-// Before it branches to trap(), it puts its return address in
-// x23. trap() knows to branch back to $x23 when it has finished.
+// function call to trap(), simulating an async signal/interrup/exception/fault.
+// Before it branches to trap(), put the return address in x23.
+// trap() knows to branch back to $x23 when it has finished.
//--------------------------------------
.globl _to_be_interrupted
.p2align 2
@@ -51,6 +53,15 @@ _trap:
// The pc value when we were interrupted is in x23
.cfi_escape DW_CFA_register, ehframe_pc, ehframe_x23
+ // For fun, mark x0 as unmodified so the caller can
+ // retrieve the value if it wants.
+ .cfi_same_value ehframe_x0
+
+ // Mark x20 as undefined. This is a callee-preserved
+ // (non-volatile) register by the SysV AArch64 ABI, but
+ // it's be fun to see lldb not passing a value past this.
+ .cfi_undefined ehframe_x20
+
// standard prologue save of fp & lr so we can call
// break_to_debugger()
sub sp, sp, #32
@@ -63,7 +74,11 @@ _trap:
bl _break_to_debugger
ldp x29, x30, [sp, #16]
+ .cfi_same_value x29
+ .cfi_same_value x30
+ .cfi_def_cfa sp, 32
add sp, sp, #32
+ .cfi_same_value sp
// jump back to $x23 to resume execution of to_be_interrupted
br x23
@@ -77,6 +92,10 @@ _trap:
_break_to_debugger:
.cfi_startproc
+ // For fun, mark x0 as unmodified so the caller can
+ // retrieve the value if it wants.
+ .cfi_same_value ehframe_x0
+
brk #0xf000 ;; __builtin_debugtrap aarch64 instruction
ret
>From 303edd47f7bcfb6af0a9947ca7b0b9a0c5bec589 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 18:46:14 -0700
Subject: [PATCH 06/17] small comment improvement
---
.../unwind-frameless-faulted/interrupt-and-trap-funcs.s | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index b50c4734f18f3..38be06a681bf2 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -18,10 +18,10 @@
_to_be_interrupted:
.cfi_startproc
- // This is a garbage entry to ensure that eh_frame is emitted,
- // it isn't used for anything. If there's no eh_frame, lldb
- // can do an assembly emulation scan and add a rule for $lr
- // which won't expose the issue at hand.
+ // This is a garbage entry to ensure that eh_frame is emitted.
+ // If there's no eh_frame, lldb can use the assembly emulation scan,
+ // which always includes a rule for $lr, and we won't replicate the
+ // bug we're testing for.
.cfi_escape DW_CFA_register, ehframe_x22, ehframe_x23
mov x24, x0
add x24, x24, #1
>From 620eace34ae149b8c513767935118b6e870646fc Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 18:47:54 -0700
Subject: [PATCH 07/17] more comment fix
---
.../macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index 38be06a681bf2..b5c5cb79656c3 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -59,7 +59,8 @@ _trap:
// Mark x20 as undefined. This is a callee-preserved
// (non-volatile) register by the SysV AArch64 ABI, but
- // it's be fun to see lldb not passing a value past this.
+ // it'll be fun to see lldb not passing a value past this
+ // point on the stack.
.cfi_undefined ehframe_x20
// standard prologue save of fp & lr so we can call
>From 6185c513beaa2f63dc04b54f723b209de8af2286 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 22:36:21 -0700
Subject: [PATCH 08/17] Add test case Makefile and API test python code. Also
fix one bug in the by-hand unwind state in the assembly file.
---
.../macosx/unwind-frameless-faulted/Makefile | 12 ++++
.../TestUnwindFramelessFaulted.py | 59 +++++++++++++++++++
.../interrupt-and-trap-funcs.s | 1 +
3 files changed, 72 insertions(+)
create mode 100644 lldb/test/API/macosx/unwind-frameless-faulted/Makefile
create mode 100644 lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/Makefile b/lldb/test/API/macosx/unwind-frameless-faulted/Makefile
new file mode 100644
index 0000000000000..76548928a3622
--- /dev/null
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/Makefile
@@ -0,0 +1,12 @@
+C_SOURCES := main.c
+
+interrupt-and-trap-funcs.o: interrupt-and-trap-funcs.s
+ $(CC) $(CFLAGS) -c -o interrupt-and-trap-funcs.o $(SRCDIR)/interrupt-and-trap-funcs.s
+
+include Makefile.rules
+
+a.out: interrupt-and-trap-funcs.o
+
+# Needs to come after include
+OBJECTS += interrupt-and-trap-funcs.o
+
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
new file mode 100644
index 0000000000000..34e7fbfffacde
--- /dev/null
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
@@ -0,0 +1,59 @@
+"""Test that lldb backtraces a frameless function that faults correctly."""
+
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import shutil
+import os
+
+
+class TestUnwindFramelessFaulted(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipUnlessDarwin
+ def test_frameless_faulted_unwind(self):
+ self.build()
+
+ (target, process, thread, bp) = lldbutil.run_to_name_breakpoint(
+ self, "main", only_one_thread=False
+ )
+
+ # The test program will have a backtrace like this at its deepest:
+ #
+ # * frame #0: 0x0000000102adc468 a.out`break_to_debugger + 4
+ # frame #1: 0x0000000102adc458 a.out`trap + 16
+ # frame #2: 0x0000000102adc440 a.out`to_be_interrupted + 20
+ # frame #3: 0x0000000102adc418 a.out`main at main.c:4:7
+ # frame #4: 0x0000000193b7eb4c dyld`start + 6000
+
+ correct_frames = ["break_to_debugger", "trap", "to_be_interrupted", "main"]
+
+ # Keep track of when main has branch & linked, instruction step until we're
+ # back in main()
+ main_has_bl_ed = False
+
+ # Instruction step through the binary until we are in a function not
+ # listed in correct_frames.
+ while (
+ process.GetState() == lldb.eStateStopped
+ and thread.GetFrameAtIndex(0).name in correct_frames
+ ):
+ starting_index = 0
+ if self.TraceOn():
+ self.runCmd("bt")
+
+ # Find which index into correct_frames the current stack frame is
+ for idx, name in enumerate(correct_frames):
+ if thread.GetFrameAtIndex(0).name == name:
+ starting_index = idx
+
+ # Test that all frames after the current frame listed in
+ # correct_frames appears in the backtrace.
+ frame_idx = 0
+ for expected_frame in correct_frames[starting_index:]:
+ self.assertEqual(thread.GetFrameAtIndex(frame_idx).name, expected_frame)
+ frame_idx = frame_idx + 1
+
+ if self.TraceOn():
+ print("StepInstruction")
+ thread.StepInstruction(False)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index b5c5cb79656c3..5bc991fc0f67d 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -80,6 +80,7 @@ _trap:
.cfi_def_cfa sp, 32
add sp, sp, #32
.cfi_same_value sp
+ .cfi_def_cfa sp, 0
// jump back to $x23 to resume execution of to_be_interrupted
br x23
>From d239b7a84c1e489b2630aa63358061435a749ce7 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 22:49:20 -0700
Subject: [PATCH 09/17] Add tests for x0 and x20, which I treat in normally
ABI-wrong ways in these hand-written UnwindPlans.
---
.../TestUnwindFramelessFaulted.py | 34 ++++++++++++++++---
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
index 34e7fbfffacde..d899b7a2f7369 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
@@ -34,17 +34,15 @@ def test_frameless_faulted_unwind(self):
# Instruction step through the binary until we are in a function not
# listed in correct_frames.
- while (
- process.GetState() == lldb.eStateStopped
- and thread.GetFrameAtIndex(0).name in correct_frames
- ):
+ frame = thread.GetFrameAtIndex(0)
+ while process.GetState() == lldb.eStateStopped and frame.name in correct_frames:
starting_index = 0
if self.TraceOn():
self.runCmd("bt")
# Find which index into correct_frames the current stack frame is
for idx, name in enumerate(correct_frames):
- if thread.GetFrameAtIndex(0).name == name:
+ if frame.name == name:
starting_index = idx
# Test that all frames after the current frame listed in
@@ -54,6 +52,32 @@ def test_frameless_faulted_unwind(self):
self.assertEqual(thread.GetFrameAtIndex(frame_idx).name, expected_frame)
frame_idx = frame_idx + 1
+ # When we're at our deepest level, test that register passing of x0 and x20
+ # follow the by-hand UnwindPlan rules. In this test program, we can get x0
+ # in the middle of the stack and we CAN'T get x20. The opposites of the normal
+ # AArch64 SysV ABI.
+ if frame.name == "break_to_debugger":
+ tbi_frame = thread.GetFrameAtIndex(2)
+ self.assertEqual(tbi_frame.name, "to_be_interrupted")
+
+ # The original argument to to_be_interrupted(), 10
+ # Normally can't get x0 mid-stack, but UnwindPlans have special rules to
+ # make this possible.
+ x0_reg = tbi_frame.register["x0"]
+ self.assertTrue(x0_reg.IsValid())
+ self.assertEqual(x0_reg.GetValueAsUnsigned(), 10)
+
+ # The incremented return value from to_be_interrupted(), 11
+ x24_reg = tbi_frame.register["x24"]
+ self.assertTrue(x24_reg.IsValid())
+ self.assertEqual(x24_reg.GetValueAsUnsigned(), 11)
+
+ # x20 can normally be fetched mid-stack, but the UnwindPlan
+ # has a rule saying it can't be fetched.
+ x20_reg = tbi_frame.register["x20"]
+ self.assertTrue(x20_reg.error.fail)
+
if self.TraceOn():
print("StepInstruction")
thread.StepInstruction(False)
+ frame = thread.GetFrameAtIndex(0)
>From 33563049b37479db9ebebdad0a1c982deb4c6f14 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Thu, 8 May 2025 22:52:04 -0700
Subject: [PATCH 10/17] Remove some Mach-O/Darwinisms, get closer to this
compiling on linux? I think maybe the only difference is that the symbol
names are prefixed with _ on darwin?
---
.../unwind-frameless-faulted/interrupt-and-trap-funcs.s | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
index 5bc991fc0f67d..2ba6a711767b3 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
@@ -5,7 +5,7 @@
#define ehframe_x23 23
#define ehframe_pc 32
- .section __TEXT,__text,regular,pure_instructions
+ .text
//--------------------------------------
// to_be_interrupted() a frameless function that does a non-ABI
@@ -14,7 +14,6 @@
// trap() knows to branch back to $x23 when it has finished.
//--------------------------------------
.globl _to_be_interrupted
- .p2align 2
_to_be_interrupted:
.cfi_startproc
@@ -45,7 +44,6 @@ L_.return:
// break_to_debugger().
//--------------------------------------
.globl _trap
- .p2align 2
_trap:
.cfi_startproc
.cfi_signal_frame
@@ -90,7 +88,6 @@ _trap:
// break_to_debugger() executes a BRK instruction
//--------------------------------------
.globl _break_to_debugger
- .p2align 2
_break_to_debugger:
.cfi_startproc
>From 80248f5a5841645a1da0026799c040d4db7ab6f3 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 18:44:27 -0700
Subject: [PATCH 11/17] Adapt test case to build & run on linux or Darwin.
There's a slight syntax diff for the ADRP + ADD pair and the label
name. And the function names in Darwin are prepended with an _ and
not on linux.
clang on darwin runs the .s file through the preprocessor, but it
doesn't seem to on linux. I renamed interrupt-and-trap-funcs.s to
interrupt-and-trap-funcs.c and run it through the preprocessor then
assemble it in Makefile now.
The linux version would probably run on other AArch64 systems like
FreeBSD but I haven't checked those.
---
.../API/macosx/unwind-frameless-faulted/Makefile | 5 +++--
.../TestUnwindFramelessFaulted.py | 5 ++++-
...d-trap-funcs.s => interrupt-and-trap-funcs.c} | 16 ++++++++++++----
.../API/macosx/unwind-frameless-faulted/main.c | 10 ++++++++++
4 files changed, 29 insertions(+), 7 deletions(-)
rename lldb/test/API/macosx/unwind-frameless-faulted/{interrupt-and-trap-funcs.s => interrupt-and-trap-funcs.c} (88%)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/Makefile b/lldb/test/API/macosx/unwind-frameless-faulted/Makefile
index 76548928a3622..fca47ae47491c 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/Makefile
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/Makefile
@@ -1,7 +1,8 @@
C_SOURCES := main.c
-interrupt-and-trap-funcs.o: interrupt-and-trap-funcs.s
- $(CC) $(CFLAGS) -c -o interrupt-and-trap-funcs.o $(SRCDIR)/interrupt-and-trap-funcs.s
+interrupt-and-trap-funcs.o: interrupt-and-trap-funcs.c
+ $(CC) $(CFLAGS) -E -o interrupt-and-trap-funcs.s $(SRCDIR)/interrupt-and-trap-funcs.c
+ $(CC) $(CFLAGS) -c -o interrupt-and-trap-funcs.o interrupt-and-trap-funcs.s
include Makefile.rules
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
index d899b7a2f7369..fe4b9b52abebb 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
@@ -10,7 +10,10 @@
class TestUnwindFramelessFaulted(TestBase):
NO_DEBUG_INFO_TESTCASE = True
- @skipUnlessDarwin
+ @skipIf(
+ oslist=no_match([lldbplatformutil.getDarwinOSTriples(), "linux"]),
+ archs=no_match(["aarch64", "arm64", "arm64e"]),
+ )
def test_frameless_faulted_unwind(self):
self.build()
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.c
similarity index 88%
rename from lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
rename to lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.c
index 2ba6a711767b3..23c6cfd688969 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.s
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.c
@@ -6,7 +6,6 @@
#define ehframe_pc 32
.text
-
//--------------------------------------
// to_be_interrupted() a frameless function that does a non-ABI
// function call to trap(), simulating an async signal/interrup/exception/fault.
@@ -25,12 +24,21 @@
mov x24, x0
add x24, x24, #1
- adrp x23, L_.return at PAGE ; put return address in x4
+#if defined(__APPLE__)
+ adrp x23, L_.return at PAGE // put return address in x4
add x23, x23, L_.return at PAGEOFF
+#else
+ adrp x23, .L.return
+ add x23, x23, :lo12:.L.return
+#endif
- b _trap ; branch to trap handler, fake async interrupt
+ b _trap // branch to trap handler, fake async interrupt
+#if defined(__APPLE__)
L_.return:
+#else
+.L.return:
+#endif
mov x0, x24
ret
.cfi_endproc
@@ -95,7 +103,7 @@ L_.return:
// retrieve the value if it wants.
.cfi_same_value ehframe_x0
- brk #0xf000 ;; __builtin_debugtrap aarch64 instruction
+ brk #0xf000 // __builtin_debugtrap aarch64 instruction
ret
.cfi_endproc
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/main.c b/lldb/test/API/macosx/unwind-frameless-faulted/main.c
index e121809f25478..27a2f228b5feb 100644
--- a/lldb/test/API/macosx/unwind-frameless-faulted/main.c
+++ b/lldb/test/API/macosx/unwind-frameless-faulted/main.c
@@ -1,6 +1,16 @@
+#if defined(__APPLE__)
int to_be_interrupted(int);
+#else
+int _to_be_interrupted(int);
+#endif
+
int main() {
int c = 10;
+#if defined(__APPLE__)
c = to_be_interrupted(c);
+#else
+ c = _to_be_interrupted(c);
+ #endif
+
return c;
}
>From 98be98ce9eb68dd89179ed1dc1905db9e5fd9cbf Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 18:48:00 -0700
Subject: [PATCH 12/17] Move this test from macosx/ to functionalities/unwind
because it can run on darwin or linux aarch64.
---
.../unwind/frameless-faulted}/Makefile | 0
.../unwind/frameless-faulted}/TestUnwindFramelessFaulted.py | 0
.../unwind/frameless-faulted}/interrupt-and-trap-funcs.c | 0
.../unwind/frameless-faulted}/main.c | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename lldb/test/API/{macosx/unwind-frameless-faulted => functionalities/unwind/frameless-faulted}/Makefile (100%)
rename lldb/test/API/{macosx/unwind-frameless-faulted => functionalities/unwind/frameless-faulted}/TestUnwindFramelessFaulted.py (100%)
rename lldb/test/API/{macosx/unwind-frameless-faulted => functionalities/unwind/frameless-faulted}/interrupt-and-trap-funcs.c (100%)
rename lldb/test/API/{macosx/unwind-frameless-faulted => functionalities/unwind/frameless-faulted}/main.c (100%)
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/Makefile b/lldb/test/API/functionalities/unwind/frameless-faulted/Makefile
similarity index 100%
rename from lldb/test/API/macosx/unwind-frameless-faulted/Makefile
rename to lldb/test/API/functionalities/unwind/frameless-faulted/Makefile
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
similarity index 100%
rename from lldb/test/API/macosx/unwind-frameless-faulted/TestUnwindFramelessFaulted.py
rename to lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.c b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
similarity index 100%
rename from lldb/test/API/macosx/unwind-frameless-faulted/interrupt-and-trap-funcs.c
rename to lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
diff --git a/lldb/test/API/macosx/unwind-frameless-faulted/main.c b/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
similarity index 100%
rename from lldb/test/API/macosx/unwind-frameless-faulted/main.c
rename to lldb/test/API/functionalities/unwind/frameless-faulted/main.c
>From 2e1250cf6bdaed75a3829a8cf465b2fb798505d3 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 18:51:15 -0700
Subject: [PATCH 13/17] typeo
---
lldb/test/API/functionalities/unwind/frameless-faulted/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/main.c b/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
index 27a2f228b5feb..1a016ea61affb 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
@@ -10,7 +10,7 @@ int main() {
c = to_be_interrupted(c);
#else
c = _to_be_interrupted(c);
- #endif
+#endif
return c;
}
>From 2d30011693cf3c3aa1ebdfde57a2c43687b37757 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 19:05:15 -0700
Subject: [PATCH 14/17] Disabling clang-format of the assembly file called ".c"
Add two more checks for non-ABI compliant register availability
from the custom UnwindPlans.
---
.../TestUnwindFramelessFaulted.py | 37 ++++++++++++++-----
.../interrupt-and-trap-funcs.c | 7 ++++
2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
index fe4b9b52abebb..dfb42c56164ac 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
@@ -55,31 +55,50 @@ def test_frameless_faulted_unwind(self):
self.assertEqual(thread.GetFrameAtIndex(frame_idx).name, expected_frame)
frame_idx = frame_idx + 1
- # When we're at our deepest level, test that register passing of x0 and x20
- # follow the by-hand UnwindPlan rules. In this test program, we can get x0
- # in the middle of the stack and we CAN'T get x20. The opposites of the normal
- # AArch64 SysV ABI.
+ # When we're at our deepest level, test that register passing of
+ # x0 and x20 follow the by-hand UnwindPlan rules.
+ # In this test program, we can get x0 in the middle of the stack
+ # and we CAN'T get x20. The opposites of the normal AArch64 SysV
+ # ABI.
if frame.name == "break_to_debugger":
tbi_frame = thread.GetFrameAtIndex(2)
self.assertEqual(tbi_frame.name, "to_be_interrupted")
-
# The original argument to to_be_interrupted(), 10
- # Normally can't get x0 mid-stack, but UnwindPlans have special rules to
- # make this possible.
+ # Normally can't get x0 mid-stack, but UnwindPlans have
+ # special rules to make this possible.
x0_reg = tbi_frame.register["x0"]
self.assertTrue(x0_reg.IsValid())
self.assertEqual(x0_reg.GetValueAsUnsigned(), 10)
-
# The incremented return value from to_be_interrupted(), 11
x24_reg = tbi_frame.register["x24"]
self.assertTrue(x24_reg.IsValid())
self.assertEqual(x24_reg.GetValueAsUnsigned(), 11)
-
# x20 can normally be fetched mid-stack, but the UnwindPlan
# has a rule saying it can't be fetched.
x20_reg = tbi_frame.register["x20"]
self.assertTrue(x20_reg.error.fail)
+ trap_frame = thread.GetFrameAtIndex(1)
+ self.assertEqual(trap_frame.name, "trap")
+ # Confirm that we can fetch x0 from trap() which
+ # is normally not possible w/ SysV AbI, but special
+ # UnwindPlans in use.
+ x0_reg = trap_frame.register["x0"]
+ self.assertTrue(x0_reg.IsValid())
+ self.assertEqual(x0_reg.GetValueAsUnsigned(), 10)
+ x1_reg = trap_frame.register["x1"]
+ self.assertTrue(x1_reg.error.fail)
+
+ main_frame = thread.GetFrameAtIndex(3)
+ self.assertEqual(main_frame.name, "main")
+ # x20 can normally be fetched mid-stack, but the UnwindPlan
+ # has a rule saying it can't be fetched.
+ x20_reg = main_frame.register["x20"]
+ self.assertTrue(x20_reg.error.fail)
+ # x21 can be fetched mid-stack.
+ x21_reg = main_frame.register["x21"]
+ self.assertTrue(x21_reg.error.success)
+
if self.TraceOn():
print("StepInstruction")
thread.StepInstruction(False)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
index 23c6cfd688969..d32f01a2ea429 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
@@ -1,3 +1,10 @@
+// This is assembly code that needs to be run
+// through the preprocessor, for simplicity of
+// preprocessing it's named .c to start with.
+//
+// clang-format off
+
+
#define DW_CFA_register 0x9
#define ehframe_x0 0
#define ehframe_x20 20
>From a555af1ba3c17076708aea0548997fd3b579e2a7 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 19:20:02 -0700
Subject: [PATCH 15/17] Advance past the BRK instruction in break_to_debugger()
for lldb-server where it does not advance past this BRK instruction
automatically.
Also add a limit on instruction stepping, so if this does get stuck
in a loop it won't run forever.
I haven't tested this on a linux system yet but in by-hand running
on the binary, I saw the lldb-server behavior w.r.t builtin_debugtrap
and this should be necessary.
---
.../TestUnwindFramelessFaulted.py | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py b/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
index dfb42c56164ac..a03d994045773 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/TestUnwindFramelessFaulted.py
@@ -38,7 +38,13 @@ def test_frameless_faulted_unwind(self):
# Instruction step through the binary until we are in a function not
# listed in correct_frames.
frame = thread.GetFrameAtIndex(0)
- while process.GetState() == lldb.eStateStopped and frame.name in correct_frames:
+ step_count = 0
+ max_step_count = 200
+ while (
+ process.GetState() == lldb.eStateStopped
+ and frame.name in correct_frames
+ and step_count < max_step_count
+ ):
starting_index = 0
if self.TraceOn():
self.runCmd("bt")
@@ -99,7 +105,18 @@ def test_frameless_faulted_unwind(self):
x21_reg = main_frame.register["x21"]
self.assertTrue(x21_reg.error.success)
+ # manually move past the BRK instruction in
+ # break_to_debugger(). lldb-server doesn't
+ # advance past the builtin_debugtrap() BRK
+ # instruction.
+ if (
+ thread.GetStopReason() == lldb.eStopReasonException
+ and frame.name == "break_to_debugger"
+ ):
+ frame.SetPC(frame.GetPC() + 4)
+
if self.TraceOn():
print("StepInstruction")
thread.StepInstruction(False)
frame = thread.GetFrameAtIndex(0)
+ step_count = step_count + 1
>From da712493ad7917218603c0f622d4390bcf6810ed Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 19:23:15 -0700
Subject: [PATCH 16/17] typeo
---
.../unwind/frameless-faulted/interrupt-and-trap-funcs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
index d32f01a2ea429..7525200595f77 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
@@ -32,7 +32,7 @@
add x24, x24, #1
#if defined(__APPLE__)
- adrp x23, L_.return at PAGE // put return address in x4
+ adrp x23, L_.return at PAGE // put return address in x23
add x23, x23, L_.return at PAGEOFF
#else
adrp x23, .L.return
>From a1b574a0654b1a80d78b336cf397c11016ec110a Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 9 May 2025 19:28:20 -0700
Subject: [PATCH 17/17] Shift the underscore-versus-not assembly naming
convention into the .s file -- the Test python file also hardcodes the names
of the functions and I don't want to prepend _ on linux to those names.
---
.../interrupt-and-trap-funcs.c | 26 +++++++++++++------
.../unwind/frameless-faulted/main.c | 9 -------
2 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
index 7525200595f77..ba6537226f920 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/interrupt-and-trap-funcs.c
@@ -12,6 +12,16 @@
#define ehframe_x23 23
#define ehframe_pc 32
+#if defined(__APPLE__)
+#define TO_BE_INTERRUPTED _to_be_interrupted
+#define TRAP _trap
+#define BREAK_TO_DEBUGGER _break_to_debugger
+#else
+#define TO_BE_INTERRUPTED to_be_interrupted
+#define TRAP trap
+#define BREAK_TO_DEBUGGER break_to_debugger
+#endif
+
.text
//--------------------------------------
// to_be_interrupted() a frameless function that does a non-ABI
@@ -19,8 +29,8 @@
// Before it branches to trap(), put the return address in x23.
// trap() knows to branch back to $x23 when it has finished.
//--------------------------------------
- .globl _to_be_interrupted
-_to_be_interrupted:
+ .globl TO_BE_INTERRUPTED
+TO_BE_INTERRUPTED:
.cfi_startproc
// This is a garbage entry to ensure that eh_frame is emitted.
@@ -39,7 +49,7 @@
add x23, x23, :lo12:.L.return
#endif
- b _trap // branch to trap handler, fake async interrupt
+ b TRAP // branch to trap handler, fake async interrupt
#if defined(__APPLE__)
L_.return:
@@ -58,8 +68,8 @@ L_.return:
// "interrupted" stack frame (it's in x23), then calls
// break_to_debugger().
//--------------------------------------
- .globl _trap
-_trap:
+ .globl TRAP
+TRAP:
.cfi_startproc
.cfi_signal_frame
@@ -85,7 +95,7 @@ L_.return:
.cfi_offset w30, -8
.cfi_offset w29, -16
- bl _break_to_debugger
+ bl BREAK_TO_DEBUGGER
ldp x29, x30, [sp, #16]
.cfi_same_value x29
@@ -102,8 +112,8 @@ L_.return:
//--------------------------------------
// break_to_debugger() executes a BRK instruction
//--------------------------------------
- .globl _break_to_debugger
-_break_to_debugger:
+ .globl BREAK_TO_DEBUGGER
+BREAK_TO_DEBUGGER:
.cfi_startproc
// For fun, mark x0 as unmodified so the caller can
diff --git a/lldb/test/API/functionalities/unwind/frameless-faulted/main.c b/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
index 1a016ea61affb..e5f690a21a45e 100644
--- a/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
+++ b/lldb/test/API/functionalities/unwind/frameless-faulted/main.c
@@ -1,16 +1,7 @@
-#if defined(__APPLE__)
int to_be_interrupted(int);
-#else
-int _to_be_interrupted(int);
-#endif
int main() {
int c = 10;
-#if defined(__APPLE__)
c = to_be_interrupted(c);
-#else
- c = _to_be_interrupted(c);
-#endif
-
return c;
}
More information about the lldb-commits
mailing list