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