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