StackTrace: AArch64: Add Frame pointer based stack trace support for GCC compiled PE binaries#1317
Open
vineelko wants to merge 1 commit intoOpenDevicePartnership:mainfrom
Conversation
bb77c2c to
85e1f94
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
85e1f94 to
5d03bad
Compare
os-d
approved these changes
Feb 13, 2026
…led PE binaries Dumps the stack trace by walking the FP/LR registers, without relying on unwind information. This is an AArch64-only fallback mechanism. For GCC built PE images, .pdata/.xdata sections are not generated, causing stack trace dumping to fail. In this case, we attempt to dump the stack trace using an FP/LR register walk with the following limitations: 1. Patina binaries produced with LLVM almost always do not save FP/LR register pairs as part of the function prologue for non-leaf functions, even though the ABI mandates it. https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#646the-frame-pointer 2. Forcing this with the `-C force-frame-pointers=yes` compiler flag can produce strange results. In some cases, instead of saving fp/lr using `stp x29, x30, [sp, OpenDevicePartnership#16]!`, it saves lr/fp using `stp x30, x29, [sp, OpenDevicePartnership#16]!`, completely breaking the stack walk. https://godbolt.org/z/7s9fG9vWe 3. Due to the above reasons, the stack walk cannot be reliably terminated. The only reason this is being introduced is to identify the driver/app causing the exception. For example, a Shell app built with GCC that triggers an assertion can still produce a reasonable stack trace. ```text Dumping stack trace with PC: 000001007AB72ED0, SP: 0000010078885D50, FP: 0000010078885D50 # Child-SP Return Address Call Site 0 0000010078885D50 000001007AB12770 Shell+66ED0 1 0000010078885E90 0000010007B98DCC Shell+6770 2 0000010078885FF0 0000010007B98E54 qemu_sbsa_dxe_core+18DCC 3 0000010007FFF4C0 0000010007B98F48 qemu_sbsa_dxe_core+18E54 4 0000010007FFF800 000001007AF54D08 qemu_sbsa_dxe_core+18F48 5 0000010007FFFA90 0000010007BAC388 BdsDxe+8D08 6 0000010007FFFF80 0000000010008878 qemu_sbsa_dxe_core+2C388 --. | 0:000> u qemu_sbsa_dxe_core!patina_dxe_core::call_bds | 00000000`1002c1b0 f81f0ff3 str x19,[sp,#-0x10]! | 00000000`1002c1b4 f90007fe str lr,[sp,OpenDevicePartnership#8] <---------------------------' 00000000`1002c1b8 d10183ff sub sp,sp,#0x60 The FP is not saved, so the return address in frame OpenDevicePartnership#6 is garbage. ``` Symbol to source file resolution(Resolving OpenDevicePartnership#2 frame): Since some modules in the stack trace are built with GCC and do not generate PDB files, their symbols must be resolved manually as shown below. ```text $ addr2line -e Shell.debug -f -C 0x6770 UefiMain ~/repos/patina-qemu/MU_BASECORE/ShellPkg/Application/Shell/Shell.c:372 ``` Signed-off-by: Vineel Kovvuri[MSFT] <vineelko@microsoft.com>
5d03bad to
73899a0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Dumps the stack trace by walking the FP/LR registers, without relying on unwind information. This is an AArch64-only fallback mechanism.
For GCC built PE images, .pdata/.xdata sections are not generated, causing stack trace dumping to fail. In this case, we attempt to dump the stack trace using an FP/LR register walk with the following limitations:
Patina binaries produced with LLVM almost always do not save FP/LR register pairs as part of the function prologue for non-leaf functions, even though the ABI mandates it. https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#646the-frame-pointer
Forcing this with the
-C force-frame-pointers=yescompiler flag can produce strange results. In some cases, instead of saving fp/lr usingstp x29, x30, [sp, #16]!, it saves lr/fp usingstp x30, x29, [sp, #16]!, completely breaking the stack walk. https://godbolt.org/z/7s9fG9vWeDue to the above reasons, the stack walk cannot be reliably terminated.
The only reason this is being introduced is to identify the driver/app causing the exception. For example, a Shell app built with GCC that triggers an assertion can still produce a reasonable stack trace.
Symbol to source file resolution(Resolving frame 2): Since some modules in the stack trace are built with GCC and do not generate PDB files, their symbols must be resolved manually as shown below.
How This Was Tested
Validated on SBSA Q35.
Integration Instructions
The change is already hooked into the exception handler for AArch64.