brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 6449158 Raw
143 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * vdso_test.c: Sample code to test parse_vdso.c on x864 * Copyright (c) 2011-2014 Andy Lutomirski5 *6 * You can amuse yourself by compiling with:7 * gcc -std=gnu99 -nostdlib8 *     -Os -fno-asynchronous-unwind-tables -flto -lgcc_s9 *      vdso_standalone_test_x86.c parse_vdso.c10 * to generate a small binary.  On x86_64, you can omit -lgcc_s11 * if you want the binary to be completely standalone.12 */13 14#include <sys/syscall.h>15#include <sys/time.h>16#include <unistd.h>17#include <stdint.h>18 19#include "parse_vdso.h"20 21/* We need some libc functions... */22int strcmp(const char *a, const char *b)23{24	/* This implementation is buggy: it never returns -1. */25	while (*a || *b) {26		if (*a != *b)27			return 1;28		if (*a == 0 || *b == 0)29			return 1;30		a++;31		b++;32	}33 34	return 0;35}36 37/*38 * The clang build needs this, although gcc does not.39 * Stolen from lib/string.c.40 */41void *memcpy(void *dest, const void *src, size_t count)42{43	char *tmp = dest;44	const char *s = src;45 46	while (count--)47		*tmp++ = *s++;48	return dest;49}50 51/* ...and two syscalls.  This is x86-specific. */52static inline long x86_syscall3(long nr, long a0, long a1, long a2)53{54	long ret;55#ifdef __x86_64__56	asm volatile ("syscall" : "=a" (ret) : "a" (nr),57		      "D" (a0), "S" (a1), "d" (a2) :58		      "cc", "memory", "rcx",59		      "r8", "r9", "r10", "r11" );60#else61	asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),62		      "b" (a0), "c" (a1), "d" (a2) :63		      "cc", "memory" );64#endif65	return ret;66}67 68static inline long linux_write(int fd, const void *data, size_t len)69{70	return x86_syscall3(__NR_write, fd, (long)data, (long)len);71}72 73static inline void linux_exit(int code)74{75	x86_syscall3(__NR_exit, code, 0, 0);76}77 78void to_base10(char *lastdig, time_t n)79{80	while (n) {81		*lastdig = (n % 10) + '0';82		n /= 10;83		lastdig--;84	}85}86 87void c_main(void **stack)88{89	/* Parse the stack */90	long argc = (long)*stack;91	stack += argc + 2;92 93	/* Now we're pointing at the environment.  Skip it. */94	while(*stack)95		stack++;96	stack++;97 98	/* Now we're pointing at auxv.  Initialize the vDSO parser. */99	vdso_init_from_auxv((void *)stack);100 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");104 105	if (!gtod)106		linux_exit(1);107 108	struct timeval tv;109	long ret = gtod(&tv, 0);110 111	if (ret == 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);116	} else {117		linux_exit(ret);118	}119 120	linux_exit(0);121}122 123/*124 * This is the real entry point.  It passes the initial stack into125 * the C entry point.126 */127asm (128	".text\n"129	".global _start\n"130	".type _start,@function\n"131	"_start:\n\t"132#ifdef __x86_64__133	"mov %rsp,%rdi\n\t"134	"and $-16,%rsp\n\t"135	"sub $8,%rsp\n\t"136	"jmp c_main"137#else138	"push %esp\n\t"139	"call c_main\n\t"140	"int $3"141#endif142	);143