a.c (949B)
1 /* IFUNC called from a __attribute__((constructor)) ctor. 2 * 3 * The ctor lands in .init_array; kit-ld's synthetic ifunc-init 4 * entry sits in .preinit_array, which the CRT (test/link/harness/ 5 * start.c and any standard CRT) iterates first. By the time the 6 * ctor below runs, the .igot.plt slot for my_fn is already 7 * filled with impl_a's address. test_main checks that the ctor 8 * recorded 42, which it could only do if the iplt stub returned 9 * the resolved implementation. */ 10 11 extern int impl_a(void); 12 extern int impl_b(void); 13 extern int (*resolve(void))(void); 14 15 int impl_a(void) { return 42; } 16 int impl_b(void) { return 99; } 17 18 int (*resolve(void))(void) { 19 volatile int x = 1; 20 return x ? impl_a : impl_b; 21 } 22 23 int my_fn(void) __attribute__((ifunc("resolve"))); 24 25 static int g_observed = -1; 26 27 __attribute__((constructor)) static void ctor_runs_my_fn(void) { 28 g_observed = my_fn(); 29 } 30 31 int test_main(void) { return g_observed == 42 ? 0 : 1; }