~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * vdso_test.c: Sample code to test parse_vdso.c on x86
  4  * Copyright (c) 2011-2014 Andy Lutomirski
  5  *
  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.
 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... */
 22 int 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  */
 41 void *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. */
 52 static 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 #else
 61         asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),
 62                       "b" (a0), "c" (a1), "d" (a2) :
 63                       "cc", "memory" );
 64 #endif
 65         return ret;
 66 }
 67 
 68 static 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 
 73 static inline void linux_exit(int code)
 74 {
 75         x86_syscall3(__NR_exit, code, 0, 0);
 76 }
 77 
 78 void to_base10(char *lastdig, time_t n)
 79 {
 80         while (n) {
 81                 *lastdig = (n % 10) + '';
 82                 n /= 10;
 83                 lastdig--;
 84         }
 85 }
 86 
 87 void 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 into
125  * the C entry point.
126  */
127 asm (
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         "jmp c_main"
135 #else
136         "push %esp\n\t"
137         "call c_main\n\t"
138         "int $3"
139 #endif
140         );
141 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php