mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
scr_unwind_raise walks the stack with plans cached per return address. The first raise through a return address finds the function's FDE through the .eh_frame_hdr of the object that contains it, runs the CFI up to the call, and finds the call site's landing pad in the LSDA; the plan records the frame's CFA rule, where its callee-saved registers are saved, and the landing pad. Later raises look the plans up, restore the registers, and jump to the first landing pad. Plans are inserted under a lock and read without one. Landing pads continue the unwind with scr_unwind_resume instead of `resume`, so the walk goes on from their frame. A frame whose CFI, pointer encodings or personality the plans do not express, or a return address without an FDE, leaves the unwind to libgcc's forced unwind from the frame the walk started at, as before. Other Linux targets keep libgcc's unwinder; their scr_unwind_resume calls _Unwind_Resume. bench:runtime gains layered-errors, a workload whose errors are thrown below small functions that hold references and caught per entry in a loop, and the corpus gains unwind-landing-pad-chains, which pins landing pads that continue the unwind, including in frames LLVM inlines into a caller whose handler takes the exception.
102 lines
2.3 KiB
ArmAsm
102 lines
2.3 KiB
ArmAsm
/* Frames for test_unwind.c with CFI that compilers emit rarely. Like the
|
|
* frames in test_unwind_frames.ll, each takes a chain and calls its first
|
|
* function with the rest. */
|
|
.text
|
|
|
|
/* Saves rbx and r12, and leaves through an early epilogue under
|
|
* remember_state before its call, so the call's rules come from
|
|
* restore_state. */
|
|
.globl asm_remember
|
|
.type asm_remember,@function
|
|
asm_remember:
|
|
.cfi_startproc
|
|
pushq %rbx
|
|
.cfi_def_cfa_offset 16
|
|
.cfi_offset %rbx, -16
|
|
pushq %r12
|
|
.cfi_def_cfa_offset 24
|
|
.cfi_offset %r12, -24
|
|
subq $8, %rsp
|
|
.cfi_def_cfa_offset 32
|
|
movq (%rdi), %rax
|
|
testq %rax, %rax
|
|
jne 1f
|
|
.cfi_remember_state
|
|
addq $8, %rsp
|
|
.cfi_def_cfa_offset 24
|
|
popq %r12
|
|
.cfi_def_cfa_offset 16
|
|
.cfi_restore %r12
|
|
popq %rbx
|
|
.cfi_def_cfa_offset 8
|
|
.cfi_restore %rbx
|
|
retq
|
|
.cfi_restore_state
|
|
1:
|
|
movabsq $0x5151515151515151, %rbx
|
|
movabsq $0x5252525252525252, %r12
|
|
addq $8, %rdi
|
|
callq *%rax
|
|
addq $8, %rsp
|
|
.cfi_def_cfa_offset 24
|
|
popq %r12
|
|
.cfi_def_cfa_offset 16
|
|
popq %rbx
|
|
.cfi_def_cfa_offset 8
|
|
retq
|
|
.cfi_endproc
|
|
.size asm_remember, .-asm_remember
|
|
|
|
/* An rbp frame that saves r13 and r14 below rbp and moves the stack
|
|
* pointer by an amount that depends on the chain's address. */
|
|
.globl asm_rbp
|
|
.type asm_rbp,@function
|
|
asm_rbp:
|
|
.cfi_startproc
|
|
pushq %rbp
|
|
.cfi_def_cfa_offset 16
|
|
.cfi_offset %rbp, -16
|
|
movq %rsp, %rbp
|
|
.cfi_def_cfa_register %rbp
|
|
pushq %r13
|
|
pushq %r14
|
|
.cfi_offset %r13, -24
|
|
.cfi_offset %r14, -32
|
|
movq %rdi, %rax
|
|
andq $0x70, %rax
|
|
subq %rax, %rsp
|
|
movabsq $0x5353535353535353, %r13
|
|
movabsq $0x5454545454545454, %r14
|
|
movq (%rdi), %rax
|
|
addq $8, %rdi
|
|
callq *%rax
|
|
leaq -16(%rbp), %rsp
|
|
popq %r14
|
|
popq %r13
|
|
popq %rbp
|
|
.cfi_def_cfa %rsp, 8
|
|
retq
|
|
.cfi_endproc
|
|
.size asm_rbp, .-asm_rbp
|
|
|
|
/* Defines its CFA with a DWARF expression (rsp + 16), which the plans do
|
|
* not express: raises through it go to libgcc's unwinder. */
|
|
.globl asm_expr
|
|
.type asm_expr,@function
|
|
asm_expr:
|
|
.cfi_startproc
|
|
pushq %rbx
|
|
.cfi_escape 0x0f, 0x02, 0x77, 0x10
|
|
.cfi_offset %rbx, -16
|
|
movabsq $0x5555555555555555, %rbx
|
|
movq (%rdi), %rax
|
|
addq $8, %rdi
|
|
callq *%rax
|
|
popq %rbx
|
|
.cfi_def_cfa %rsp, 8
|
|
retq
|
|
.cfi_endproc
|
|
.size asm_expr, .-asm_expr
|
|
|
|
.section .note.GNU-stack,"",@progbits
|