tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / memcheck / tests / descr_belowsp.c
blob704c222917cc812f779a8c0842ab6bfe4cec81c6
1 #include "../../config.h"
3 #define _GNU_SOURCE
4 #include <stdio.h>
5 #include <pthread.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <assert.h>
11 #include <setjmp.h>
12 #include <signal.h>
13 #ifdef HAVE_GETPAGESIZE
14 #include <unistd.h>
15 #endif
16 #include "../../include/valgrind.h"
17 #include "../memcheck.h"
19 typedef unsigned long UWord;
20 typedef UWord Addr;
21 #define VG_ROUNDDN(p, a) ((Addr)(p) & ~((Addr)(a)-1))
22 #define VG_ROUNDUP(p, a) VG_ROUNDDN((p)+(a)-1, (a))
24 static pthread_t children;
26 // If != 0, will test addr description does not explode with
27 // wrong stack registration.
28 static int shake_with_wrong_registration = 0;
30 /* Do whatever to have the stack grown enough that
31 we can access below sp relatively safely */
32 static void grow_the_stack(void)
34 int i;
35 char m[5000];
36 for (i = 0; i < sizeof(m); i++)
37 m[i] = i;
38 sprintf(m, "do whatever %d", i);
39 if (strlen(m) > 1000)
40 fprintf(stderr, "something went wrong with %s\n", m);
43 static char s[1000];
44 static void describe (char* what, void* a)
46 fprintf(stderr, "describing %p %s\n", a, what);
47 sprintf(s, "v.info location %p", a);
48 VALGRIND_MONITOR_COMMAND(s);
51 static void bad_things_below_sp (void)
53 int i;
54 char *p = (char*)&i;
55 describe ("1500 bytes below a local var", p-1500);
59 static volatile char *lowest_j;
60 static jmp_buf goback;
62 static void sigsegv_handler(int signr)
64 longjmp(goback, 1);
67 static void bad_things_till_guard_page(void)
69 char j = 0;
70 char *p = &j;
72 for (;;) {
73 j = j + *p;
74 p = p - 400;
75 lowest_j = p;
79 static int guess_pagesize(void)
81 #ifdef HAVE_GETPAGESIZE
82 const int pagesize = getpagesize();
83 #else
84 const int pagesize = 4096; // let's say ?
85 #endif
86 return pagesize;
89 static void describe_many(void)
91 const int pagesize = guess_pagesize();
92 describe ("discovered address giving SEGV in thread stack",
93 (void*)lowest_j);
94 describe ("byte just above highest guardpage byte",
95 (void*) VG_ROUNDUP(lowest_j, pagesize));
96 describe ("highest guardpage byte",
97 (void*) VG_ROUNDUP(lowest_j, pagesize)-1);
98 describe ("lowest guardpage byte",
99 (void*) VG_ROUNDDN(lowest_j, pagesize));
100 /* Cannot test the next byte, as we cannot predict how
101 this byte will be described. */
104 static void* child_fn_0 ( void* arg )
106 grow_the_stack();
107 bad_things_below_sp();
109 if (setjmp(goback)) {
110 describe_many();
111 } else
112 bad_things_till_guard_page();
114 if (shake_with_wrong_registration) {
115 // Do whatever stupid things we could imagine
116 // with stack registration and see no explosion happens
117 // Note: this is executed only if an arg is given to the program.
120 const int pgsz = guess_pagesize();
121 int stackid;
123 fprintf(stderr, "\n\nShaking after unregistering stack\n");
124 // Assuming our first stack was automatically registered as nr 1
125 VALGRIND_STACK_DEREGISTER(1);
126 // Test with no stack registered
127 describe_many();
129 fprintf(stderr, "\n\nShaking with small stack\n");
130 stackid = VALGRIND_STACK_REGISTER((void*) VG_ROUNDDN(&stackid, pgsz),
131 (void*) VG_ROUNDUP(&stackid, pgsz));
132 describe_many();
133 VALGRIND_STACK_DEREGISTER(stackid);
135 fprintf(stderr, "\n\nShaking with huge stack\n");
136 stackid = VALGRIND_STACK_REGISTER((void*) 0x0,
137 (void*) VG_ROUNDUP(&stackid, 2<<20));
138 describe_many();
139 VALGRIND_STACK_DEREGISTER(stackid);
144 return NULL;
147 int main(int argc, const char** argv)
149 struct sigaction sa;
150 int r;
152 shake_with_wrong_registration = argc > 1;
154 /* We will discover the thread guard page using SEGV.
155 So, prepare an handler. */
156 sa.sa_handler = sigsegv_handler;
157 sigemptyset(&sa.sa_mask);
158 sa.sa_flags = 0;
160 if (sigaction (SIGSEGV, &sa, NULL) != 0)
161 perror("sigaction");
163 grow_the_stack();
164 bad_things_below_sp();
166 r = pthread_create(&children, NULL, child_fn_0, NULL);
167 assert(!r);
169 r = pthread_join(children, NULL);
170 assert(!r);
173 return 0;