diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-06-16 19:15:23 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-06-16 19:15:23 -0700 |
commit | a855db50712b45bc6e531a00d00b1b6c519943ee (patch) | |
tree | 94488bdd785dcbd3674e7b67c803cec348ccc200 | |
parent | 77ba3efb094057f7d1a720887c7ae92ca0ac031c (diff) | |
download | misc-tests-a855db50712b45bc6e531a00d00b1b6c519943ee.tar.gz |
Add test_vdso_parser
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | test_vdso_parser.cc | 83 |
2 files changed, 91 insertions, 2 deletions
@@ -1,8 +1,8 @@ .PHONY: all clean -all: timing_test_64 timing_test_32 evil-clock-test test_vsyscall_64 test_vsyscall_32 dump-vdso dump-vvar dump-vsyscall context_switch_latency kernel_pf user_visible_state +all: timing_test_64 timing_test_32 evil-clock-test test_vsyscall_64 test_vsyscall_32 dump-vdso dump-vvar dump-vsyscall context_switch_latency kernel_pf user_visible_state test_vdso_parser_64 test_vdso_parser_32 clean: - rm -f timing_test_64 timing_test_32 evil-clock-test test_vsyscall_64 test_vsyscall_32 dump-vdso dump-vvar dump-vsyscall context_switch_latency kernel_pf user_visible_state + rm -f timing_test_64 timing_test_32 evil-clock-test test_vsyscall_64 test_vsyscall_32 dump-vdso dump-vvar dump-vsyscall context_switch_latency kernel_pf user_visible_state test_vdso_parser_64 test_vdso_parser_32 user_visible_state: user_visible_state.c gcc -o $@ -O2 -std=gnu99 -Wall $(EXTRA_CFLAGS) -g $^ -lrt -ldl @@ -25,6 +25,12 @@ test_vsyscall_64: test_vsyscall.cc test_vsyscall_32: test_vsyscall.cc g++ -m32 -o $@ -std=gnu++0x -O2 -Wall $(EXTRA_CFLAGS) -g $^ -lrt -ldl +test_vdso_parser_64: test_vdso_parser.cc + g++ -m64 -o $@ -std=gnu++0x -O2 -Wall $(EXTRA_CFLAGS) -g $^ -lrt -ldl + +test_vdso_parser_32: test_vdso_parser.cc + g++ -m32 -o $@ -std=gnu++0x -O2 -Wall $(EXTRA_CFLAGS) -g $^ -lrt -ldl + dump-vdso: dump-vdso.c gcc -o $@ -O2 $(EXTRA_CFLAGS) $^ -ldl diff --git a/test_vdso_parser.cc b/test_vdso_parser.cc new file mode 100644 index 0000000..f8612c4 --- /dev/null +++ b/test_vdso_parser.cc @@ -0,0 +1,83 @@ +#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; +} |