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 #if defined(VGO_linux) || defined(VGO_darwin) 18 #define __NR_READLINK VG_STRINGIFY(__NR_readlink) 19 20 extern long my_readlink ( const char* path ); 21 asm( 22 ".text\n" 23 ".globl my_readlink\n" 24 "my_readlink:\n" 25 "\tsubq $0x1008,%rsp\n" 26 "\tmovq %rdi,%rdi\n" // path is in rdi 27 "\tmovq %rsp,%rsi\n" // &buf[0] -> rsi 28 "\tmovl $0x1000,%edx\n" // sizeof(buf) in rdx 29 "\tmovl $"__NR_READLINK",%eax\n" // syscall number 30 "\tsyscall\n" 31 "\taddq $0x1008,%rsp\n" 32 "\tret\n" 33 ".previous\n" 34 ); 35 36 #elif defined(VGO_solaris) 37 #define __NR_READLINKAT VG_STRINGIFY(SYS_readlinkat) 38 39 extern long my_readlink ( const char* path ); 40 asm( 41 ".text\n" 42 ".globl my_readlink\n" 43 "my_readlink:\n" 44 "\tsubq $0x1008,%rsp\n" 45 "\tmovq %rdi,%rsi\n" 46 "\txorq %rdi,%rdi\n" 47 "\tmovq %rsp,%rdx\n" 48 "\tmovq $0x1000,%r10\n" 49 "\tmovl $"__NR_READLINKAT",%eax\n" 50 "\tsyscall\n" 51 "\taddq $0x1008,%rsp\n" 52 "\tret\n" 53 ".previous\n" 54 ); 55 56 #else 57 #error "Unknown OS" 58 #endif 59 60 long recurse ( const char* path, long count ) 61 { 62 if (count <= 0) { 63 return my_readlink(path); 64 } else { 65 long r = recurse(path, count-1); 66 return r; 67 } 68 } 69 70 int main ( void ) 71 { 72 long i, r; 73 for (i = 0; i < 2000; i++) { 74 printf("depth %ld: ", i ); 75 r = recurse( "/proc/self", i ); 76 if (r > 1) r = 1; /* to make the output repeatable */ 77 assert(r >= 1); 78 printf("r = %ld\n", r); 79 } 80 return 0; 81 } 82