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
19 extern long my_readlink ( const char* path );
20 asm(
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
recurse(const char * path,long count)35 long 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
main(void)45 int 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