blob: f8612c46d7c8278be94fae22b19d875e2843e157 [file] [log] [blame]
#include <stdio.h>
#include <dlfcn.h>
#include <err.h>
#include <sys/auxv.h>
#ifndef AT_VDSO_FINDSYM
# define AT_VDSO_FINDSYM 37
#endif
struct vdso_entry {
const char *name, *version;
bool findsym_should_fail;
};
const struct vdso_entry entries[] = {
{ "__vdso_clock_gettime", "LINUX_2.6" },
{ "__vdso_clock_gettime", "LINUX_NEW" },
{ "__vdso_clock_gettime", "LINUX_MISSPELLED" },
{ "__vdso_time", "LINUX_2.6" },
{ "__vdso_getcpu", "LINUX_2.6" },
{ "__vdso_gettimeofday", "LINUX_2.6" },
{ "clock_gettime", "LINUX_2.6", true },
{ "time", "LINUX_2.6", true },
{ "getcpu", "LINUX_2.6", true },
{ "gettimeofday", "LINUX_2.6", true },
{ }
};
/* vsyscalls and vDSO */
typedef void *(*findsym_t)(const char *name, const char *version);
static void *vdso;
static findsym_t findsym;
void init_vdso()
{
vdso = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if (!vdso)
vdso = dlopen("linux-gate.so.1",
RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if (!vdso)
errx(1, "Failed to find vDSO\n");
findsym = (findsym_t)dlvsym(vdso, "__vdso_findsym", "LINUX_2.6");
if (!findsym)
printf("Warning: failed to find __vdso_findsym in vDSO\n");
if (findsym != (findsym_t)getauxval(AT_VDSO_FINDSYM))
printf("Warning: AT_VDSO_FINDSYM doesn't match __vdso_findsym\n");
}
void test(const struct vdso_entry *entry)
{
void *findsym_result, *dlvsym_result;
if (!findsym)
return;
findsym_result = findsym(entry->name, entry->version);
dlvsym_result = dlvsym(vdso, entry->name, entry->version);
if (findsym_result !=
(entry->findsym_should_fail ? NULL : dlvsym_result)) {
printf("Finding \"%s\" (ver \"%s\"): findsym says %p but dlvsym says %p\n",
entry->name, entry->version,
findsym_result, dlvsym_result);
} else {
printf("OK: \"%s\" (ver \"%s\") -> %p (%p)\n",
entry->name, entry->version,
dlvsym_result, findsym_result);
}
}
int main(int argc, char **argv)
{
const struct vdso_entry *e;
init_vdso();
for (e = entries; e->name; e++)
test(e);
return 0;
}