File: bug156404-amd64.c

package info (click to toggle)
valgrind 1%3A3.12.0~svn20160714-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 120,428 kB
  • ctags: 70,855
  • sloc: ansic: 674,645; exp: 26,134; xml: 21,574; asm: 7,570; cpp: 7,567; makefile: 7,380; sh: 6,188; perl: 5,855; haskell: 195
file content (81 lines) | stat: -rw-r--r-- 1,843 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

/* Check that the main thread's stack, on Linux, is automatically
   extended down to the lowest valid address when a syscall happens.
   Failure to do so was causing this test to fail on Linux amd64. */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include <sys/syscall.h>
#include <unistd.h>

#define VG_STRINGIFZ(__str)  #__str
#define VG_STRINGIFY(__str)  VG_STRINGIFZ(__str)

#if defined(VGO_linux) || defined(VGO_darwin)
#define __NR_READLINK        VG_STRINGIFY(__NR_readlink)

extern long my_readlink ( const char* path );
asm(
".text\n"
".globl my_readlink\n"
"my_readlink:\n"
"\tsubq    $0x1008,%rsp\n"
"\tmovq    %rdi,%rdi\n"              // path is in rdi
"\tmovq    %rsp,%rsi\n"              // &buf[0] -> rsi
"\tmovl    $0x1000,%edx\n"           // sizeof(buf) in rdx
"\tmovl    $"__NR_READLINK",%eax\n"  // syscall number
"\tsyscall\n"
"\taddq    $0x1008,%rsp\n"
"\tret\n"
".previous\n"
);

#elif defined(VGO_solaris)
#define __NR_READLINKAT      VG_STRINGIFY(SYS_readlinkat)

extern long my_readlink ( const char* path );
asm(
".text\n"
".globl my_readlink\n"
"my_readlink:\n"
"\tsubq    $0x1008,%rsp\n"
"\tmovq    %rdi,%rsi\n"
"\txorq    %rdi,%rdi\n"
"\tmovq    %rsp,%rdx\n"
"\tmovq    $0x1000,%r10\n"
"\tmovl    $"__NR_READLINKAT",%eax\n"
"\tsyscall\n"
"\taddq    $0x1008,%rsp\n"
"\tret\n"
".previous\n"
);

#else
#error "Unknown OS"
#endif

long recurse ( const char* path, long count )
{
   if (count <= 0) {
      return my_readlink(path);
   } else { 
      long r = recurse(path, count-1);
      return r;
   }
}

int main ( void )
{
   long i, r;
   for (i = 0; i < 2000; i++) {
      printf("depth %ld: ", i );
      r = recurse( "/proc/self", i );
      if (r > 1) r = 1; /* to make the output repeatable */
      assert(r >= 1);
      printf("r = %ld\n", r);
   }
   return 0;
}