// pseudo-handle RTLD_NEXT: find the next occurrence of a function in the search order after the current library. This allows one to provide a wrapper around a function in another shared library.
#ifndef RTLD_NEXT
# define RTLD_NEXT ((void *) -1L)
#endif
#define REAL_LIBC RTLD_NEXT
// function pointer which will store the location of libc's uname (ie: the 'real' uname function)
int (*real_uname)(struct utsname *buf) = 0;
static void init (void) __attribute__ ((constructor));
static void init (void)
{
if(!real_uname)
{
real_uname = dlsym(REAL_LIBC, "uname");
if(!real_uname)
{
fprintf(stderr, "missing symbol: uname");
exit(1);
}
}
}
static int do_uname(struct utsname *buf, int (*uname_proc)(struct utsname *buf))
{
return uname_proc(buf);
}
__attribute__ ((visibility("default"))) int uname(struct utsname *buf)
{
init(); // we must always call init as constructor may not be called in some cases (such as loading 32bit pthread library)
int rc = do_uname(buf, real_uname);
if(!rc)
{
// do special processing
}
return rc;
}
Compile this into a shared library, and intercept libc's uname by using LD_PRELOAD=libname.so