1/* @title: Static Call */
2#pragma once
3#include <rw_once.h>
4#include <stdint.h>
5
6#define STATIC_CALL_DECLARE(name, default_fn) \
7 extern __typeof__(default_fn) name##_trampoline; \
8 asm(".pushsection .text, \"ax\"\n\t" \
9 ".globl " #name "_trampoline\n\t" #name "_trampoline:\n\t" \
10 ".byte 0xe9\n\t" /* jmp rel32 */ \
11 ".long " #default_fn " - (" #name "_trampoline + 5)\n\t" \
12 ".popsection\n\t")
13
14#define static_call(name) name##_trampoline
15
16static inline void __static_call_update(void *trampoline, void *fn) {
17 uint8_t *p = trampoline;
18 uint32_t rel = (uint32_t) ((uintptr_t) fn - (uintptr_t) trampoline - 5);
19
20 WRITE_ONCE(*(uint32_t *) (p + 1), rel);
21}
22
23#define static_call_update(name, fn) \
24 do { \
25 __typeof__(&name##_trampoline) _scu_fn = (fn); \
26 __static_call_update((void *) name##_trampoline, (void *) _scu_fn); \
27 } while (0)
28