Skip to content

Commit f47d763

Browse files
committed
Add comment for inviariant and fix CFI instructions
1 parent 17be0a2 commit f47d763

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

Python/jit_unwind.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,22 @@ static void elf_init_ehframe(ELFObjectContext* ctx, int absolute_addr) {
533533
* These instructions describe how registers are saved and restored
534534
* during function calls. Each architecture has different calling
535535
* conventions and register usage patterns.
536+
*
537+
* GDB JIT invariant (absolute_addr == 1):
538+
*
539+
* We emit one synthetic FDE for the whole registered JIT region and
540+
* treat that region as one logical native frame while unwinding. This
541+
* relies on the generated executor stencils preserving the
542+
* frame-pointer register across the whole region (%rbp on x86_64,
543+
* x29 on AArch64). Individual stencils may still adjust SP or spill
544+
* temporaries, but they must not clobber the frame pointer or move
545+
* the recoverable caller state away from the frame layout described by
546+
* the steady-state CFI below.
547+
*
548+
* If code generation changes so that executor stencils start touching
549+
* the frame pointer, or the caller state is no longer recoverable from
550+
* this frame layout, then this synthetic GDB CFI must be updated
551+
* together with the stencil generator and tests.
536552
*/
537553
#ifdef __x86_64__
538554
/* x86_64 calling convention unwinding rules; keep CFA on %rbp */
@@ -547,6 +563,12 @@ static void elf_init_ehframe(ELFObjectContext* ctx, int absolute_addr) {
547563
DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past mov %rsp,%rbp (3 bytes)
548564
DWRF_U8(DWRF_CFA_def_cfa_register); // def_cfa_register r6
549565
DWRF_UV(DWRF_REG_BP); // Use base pointer register
566+
if (!absolute_addr) {
567+
DWRF_U8(DWRF_CFA_advance_loc | 3); // Advance past call *%rcx (2 bytes) + pop %rbp (1 byte) = 3
568+
DWRF_U8(DWRF_CFA_def_cfa); // def_cfa r7 ofs 8
569+
DWRF_UV(DWRF_REG_SP); // Use stack pointer register
570+
DWRF_UV(8); // New offset: SP + 8
571+
}
550572
#elif defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__)
551573
/* AArch64 calling convention unwinding rules */
552574
DWRF_U8(DWRF_CFA_advance_loc | 1); // Advance by 1 instruction (4 bytes)
@@ -562,14 +584,16 @@ static void elf_init_ehframe(ELFObjectContext* ctx, int absolute_addr) {
562584
DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = SP + 0 (stack restored)
563585
DWRF_UV(0); // Back to original stack position
564586

565-
DWRF_U8(DWRF_CFA_def_cfa_register); // CFA = FP (x29)
566-
DWRF_UV(DWRF_REG_FP);
567-
DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = FP + 16
568-
DWRF_UV(16);
569-
DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // x29 saved
570-
DWRF_UV(2);
571-
DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 saved
572-
DWRF_UV(1);
587+
if (absolute_addr) {
588+
DWRF_U8(DWRF_CFA_def_cfa_register); // CFA = FP (x29)
589+
DWRF_UV(DWRF_REG_FP);
590+
DWRF_U8(DWRF_CFA_def_cfa_offset); // CFA = FP + 16
591+
DWRF_UV(16);
592+
DWRF_U8(DWRF_CFA_offset | DWRF_REG_FP); // x29 saved
593+
DWRF_UV(2);
594+
DWRF_U8(DWRF_CFA_offset | DWRF_REG_RA); // x30 saved
595+
DWRF_UV(1);
596+
}
573597

574598
#else
575599
# error "Unsupported target architecture"

0 commit comments

Comments
 (0)