1
2/* Check that the main thread's stack, on Linux, is automatically
3   extended down to the lowest valid address when a syscall happens.
4   Failure to do so was causing this test to fail on Linux amd64. */
5
6#include <unistd.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <assert.h>
10
11#include <sys/syscall.h>
12#include <unistd.h>
13
14#define VG_STRINGIFZ(__str)  #__str
15#define VG_STRINGIFY(__str)  VG_STRINGIFZ(__str)
16
17#define __NR_READLINK        VG_STRINGIFY(__NR_readlink)
18
19extern long my_readlink ( const char* path );
20asm(
21".text\n"
22".globl my_readlink\n"
23"my_readlink:\n"
24"\tsubq    $0x1008,%rsp\n"
25"\tmovq    %rdi,%rdi\n"              // path is in rdi
26"\tmovq    %rsp,%rsi\n"              // &buf[0] -> rsi
27"\tmovl    $0x1000,%edx\n"           // sizeof(buf) in rdx
28"\tmovl    $"__NR_READLINK",%eax\n"  // syscall number
29"\tsyscall\n"
30"\taddq    $0x1008,%rsp\n"
31"\tret\n"
32".previous\n"
33);
34
35long recurse ( const char* path, long count )
36{
37   if (count <= 0) {
38      return my_readlink(path);
39   } else {
40      long r = recurse(path, count-1);
41      return r;
42   }
43}
44
45int main ( void )
46{
47   long i, r;
48   for (i = 0; i < 2000; i++) {
49      printf("depth %ld: ", i );
50      r = recurse( "/proc/self", i );
51      if (r > 1) r = 1; /* to make the output repeatable */
52      assert(r >= 1);
53      printf("r = %ld\n", r);
54   }
55   return 0;
56}
57