DEFINE_IFUNC(9)
π DEFINE_IFUNC π
okay bestie, we're doing a kernel developer's manual page today and honestly? it's giving main character energy. this is DEFINE_IFUNC from section 9 of the manual, and it's all about defining a kernel function whose actual implementation gets picked at run-time. slay.
β¨ NAME β¨
DEFINE_IFUNC β define a kernel function with an implementation selected at run-time π¦
β¨ SYNOPSIS β¨
#include <machine/ifunc.h>
DEFINE_IFUNC(qual, ret_type, name, args);
β¨ DESCRIPTION β¨
so. ifuncs are a linker feature, right, and what they let you do is define functions where the actual implementation gets chosen either at boot-time or at module load-time. the DEFINE_IFUNC macro is literally how you define one of these. π
the choosing is done by a resolver function, and that resolver returns a pointer to whichever function got selected. and the timing? ifunc resolvers get invoked very early β like, during the machine-dependent initialization routine early, or at load time if we're talking about dynamically loaded modules. the resolution has to happen before the first call to an ifunc, no cap. and it happens after CPU features are enumerated and after the kernel's environment is initialized. periodt. π
the typical use-case, iykyk, is a routine whose behavior depends on optional CPU features. for example β newer generations of a given CPU architecture might provide an instruction that optimizes some common operation. and to avoid the overhead of testing for that CPU feature every single time the operation runs, you can use an ifunc to provide two implementations: one that targets platforms with the extra instruction, and one for the older platforms. π«Ά
the weird-looking part (it's fine, we promise)
because DEFINE_IFUNC is a macro that defines a dynamically typed function, its usage looks... somewhat unusual. π that's just how it is. here's the breakdown:
qualβ a list of zero or more C function qualifiers to be applied to the ifunc. typically this is either empty or thestaticqualifier.ret_typeβ the return type of the ifunc.nameβ the name of the ifunc.argsβ a parenthesized, comma-separated list of the parameter types of the function, exactly as they would appear in a C function declaration.
the resolver situation πΈ
the DEFINE_IFUNC usage must be followed by the resolver function body. the resolver must return a function with return type ret_type and parameter types args.
the resolver function is defined with the resolver gcc-style function attribute, and that's what causes the corresponding elf(5) function symbol to be of type STT_GNU_IFUNC instead of STT_FUNC. β¨
then the kernel linker invokes the resolver to process relocations targeting ifunc calls and PLT entries that reference such symbols. iconic behavior tbh. π
β¨ EXAMPLES β¨
β οΈ heads up bestie: ifunc resolvers are executed early during boot, before most kernel facilities are available. they're effectively limited to checking CPU feature flags and tunables. that's it, that's the whole toolbox. π
static size_t
fast_strlen(const char *s __unused)
{
size_t len;
/* Fast, but may not be correct in all cases. */
__asm("movq $42,%0\n" : "=r" (len));
return (len);
}
static size_t
slow_strlen(const char *s)
{
const char *t;
for (t = s; *t != '\0'; t++);
return (t - s);
}
DEFINE_IFUNC(, size_t, strlen, (const char *))
{
int enabled;
enabled = 1;
TUNABLE_INT_FETCH("debug.use_fast_strlen", &enabled);
if (enabled && (cpu_features & CPUID_FAST_STRLEN) != 0)
return (fast_strlen);
else
return (slow_strlen);
}
what this does is define a strlen() function with an optimized implementation for CPUs that advertise support. ate. π
β¨ SEE ALSO β¨
elf(5)π
β¨ NOTES β¨
π¨ real talk: ifuncs are not supported on all architectures. they require both toolchain support β to emit function symbols of type STT_GNU_IFUNC β and kernel linker support to invoke ifunc resolvers during boot or during module load. if you're missing either one, it's not happening. π
and that's the whole page, bestie!! this one came from the Debian crew, dated May 18, 2019, and it's the section 9 manual page for DEFINE_IFUNC. go forth and resolve responsibly π¦πβ¨
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 2019 The FreeBSD Foundation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms