@@ -1413,31 +1413,74 @@ r[asm.naked-rules.unwind]
14131413``` rust
14141414# #[cfg(target_arch = " x86_64" )] {
14151415#[unsafe (naked)]
1416- extern " C -unwind" fn naked_function () {
1416+ extern " sysv64 -unwind" fn unwinding_naked () {
14171417 core :: arch :: naked_asm! (
1418+ // "CFI" here stands for "call frame information".
14181419 " .cfi_startproc" ,
1420+ // The CFA (canonical frame address) is the value of `rsp`
1421+ // before the `call`, i.e. before the return address, `rip`,
1422+ // was pushed to `rsp`, so it's eight bytes higher in memory
1423+ // than `rsp` upon function entry (after `rip` has been
1424+ // pushed).
1425+ //
1426+ // This is the default, so we don't have to write it.
1427+ // ".cfi_def_cfa rsp, 8",
1428+ //
1429+ // The traditional thing to do is to preserve the base
1430+ // pointer, so we'll do that.
14191431 " push rbp" ,
1420- " .cfi_def_cfa_offset 16" ,
1432+ // Since we've now extended the stack downward by 8 bytes in
1433+ // memory, we need to adjust the offset to the CFA from `rsp`
1434+ // by another 8 bytes.
1435+ " .cfi_adjust_cfa_offset 8" ,
1436+ // We also then annotate where we've stored the caller's value
1437+ // of `rbp`, relative to the CFA, so that when unwinding into
1438+ // the caller we can find it, in case we need it to calculate
1439+ // the caller's CFA relative to it.
1440+ //
1441+ // Here, we've stored the caller's `rbp` starting 16 bytes
1442+ // below the CFA. I.e., starting from the CFA, there's first
1443+ // the `rip` (which starts 8 bytes below the CFA and continues
1444+ // up to it), then there's the caller's `rbp` that we just
1445+ // pushed.
14211446 " .cfi_offset rbp, -16" ,
1447+ // As is traditional, we set the base pointer to the value of
1448+ // the stack pointer. This way, the base pointer stays the
1449+ // same throughout the function body.
14221450 " mov rbp, rsp" ,
1451+ // We can now track the offset to the CFA from the base
1452+ // pointer. This means we don't need to make any further
1453+ // adjustments until the end, as we don't change `rbp`.
14231454 " .cfi_def_cfa_register rbp" ,
1424- "" ,
1425- " call {function}" ,
1426- "" ,
1455+ // We can now call a function that may panic.
1456+ " call {f}" ,
1457+ // Upon return, we restore `rbp` in preparation for returning
1458+ // ourselves.
14271459 " pop rbp" ,
1460+ // Now that we've restored `rbp`, we must specify the offset
1461+ // to the CFA again in terms of `rsp`.
14281462 " .cfi_def_cfa rsp, 8" ,
1463+ // Now we can return.
14291464 " ret" ,
14301465 " .cfi_endproc" ,
1431- function = sym function_that_panics ,
1466+ f = sym may_panic ,
14321467 )
14331468}
14341469
1435- extern " C -unwind" fn function_that_panics () {
1436- panic! (" unwind! " );
1470+ extern " sysv64 -unwind" fn may_panic () {
1471+ panic! (" unwind" );
14371472}
14381473# }
14391474```
14401475
1476+ > [ !NOTE]
1477+ >
1478+ > For more information on the ` cfi ` assembler directives above, see these resources:
1479+ >
1480+ > - [ Using ` as ` - CFI directives] ( https://sourceware.org/binutils/docs/as/CFI-directives.html )
1481+ > - [ DWARF Debugging Information Format Version 5] ( https://dwarfstd.org/doc/DWARF5.pdf )
1482+ > - [ ImperialViolet - CFI directives in assembly files] ( https://www.imperialviolet.org/2017/01/18/cfi.html )
1483+
14411484r[ asm.validity]
14421485### Correctness and Validity
14431486
0 commit comments