summaryrefslogtreecommitdiffstats
path: root/test_vdso_parser.cc
blob: f8612c46d7c8278be94fae22b19d875e2843e157 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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;
}