blob: d0c4ea039cd4c6d65d6cd8e40339b0397abb0151 [file] [log] [blame]
/* 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)
#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"
);
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;
}