1 // SPDX-License-Identifier: GPL-2.0-only
3 * vdso_test.c: Sample code to test parse_vdso.c on x86
4 * Copyright (c) 2011-2014 Andy Lutomirski
6 * You can amuse yourself by compiling with:
7 * gcc -std=gnu99 -nostdlib
8 * -Os -fno-asynchronous-unwind-tables -flto -lgcc_s
9 * vdso_standalone_test_x86.c parse_vdso.c
10 * to generate a small binary. On x86_64, you can omit -lgcc_s
11 * if you want the binary to be completely standalone.
14 #include <sys/syscall.h>
19 #include "parse_vdso.h"
21 /* We need some libc functions... */
22 int strcmp(const char *a
, const char *b
)
24 /* This implementation is buggy: it never returns -1. */
28 if (*a
== 0 || *b
== 0)
38 * The clang build needs this, although gcc does not.
39 * Stolen from lib/string.c.
41 void *memcpy(void *dest
, const void *src
, size_t count
)
51 /* ...and two syscalls. This is x86-specific. */
52 static inline long x86_syscall3(long nr
, long a0
, long a1
, long a2
)
56 asm volatile ("syscall" : "=a" (ret
) : "a" (nr
),
57 "D" (a0
), "S" (a1
), "d" (a2
) :
58 "cc", "memory", "rcx",
59 "r8", "r9", "r10", "r11" );
61 asm volatile ("int $0x80" : "=a" (ret
) : "a" (nr
),
62 "b" (a0
), "c" (a1
), "d" (a2
) :
68 static inline long linux_write(int fd
, const void *data
, size_t len
)
70 return x86_syscall3(__NR_write
, fd
, (long)data
, (long)len
);
73 static inline void linux_exit(int code
)
75 x86_syscall3(__NR_exit
, code
, 0, 0);
78 void to_base10(char *lastdig
, time_t n
)
81 *lastdig
= (n
% 10) + '0';
87 void c_main(void **stack
)
90 long argc
= (long)*stack
;
93 /* Now we're pointing at the environment. Skip it. */
98 /* Now we're pointing at auxv. Initialize the vDSO parser. */
99 vdso_init_from_auxv((void *)stack
);
101 /* Find gettimeofday. */
102 typedef long (*gtod_t
)(struct timeval
*tv
, struct timezone
*tz
);
103 gtod_t gtod
= (gtod_t
)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
109 long ret
= gtod(&tv
, 0);
112 char buf
[] = "The time is .000000\n";
113 to_base10(buf
+ 31, tv
.tv_sec
);
114 to_base10(buf
+ 38, tv
.tv_usec
);
115 linux_write(1, buf
, sizeof(buf
) - 1);
124 * This is the real entry point. It passes the initial stack into
130 ".type _start,@function\n"