summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-06-16 19:15:23 -0700
committerAndy Lutomirski <luto@amacapital.net>2014-06-16 19:15:23 -0700
commita855db50712b45bc6e531a00d00b1b6c519943ee (patch)
tree94488bdd785dcbd3674e7b67c803cec348ccc200
parent77ba3efb094057f7d1a720887c7ae92ca0ac031c (diff)
downloadmisc-tests-a855db50712b45bc6e531a00d00b1b6c519943ee.tar.gz
Add test_vdso_parser
-rw-r--r--Makefile10
-rw-r--r--test_vdso_parser.cc83
2 files changed, 91 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index bfda8fb..ddf7adc 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
+}