#include #include #include #include #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; }