@@ -1413,31 +1413,73 @@ 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), then
1444+ // there's the caller's `rbp` that we just pushed.
14211445 " .cfi_offset rbp, -16" ,
1446+ // As is traditional, we set the base pointer to the value of
1447+ // the stack pointer. This way, the base pointer stays the
1448+ // same throughout the function body.
14221449 " mov rbp, rsp" ,
1450+ // We can now track the offset to the CFA from the base
1451+ // pointer. This means we don't need to make any further
1452+ // adjustments until the end, as we don't change `rbp`.
14231453 " .cfi_def_cfa_register rbp" ,
1424- "" ,
1425- " call {function}" ,
1426- "" ,
1454+ // We can now call a function that may panic.
1455+ " call {f}" ,
1456+ // Upon return, we restore `rbp` in preparation for returning
1457+ // ourselves.
14271458 " pop rbp" ,
1459+ // Now that we've restored `rbp`, we must specify the offset
1460+ // to the CFA again in terms of `rsp`.
14281461 " .cfi_def_cfa rsp, 8" ,
1462+ // Now we can return.
14291463 " ret" ,
14301464 " .cfi_endproc" ,
1431- function = sym function_that_panics ,
1465+ f = sym may_panic ,
14321466 )
14331467}
14341468
1435- extern " C -unwind" fn function_that_panics () {
1469+ extern " sysv64 -unwind" fn may_panic () {
14361470 panic! (" unwind!" );
14371471}
14381472# }
14391473```
14401474
1475+ > [ !NOTE]
1476+ >
1477+ > For more information on the ` cfi ` assembler directives above, see these resources:
1478+ >
1479+ > - [ Using ` as ` - CFI directives] ( https://sourceware.org/binutils/docs/as/CFI-directives.html )
1480+ > - [ DWARF Debugging Information Format Version 5] ( https://dwarfstd.org/doc/DWARF5.pdf )
1481+ > - [ ImperialViolet - CFI directives in assembly files] ( https://www.imperialviolet.org/2017/01/18/cfi.html )
1482+
14411483r[ asm.validity]
14421484### Correctness and Validity
14431485
0 commit comments