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