1 #include "../../config.h"
14 #ifdef HAVE_GETPAGESIZE
17 #include "../../include/valgrind.h"
18 #include "../memcheck.h"
20 typedef unsigned long UWord
;
22 #define VG_ROUNDDN(p, a) ((Addr)(p) & ~((Addr)(a)-1))
23 #define VG_ROUNDUP(p, a) VG_ROUNDDN((p)+(a)-1, (a))
25 static pthread_t children
;
27 // If != 0, will test addr description does not explode with
28 // wrong stack registration.
29 static int shake_with_wrong_registration
= 0;
31 /* Do whatever to have the stack grown enough that
32 we can access below sp relatively safely */
33 static void grow_the_stack(void)
37 for (i
= 0; i
< sizeof(m
); i
++)
39 sprintf(m
, "do whatever %d", i
);
41 fprintf(stderr
, "something went wrong with %s\n", m
);
45 static void describe (char* what
, void* a
)
47 fprintf(stderr
, "describing %#" PRIxPTR
" %s\n", (uintptr_t) a
, what
);
48 sprintf(s
, "v.info location %#" PRIxPTR
, (uintptr_t) a
);
49 VALGRIND_MONITOR_COMMAND(s
);
52 static void bad_things_below_sp (void)
56 describe ("1500 bytes below a local var", p
-1500);
60 static volatile char *lowest_j
;
61 static jmp_buf goback
;
63 static void sigsegv_handler(int signr
)
68 static void bad_things_till_guard_page(void)
80 static int guess_pagesize(void)
82 #ifdef HAVE_GETPAGESIZE
83 const int pagesize
= getpagesize();
85 const int pagesize
= 4096; // let's say ?
90 static void describe_many(void)
92 const int pagesize
= guess_pagesize();
93 describe ("discovered address giving SEGV in thread stack",
95 describe ("byte just above highest guardpage byte",
96 (void*) VG_ROUNDUP(lowest_j
, pagesize
));
97 describe ("highest guardpage byte",
98 (void*) VG_ROUNDUP(lowest_j
, pagesize
)-1);
99 describe ("lowest guardpage byte",
100 (void*) VG_ROUNDDN(lowest_j
, pagesize
));
101 /* Cannot test the next byte, as we cannot predict how
102 this byte will be described. */
105 static void* child_fn_0 ( void* arg
)
108 bad_things_below_sp();
110 if (setjmp(goback
)) {
113 bad_things_till_guard_page();
115 if (shake_with_wrong_registration
) {
116 // Do whatever stupid things we could imagine
117 // with stack registration and see no explosion happens
118 // Note: this is executed only if an arg is given to the program.
121 const int pgsz
= guess_pagesize();
124 fprintf(stderr
, "\n\nShaking after unregistering stack\n");
125 // Assuming our first stack was automatically registered as nr 1
126 VALGRIND_STACK_DEREGISTER(1);
127 // Test with no stack registered
130 fprintf(stderr
, "\n\nShaking with small stack\n");
131 stackid
= VALGRIND_STACK_REGISTER((void*) VG_ROUNDDN(&stackid
, pgsz
),
132 (void*) VG_ROUNDUP(&stackid
, pgsz
));
134 VALGRIND_STACK_DEREGISTER(stackid
);
136 fprintf(stderr
, "\n\nShaking with huge stack\n");
137 stackid
= VALGRIND_STACK_REGISTER((void*) 0x0,
138 (void*) VG_ROUNDUP(&stackid
, 2<<20));
140 VALGRIND_STACK_DEREGISTER(stackid
);
148 int main(int argc
, const char** argv
)
153 shake_with_wrong_registration
= argc
> 1;
155 /* We will discover the thread guard page using SEGV.
156 So, prepare an handler. */
157 sa
.sa_handler
= sigsegv_handler
;
158 sigemptyset(&sa
.sa_mask
);
161 if (sigaction (SIGSEGV
, &sa
, NULL
) != 0)
165 bad_things_below_sp();
167 pthread_attr_t attrs
;
168 r
= pthread_attr_init(&attrs
);
171 # if defined(VGO_solaris)
172 /* Solaris needs to configure at least two page sizes to have
173 a visible stack guard page. One page size is deducted for
174 an implicit mmap red zone. */
175 r
= pthread_attr_setguardsize(&attrs
, 2 * guess_pagesize());
177 # endif /* VGO_solaris */
179 r
= pthread_create(&children
, &attrs
, child_fn_0
, NULL
);
182 r
= pthread_attr_destroy(&attrs
);
185 r
= pthread_join(children
, NULL
);