Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.6-rc1 111 lines 2.5 kB view raw
1/* 2 * vdso_test.c: Sample code to test parse_vdso.c on x86_64 3 * Copyright (c) 2011 Andy Lutomirski 4 * Subject to the GNU General Public License, version 2 5 * 6 * You can amuse yourself by compiling with: 7 * gcc -std=gnu99 -nostdlib 8 * -Os -fno-asynchronous-unwind-tables -flto 9 * vdso_test.c parse_vdso.c -o vdso_test 10 * to generate a small binary with no dependencies at all. 11 */ 12 13#include <sys/syscall.h> 14#include <sys/time.h> 15#include <unistd.h> 16#include <stdint.h> 17 18extern void *vdso_sym(const char *version, const char *name); 19extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); 20extern void vdso_init_from_auxv(void *auxv); 21 22/* We need a libc functions... */ 23int strcmp(const char *a, const char *b) 24{ 25 /* This implementation is buggy: it never returns -1. */ 26 while (*a || *b) { 27 if (*a != *b) 28 return 1; 29 if (*a == 0 || *b == 0) 30 return 1; 31 a++; 32 b++; 33 } 34 35 return 0; 36} 37 38/* ...and two syscalls. This is x86_64-specific. */ 39static inline long linux_write(int fd, const void *data, size_t len) 40{ 41 42 long ret; 43 asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write), 44 "D" (fd), "S" (data), "d" (len) : 45 "cc", "memory", "rcx", 46 "r8", "r9", "r10", "r11" ); 47 return ret; 48} 49 50static inline void linux_exit(int code) 51{ 52 asm volatile ("syscall" : : "a" (__NR_exit), "D" (code)); 53} 54 55void to_base10(char *lastdig, uint64_t n) 56{ 57 while (n) { 58 *lastdig = (n % 10) + '0'; 59 n /= 10; 60 lastdig--; 61 } 62} 63 64__attribute__((externally_visible)) void c_main(void **stack) 65{ 66 /* Parse the stack */ 67 long argc = (long)*stack; 68 stack += argc + 2; 69 70 /* Now we're pointing at the environment. Skip it. */ 71 while(*stack) 72 stack++; 73 stack++; 74 75 /* Now we're pointing at auxv. Initialize the vDSO parser. */ 76 vdso_init_from_auxv((void *)stack); 77 78 /* Find gettimeofday. */ 79 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); 80 gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday"); 81 82 if (!gtod) 83 linux_exit(1); 84 85 struct timeval tv; 86 long ret = gtod(&tv, 0); 87 88 if (ret == 0) { 89 char buf[] = "The time is .000000\n"; 90 to_base10(buf + 31, tv.tv_sec); 91 to_base10(buf + 38, tv.tv_usec); 92 linux_write(1, buf, sizeof(buf) - 1); 93 } else { 94 linux_exit(ret); 95 } 96 97 linux_exit(0); 98} 99 100/* 101 * This is the real entry point. It passes the initial stack into 102 * the C entry point. 103 */ 104asm ( 105 ".text\n" 106 ".global _start\n" 107 ".type _start,@function\n" 108 "_start:\n\t" 109 "mov %rsp,%rdi\n\t" 110 "jmp c_main" 111 );