ajhahn.de
← FlashOS
Assembly 53 lines
/*
 * Naked trampolines for hand-rolled patchable-function-entry tracing.
 *
 * Zig has no -fpatchable-function-entry; the two-NOP prologue the
 * trace pipeline expects is synthesised in hand-written assembly. Each
 * traced function's canonical name lives on the trampoline; the real
 * implementation is renamed to <name>_impl. Callers see no change.
 *
 * Layout per entry:
 *     name:    nop              ; slot 0 -> patched to `mov x9, lr`
 *              nop              ; slot 1 -> patched to `bl hook`
 *              b name_impl      ; tail call, LR untouched
 *
 * trace_init walks __patchable_function_entries (bracketed by
 * __start/__stop_patchable_functions in linker.ld), patches both
 * slots, and the next entry into `name` is what fires the hook.
 */

.macro patchable_trampoline name, impl
.globl \name
.type \name, %function
\name:
    nop
    nop
    b \impl
.size \name, . - \name
.endm

patchable_trampoline kernel_main,  kernel_main_impl
patchable_trampoline _schedule,    _schedule_impl
patchable_trampoline do_wait,      do_wait_impl
patchable_trampoline copy_process, copy_process_impl

/*
 * Pointer table consumed by trace_init. linker.ld brackets
 * `__patchable_function_entries` with __start/__stop_patchable_functions.
 *
 * Each entry is the trampoline's absolute link-time VA (low-half,
 * because the kernel ELF is linked at PA 0x80000 / 0x40080000).
 * trace_relocate ORs LINEAR_MAP_BASE (0xFFFF_0000_0000_0000) into each
 * entry to obtain the kernel-virtual high alias the patch path uses.
 * `.quad kernel_main` is a single R_AARCH64_ABS64 the linker resolves
 * — clang's integrated assembler rejects the (function - _start)
 * subtraction-of-two-extern-symbols form, hence the OR-based design.
 */
.section __patchable_function_entries, "a"
.balign 8
.quad kernel_main
.quad _schedule
.quad do_wait
.quad copy_process
.previous