1 #include "../../config.h"
13 #ifdef HAVE_GETPAGESIZE
16 #include "../../include/valgrind.h"
17 #include "../memcheck.h"
19 typedef unsigned long UWord
;
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)
36 for (i
= 0; i
< sizeof(m
); i
++)
38 sprintf(m
, "do whatever %d", i
);
40 fprintf(stderr
, "something went wrong with %s\n", m
);
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)
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
)
67 static void bad_things_till_guard_page(void)
79 static int guess_pagesize(void)
81 #ifdef HAVE_GETPAGESIZE
82 const int pagesize
= getpagesize();
84 const int pagesize
= 4096; // let's say ?
89 static void describe_many(void)
91 const int pagesize
= guess_pagesize();
92 describe ("discovered address giving SEGV in thread stack",
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
)
107 bad_things_below_sp();
109 if (setjmp(goback
)) {
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();
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
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
));
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));
139 VALGRIND_STACK_DEREGISTER(stackid
);
147 int main(int argc
, const char** argv
)
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
);
160 if (sigaction (SIGSEGV
, &sa
, NULL
) != 0)
164 bad_things_below_sp();
166 r
= pthread_create(&children
, NULL
, child_fn_0
, NULL
);
169 r
= pthread_join(children
, NULL
);