kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

ifunc_init.c (1614B)


      1 /* IFUNC startup init for kit-ld static ELF binaries.
      2  *
      3  * The linker (src/link/link_layout.c::layout_iplt) materializes one
      4  * iplt stub + one .igot.plt slot per defined STT_GNU_IFUNC symbol and
      5  * also emits a parallel .iplt.pairs data section: alternating
      6  * (resolver_ptr, slot_ptr) u64 pairs in the same order as the slots.
      7  * For the ELF emit path, the linker additionally synthesizes a
      8  * .init_array entry pointing at __kit_ifunc_init below; the
      9  * freestanding _start (or any standard CRT) walks .init_array before
     10  * user code, so by the time test_main / main runs, every slot holds
     11  * the chosen implementation pointer and the iplt stub's load+branch
     12  * tail-calls correctly.
     13  *
     14  * The JIT path doesn't hit this function: link_jit.c pre-resolves
     15  * slots in-process at load time and intentionally skips the
     16  * .init_array synthesis (so __kit_ifunc_init never becomes an undef
     17  * ref the JIT user has to satisfy).
     18  *
     19  * The .iplt.pairs span symbols are weak so this object can also be
     20  * linked into images that don't carry IFUNCs (or that were linked by
     21  * a non-kit linker that doesn't synthesize __start_iplt_pairs /
     22  * __stop_iplt_pairs) — the function is then a no-op. */
     23 
     24 extern void* __start_iplt_pairs[] __attribute__((weak));
     25 extern void* __stop_iplt_pairs[] __attribute__((weak));
     26 
     27 typedef void* (*kit_ifunc_resolver_t)(void);
     28 
     29 void __kit_ifunc_init(void) {
     30   void** p = __start_iplt_pairs;
     31   void** end = __stop_iplt_pairs;
     32   if (!p || !end) return;
     33   for (; p < end; p += 2) {
     34     kit_ifunc_resolver_t r = (kit_ifunc_resolver_t)p[0];
     35     void** slot = (void**)p[1];
     36     *slot = r();
     37   }
     38 }