Skip to content

Commit 16d2658

Browse files
committed
---
yaml --- r: 6870 b: refs/heads/master c: 96d7f83 h: refs/heads/master v: v3
1 parent cd7da11 commit 16d2658

File tree

5 files changed

+81
-28
lines changed

5 files changed

+81
-28
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: b957916e06ea70b70aef1e404b089292aad42d7b
2+
refs/heads/master: 96d7f83eb0c87453d57e5a71959d0d74a9e500ca

trunk/src/comp/middle/ty.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,8 @@ fn type_is_signed(cx: ctxt, ty: t) -> bool {
11581158
}
11591159
}
11601160

1161-
// Whether a type is Plain Old Data (i.e. can be safely memmoved).
1161+
// Whether a type is Plain Old Data -- meaning it does not contain pointers
1162+
// that the cycle collector might care about.
11621163
fn type_is_pod(cx: ctxt, ty: t) -> bool {
11631164
let result = true;
11641165
alt struct(cx, ty) {

trunk/src/rt/rust_task.cpp

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
// The amount of extra space at the end of each stack segment, available
1919
// to the rt, compiler and dynamic linker for running small functions
2020
// FIXME: We want this to be 128 but need to slim the red zone calls down
21-
#define RZ_LINUX_32 1024*20
22-
#define RZ_LINUX_64 1024*20
23-
#define RZ_MAC_32 1024*20
24-
#define RZ_MAC_64 1024*20
25-
#define RZ_WIN_32 1024*20
21+
#define RZ_LINUX_32 (1024*20)
22+
#define RZ_LINUX_64 (1024*20)
23+
#define RZ_MAC_32 (1024*20)
24+
#define RZ_MAC_64 (1024*20)
25+
#define RZ_WIN_32 (1024*20)
2626

2727
#ifdef __linux__
2828
#ifdef __i386__
@@ -49,6 +49,12 @@
4949
#endif
5050
#endif
5151

52+
// A value that goes at the end of the stack and must not be touched
53+
const uint8_t stack_canary[] = {0xAB, 0xCD, 0xAB, 0xCD,
54+
0xAB, 0xCD, 0xAB, 0xCD,
55+
0xAB, 0xCD, 0xAB, 0xCD,
56+
0xAB, 0xCD, 0xAB, 0xCD};
57+
5258
// Stack size
5359
size_t g_custom_min_stack_size = 0;
5460

@@ -95,7 +101,8 @@ config_valgrind_stack(stk_seg *stk) {
95101
// old stack segments, since the act of popping the stack previously
96102
// caused valgrind to consider the whole thing inaccessible.
97103
size_t sz = stk->end - (uintptr_t)&stk->data[0];
98-
VALGRIND_MAKE_MEM_UNDEFINED(stk->data, sz);
104+
VALGRIND_MAKE_MEM_UNDEFINED(stk->data + sizeof(stack_canary),
105+
sz - sizeof(stack_canary));
99106
#endif
100107
}
101108

@@ -110,6 +117,18 @@ free_stk(rust_task *task, stk_seg *stk) {
110117
task->free(stk);
111118
}
112119

120+
static void
121+
add_stack_canary(stk_seg *stk) {
122+
memcpy(stk->data, stack_canary, sizeof(stack_canary));
123+
assert(sizeof(stack_canary) == 16 && "Stack canary was not the expected size");
124+
}
125+
126+
static void
127+
check_stack_canary(stk_seg *stk) {
128+
assert(!memcmp(stk->data, stack_canary, sizeof(stack_canary))
129+
&& "Somebody killed the canary");
130+
}
131+
113132
static stk_seg*
114133
new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
115134
{
@@ -151,6 +170,7 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz)
151170
stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
152171
LOGPTR(task->sched, "new stk", (uintptr_t)stk);
153172
memset(stk, 0, sizeof(stk_seg));
173+
add_stack_canary(stk);
154174
stk->prev = NULL;
155175
stk->next = task->stk;
156176
stk->end = (uintptr_t) &stk->data[rust_stk_sz + RED_ZONE_SIZE];
@@ -165,6 +185,7 @@ static void
165185
del_stk(rust_task *task, stk_seg *stk)
166186
{
167187
assert(stk == task->stk && "Freeing stack segments out of order!");
188+
check_stack_canary(stk);
168189

169190
task->stk = stk->next;
170191

@@ -268,25 +289,18 @@ struct rust_closure_env {
268289
type_desc *td;
269290
};
270291

271-
// This runs on the Rust stack
272-
extern "C" CDECL
273-
void task_start_wrapper(spawn_args *a)
274-
{
275-
rust_task *task = a->task;
276-
int rval = 42;
292+
struct cleanup_args {
293+
spawn_args *spargs;
294+
bool failed;
295+
};
277296

278-
bool failed = false;
279-
try {
280-
a->f(&rval, a->a3, a->a4);
281-
} catch (rust_task *ex) {
282-
A(task->sched, ex == task,
283-
"Expected this task to be thrown for unwinding");
284-
failed = true;
285-
}
297+
void
298+
cleanup_task(cleanup_args *args) {
299+
spawn_args *a = args->spargs;
300+
bool failed = args->failed;
301+
rust_task *task = a->task;
286302

287-
// We're on the Rust stack and the cycle collector may recurse arbitrarily
288-
// deep, so switch to the C stack
289-
task->sched->c_context.call_shim_on_c_stack(task, (void*)cc::do_cc);
303+
cc::do_cc(task);
290304

291305
rust_closure_env* env = (rust_closure_env*)a->a3;
292306
if(env) {
@@ -313,6 +327,29 @@ void task_start_wrapper(spawn_args *a)
313327
A(task->sched, false, "Shouldn't happen");
314328
#endif
315329
}
330+
}
331+
332+
// This runs on the Rust stack
333+
extern "C" CDECL
334+
void task_start_wrapper(spawn_args *a)
335+
{
336+
rust_task *task = a->task;
337+
int rval = 42;
338+
339+
bool failed = false;
340+
try {
341+
a->f(&rval, a->a3, a->a4);
342+
} catch (rust_task *ex) {
343+
A(task->sched, ex == task,
344+
"Expected this task to be thrown for unwinding");
345+
failed = true;
346+
}
347+
348+
cleanup_args ca = {a, failed};
349+
350+
// The cleanup work needs lots of stack
351+
task->sched->c_context.call_shim_on_c_stack(&ca, (void*)cleanup_task);
352+
316353
task->ctx.next->swap(task->ctx);
317354
}
318355

@@ -768,6 +805,11 @@ rust_task::on_rust_stack() {
768805
return sp_in_stk_seg(get_sp(), stk);
769806
}
770807

808+
void
809+
rust_task::check_stack_canary() {
810+
::check_stack_canary(stk);
811+
}
812+
771813
//
772814
// Local Variables:
773815
// mode: C++

trunk/src/rt/rust_task.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ rust_task : public kernel_owned<rust_task>, rust_cond
203203
void record_stack_limit();
204204
void reset_stack_limit();
205205
bool on_rust_stack();
206+
void check_stack_canary();
206207
};
207208

208209
//

trunk/src/rt/rust_upcall.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ check_stack_alignment() __attribute__ ((aligned (16)));
2727
static void check_stack_alignment() { }
2828
#endif
2929

30+
static inline void
31+
do_sanity_check(rust_task *task) {
32+
check_stack_alignment();
33+
task->check_stack_canary();
34+
}
35+
3036
#define UPCALL_SWITCH_STACK(A, F) call_upcall_on_c_stack((void*)A, (void*)F)
3137

3238
inline void
3339
call_upcall_on_c_stack(void *args, void *fn_ptr) {
34-
check_stack_alignment();
3540
rust_task *task = rust_scheduler::get_task();
41+
do_sanity_check(task);
3642
rust_scheduler *sched = task->sched;
3743
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
44+
do_sanity_check(task);
3845
}
3946

4047
extern "C" void record_sp(void *limit);
@@ -48,8 +55,8 @@ extern "C" void record_sp(void *limit);
4855
*/
4956
extern "C" CDECL void
5057
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
51-
check_stack_alignment();
5258
rust_task *task = rust_scheduler::get_task();
59+
do_sanity_check(task);
5360

5461
// FIXME (1226) - The shim functions generated by rustc contain the
5562
// morestack prologue, so we need to let them know they have enough
@@ -65,6 +72,7 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
6572

6673
task = rust_scheduler::get_task();
6774
task->record_stack_limit();
75+
do_sanity_check(task);
6876
}
6977

7078
/**********************************************************************/
@@ -634,9 +642,10 @@ upcall_del_stack() {
634642
// needs to acquire the value of the stack pointer
635643
extern "C" CDECL void
636644
upcall_reset_stack_limit() {
637-
check_stack_alignment();
638645
rust_task *task = rust_scheduler::get_task();
646+
do_sanity_check(task);
639647
task->reset_stack_limit();
648+
do_sanity_check(task);
640649
}
641650

642651
//

0 commit comments

Comments
 (0)