Home | History | Annotate | Download | only in amd64
      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