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 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 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