Chez Scheme: repair to W^X mode

Fix single-segment flipping to accomodate write regions that span
segments.
This commit is contained in:
Matthew Flatt 2021-05-01 08:58:47 -06:00
parent 8ea5b58393
commit 1f0223fef1
11 changed files with 64 additions and 54 deletions

View File

@ -264,7 +264,7 @@ ptr S_find_more_gc_room(thread_gc *tgc, ISPC s, IGEN g, iptr n, ptr old) {
/* Ensure allocated code segments are writable. The caller should
already have bracketed the writes with calls to start and stop
so there is no need for a stop here. */
S_thread_start_code_write(tgc->tc, 0, 1, NULL);
S_thread_start_code_write(tgc->tc, 0, 1, NULL, 0);
}
#endif

View File

@ -395,8 +395,8 @@ extern uptr S_maxmembytes PROTO((void));
extern void S_resetmaxmembytes PROTO((void));
extern void S_adjustmembytes PROTO((iptr amt));
extern void S_move_to_chunk_list PROTO((chunkinfo *chunk, chunkinfo **pchunk_list));
extern void S_thread_start_code_write PROTO((ptr tc, IGEN maxg, IBOOL current, void *hint));
extern void S_thread_end_code_write PROTO((ptr tc, IGEN maxg, IBOOL current, void *hint));
extern void S_thread_start_code_write PROTO((ptr tc, IGEN maxg, IBOOL current, void *hint, uptr hint_len));
extern void S_thread_end_code_write PROTO((ptr tc, IGEN maxg, IBOOL current, void *hint, uptr hint_len));
/* stats.c */
extern void S_stats_init PROTO((void));

View File

@ -508,7 +508,7 @@ static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externa
Scompact_heap();
}
S_thread_start_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL);
S_thread_start_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0);
switch (ty) {
case fasl_type_gzip:
@ -557,7 +557,7 @@ static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externa
return (ptr)0;
}
S_flush_instruction_cache(tc);
S_thread_end_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL);
S_thread_end_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0);
return x;
} else {
uf_skipbytes(uf, size);
@ -569,7 +569,7 @@ static ptr bv_fasl_entry(ptr tc, ptr bv, int ty, uptr offset, uptr len, unbufFas
ptr x; ptr strbuf = S_G.null_string;
struct faslFileObj ffo;
S_thread_start_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL);
S_thread_start_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0);
if (ty == fasl_type_vfasl) {
x = S_vfasl(bv, NULL, offset, len);
@ -585,7 +585,7 @@ static ptr bv_fasl_entry(ptr tc, ptr bv, int ty, uptr offset, uptr len, unbufFas
}
S_flush_instruction_cache(tc);
S_thread_end_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL);
S_thread_end_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0);
return x;
}

View File

@ -870,7 +870,7 @@ ptr GCENTRY(ptr tc, ptr count_roots_ls) {
GET_REAL_TIME(astart);
S_thread_start_code_write(tc, MAX_TG, 0, NULL);
S_thread_start_code_write(tc, MAX_TG, 0, NULL, 0);
/* flush instruction cache: effectively clear_code_mod but safer */
for (ls = S_threads; ls != Snil; ls = Scdr(ls)) {
@ -1679,7 +1679,7 @@ ptr GCENTRY(ptr tc, ptr count_roots_ls) {
if (MAX_CG >= S_G.min_free_gen) S_free_chunks();
S_flush_instruction_cache(tc);
S_thread_end_code_write(tc, MAX_TG, 0, NULL);
S_thread_end_code_write(tc, MAX_TG, 0, NULL, 0);
#ifndef NO_DIRTY_NEWSPACE_POINTERS
/* mark dirty those newspace cards to which we've added wrong-way pointers */
@ -2951,7 +2951,7 @@ static s_thread_rv_t start_sweeper(void *_sweeper) {
gc_sweeper *sweeper = _sweeper;
#if !defined(WRITE_XOR_EXECUTE_CODE)
S_thread_start_code_write((ptr)0, static_generation, 0, NULL); /* never ended */
S_thread_start_code_write((ptr)0, static_generation, 0, NULL, 0); /* never ended */
#endif
(void)s_thread_mutex_lock(&sweep_mutex);

View File

@ -228,7 +228,7 @@ static void s_instantiate_code_object() {
cookie = S_get_scheme_arg(tc, 2);
proc = S_get_scheme_arg(tc, 3);
S_thread_start_code_write(tc, 0, 0, NULL);
S_thread_start_code_write(tc, 0, 0, NULL, 0);
new = S_code(tc, CODETYPE(old), CODELEN(old));
@ -280,7 +280,7 @@ static void s_instantiate_code_object() {
}
S_flush_instruction_cache(tc);
S_thread_end_code_write(tc, 0, 0, NULL);
S_thread_end_code_write(tc, 0, 0, NULL, 0);
AC0(tc) = new;
}
@ -289,7 +289,7 @@ static void s_link_code_object(co, objs) ptr co, objs; {
ptr t, tc = get_thread_context();
uptr a, m, n;
S_thread_start_code_write(tc, 0, 0, NULL);
S_thread_start_code_write(tc, 0, 0, NULL, 0);
t = CODERELOC(co);
m = RELOCSIZE(t);
a = 0;
@ -308,7 +308,7 @@ static void s_link_code_object(co, objs) ptr co, objs; {
S_set_code_obj("gc", RELOC_TYPE(entry), co, a, Scar(objs), item_off);
objs = Scdr(objs);
}
S_thread_end_code_write(tc, 0, 0, NULL);
S_thread_end_code_write(tc, 0, 0, NULL, 0);
}
static INT s_check_heap_enabledp(void) {

View File

@ -879,9 +879,9 @@ static ptr s_set_code_byte(p, n, x) ptr p, n, x; {
ptr tc = get_thread_context();
a = (I8 *)TO_VOIDP((uptr)p + UNFIX(n));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I8));
*a = (I8)UNFIX(x);
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I8));
return Svoid;
}
@ -891,9 +891,9 @@ static ptr s_set_code_word(p, n, x) ptr p, n, x; {
ptr tc = get_thread_context();
a = (I16 *)TO_VOIDP((uptr)p + UNFIX(n));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I16));
*a = (I16)UNFIX(x);
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I16));
return Svoid;
}
@ -903,9 +903,9 @@ static ptr s_set_code_long(p, n, x) ptr p, n, x; {
ptr tc = get_thread_context();
a = (I32 *)TO_VOIDP((uptr)p + UNFIX(n));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I32));
*a = (I32)(Sfixnump(x) ? UNFIX(x) : Sinteger_value(x));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I32));
return Svoid;
}
@ -915,9 +915,9 @@ static void s_set_code_long2(p, n, h, l) ptr p, n, h, l; {
ptr tc = get_thread_context();
a = (I32 *)TO_VOIDP((uptr)p + UNFIX(n));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I32));
*a = (I32)((UNFIX(h) << 16) + UNFIX(l));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I32));
}
static ptr s_set_code_quad(p, n, x) ptr p, n, x; {
@ -925,21 +925,18 @@ static ptr s_set_code_quad(p, n, x) ptr p, n, x; {
ptr tc = get_thread_context();
a = (I64 *)TO_VOIDP((uptr)p + UNFIX(n));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I64));
*a = Sfixnump(x) ? UNFIX(x) : S_int64_value("\\#set-code-quad!", x);
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(a), sizeof(I64));
return Svoid;
}
static ptr s_set_reloc(p, n, e) ptr p, n, e; {
iptr *a;
ptr tc = get_thread_context();
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(p)));
a = (iptr *)(&RELOCIT(CODERELOC(p), UNFIX(n)));
*a = Sfixnump(e) ? UNFIX(e) : Sinteger_value(e);
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(p)));
return e;
}
@ -954,7 +951,7 @@ static ptr s_make_code(flags, free, name, arity_mark, n, info, pinfos)
ptr co;
ptr tc = get_thread_context();
S_thread_start_code_write(tc, 0, 0, NULL);
S_thread_start_code_write(tc, 0, 0, NULL, 0);
co = S_code(tc, type_code | (flags << code_flags_offset), n);
CODEFREE(co) = free;
@ -966,7 +963,7 @@ static ptr s_make_code(flags, free, name, arity_mark, n, info, pinfos)
S_G.profile_counters = Scons(S_weak_cons(co, pinfos), S_G.profile_counters);
}
S_thread_end_code_write(tc, 0, 0, NULL);
S_thread_end_code_write(tc, 0, 0, NULL, 0);
return co;
}
@ -974,10 +971,10 @@ static ptr s_make_code(flags, free, name, arity_mark, n, info, pinfos)
static ptr s_make_reloc_table(codeobj, n) ptr codeobj, n; {
ptr tc = get_thread_context();
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(codeobj)));
S_thread_start_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(codeobj)), sizeof(ptr));
CODERELOC(codeobj) = S_relocation_table(UNFIX(n));
RELOCCODE(CODERELOC(codeobj)) = codeobj;
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(codeobj)));
S_thread_end_code_write(tc, 0, 0, TO_VOIDP(&CODERELOC(codeobj)), sizeof(ptr));
return Svoid;
}

View File

@ -108,7 +108,7 @@ static void main_init() {
VIRTREG(tc, i) = FIX(0);
}
S_thread_start_code_write(tc, 0, 0, NULL);
S_thread_start_code_write(tc, 0, 0, NULL, 0);
p = S_code(tc, type_code, size_rp_header);
CODERELOC(p) = S_relocation_table(0);
CODENAME(p) = Sfalse;
@ -122,7 +122,7 @@ static void main_init() {
(uptr)TO_PTR(&RPHEADERTOPLINK(TO_PTR(&CODEIT(p, 0)))) - (uptr)p;
S_protect(&S_G.dummy_code_object);
S_G.dummy_code_object = p;
S_thread_end_code_write(tc, 0, 0, NULL);
S_thread_end_code_write(tc, 0, 0, NULL, 0);
S_protect(&S_G.error_invoke_code_object);
S_G.error_invoke_code_object = Snil;

View File

@ -394,7 +394,7 @@ static void do_error(type, who, s, args) iptr type; const char *who, *s; ptr arg
#endif /* PTHREADS */
/* in case error is during fasl read: */
S_thread_end_code_write(tc, static_generation, 0, NULL);
S_thread_end_code_write(tc, static_generation, 0, NULL, 0);
TRAP(tc) = (ptr)1;
AC0(tc) = (ptr)1;
@ -801,7 +801,7 @@ void S_schsig_init() {
S_protect(&S_G.collect_request_pending_id);
S_G.collect_request_pending_id = S_intern((const unsigned char *)"$collect-request-pending");
S_thread_start_code_write(tc, 0, 0, NULL);
S_thread_start_code_write(tc, 0, 0, NULL, 0);
p = S_code(tc, type_code | (code_flag_continuation << code_flags_offset), 0);
CODERELOC(p) = S_relocation_table(0);
CODENAME(p) = Sfalse;
@ -809,7 +809,7 @@ void S_schsig_init() {
CODEFREE(p) = 0;
CODEINFO(p) = Sfalse;
CODEPINFOS(p) = Snil;
S_thread_end_code_write(tc, 0, 0, NULL);
S_thread_end_code_write(tc, 0, 0, NULL, 0);
S_set_symbol_value(S_G.null_continuation_id,
S_mkcontinuation(space_new,

View File

@ -46,7 +46,7 @@ static seginfo *sort_seginfo PROTO((seginfo *si, uptr n));
static seginfo *merge_seginfo PROTO((seginfo *si1, seginfo *si2));
#if defined(WRITE_XOR_EXECUTE_CODE)
static void enable_code_write PROTO((ptr tc, IGEN maxg, IBOOL on, IBOOL current, ptr hint));
static void enable_code_write PROTO((ptr tc, IGEN maxg, IBOOL on, IBOOL current, ptr hint, uptr hint_len));
#endif
void S_segment_init() {
@ -586,17 +586,19 @@ static void contract_segment_table(uptr base, uptr end) {
being flipped while a thread is executing code off of it.
*/
void S_thread_start_code_write(WX_UNUSED ptr tc, WX_UNUSED IGEN maxg, WX_UNUSED IBOOL current, WX_UNUSED void *hint) {
void S_thread_start_code_write(WX_UNUSED ptr tc, WX_UNUSED IGEN maxg, WX_UNUSED IBOOL current,
WX_UNUSED void *hint, WX_UNUSED uptr hint_len) {
#if defined(WRITE_XOR_EXECUTE_CODE)
enable_code_write(tc, maxg, 1, current, hint);
enable_code_write(tc, maxg, 1, current, hint, hint_len);
#else
S_ENABLE_CODE_WRITE(1);
#endif
}
void S_thread_end_code_write(WX_UNUSED ptr tc, WX_UNUSED IGEN maxg, WX_UNUSED IBOOL current, WX_UNUSED void *hint) {
void S_thread_end_code_write(WX_UNUSED ptr tc, WX_UNUSED IGEN maxg, WX_UNUSED IBOOL current,
WX_UNUSED void *hint, WX_UNUSED uptr hint_len) {
#if defined(WRITE_XOR_EXECUTE_CODE)
enable_code_write(tc, maxg, 0, current, hint);
enable_code_write(tc, maxg, 0, current, hint, hint_len);
#else
S_ENABLE_CODE_WRITE(0);
#endif
@ -623,7 +625,7 @@ static IBOOL is_unused_seg(chunkinfo *chunk, seginfo *si) {
}
# endif
static void enable_code_write(ptr tc, IGEN maxg, IBOOL on, IBOOL current, void *hint) {
static void enable_code_write(ptr tc, IGEN maxg, IBOOL on, IBOOL current, void *hint, uptr hint_len) {
thread_gc *tgc;
chunkinfo *chunk;
seginfo si, *sip;
@ -633,9 +635,14 @@ static void enable_code_write(ptr tc, IGEN maxg, IBOOL on, IBOOL current, void *
/* Flip only the segment hinted at by the caller. */
if (maxg == 0 && hint != NULL) {
addr = TO_VOIDP((char*)hint - ((uptr)hint % bytes_per_segment));
if (mprotect(addr, bytes_per_segment, flags) != 0) {
S_error_abort("bad hint to enable_code_write");
uptr seg, start_seg, end_seg;
start_seg = addr_get_segment(TO_PTR(hint));
end_seg = addr_get_segment((uptr)TO_PTR(hint) + hint_len - 1);
for (seg = start_seg; seg <= end_seg; seg++) {
addr = TO_VOIDP(build_ptr(seg, 0));
if (mprotect(addr, bytes_per_segment, flags) != 0) {
S_error_abort("bad hint to enable_code_write");
}
}
return;
}

View File

@ -257,7 +257,7 @@ static IBOOL destroy_thread(tc) ptr tc; {
S_scan_dirty((ptr *)EAP(tc), (ptr *)REAL_EAP(tc));
/* close off thread-local allocation */
S_thread_start_code_write(tc, static_generation, 0, NULL);
S_thread_start_code_write(tc, static_generation, 0, NULL, 0);
{
ISPC s; IGEN g;
thread_gc *tgc = THREAD_GC(tc);
@ -266,7 +266,7 @@ static IBOOL destroy_thread(tc) ptr tc; {
if (tgc->next_loc[g][s])
S_close_off_thread_local_segment(tc, s, g);
}
S_thread_end_code_write(tc, static_generation, 0, NULL);
S_thread_end_code_write(tc, static_generation, 0, NULL, 0);
alloc_mutex_release();

View File

@ -248,12 +248,10 @@ typedef int tputsputcchar;
/* for both iPhone and iPhoneSimulator */
#if defined(TARGET_OS_IPHONE)
# define SYSTEM(s) ((void)s, -1)
# define S_PROT_CODE (PROT_WRITE | PROT_READ)
# define WRITE_XOR_EXECUTE_CODE
# define WX_UNUSED
#endif
#if defined(__arm64__)
# if !defined(TARGET_OS_IPHONE)
# if !defined(WRITE_XOR_EXECUTE_CODE)
# define S_MAP_CODE MAP_JIT
# define S_ENABLE_CODE_WRITE(on) pthread_jit_write_protect_np(!(on))
# endif
@ -419,7 +417,11 @@ typedef char tputsputcchar;
#endif
#ifndef S_PROT_CODE
# define S_PROT_CODE (PROT_READ | PROT_WRITE | PROT_EXEC)
# ifdef WRITE_XOR_EXECUTE_CODE
# define S_PROT_CODE (PROT_WRITE | PROT_READ)
# else
# define S_PROT_CODE (PROT_READ | PROT_WRITE | PROT_EXEC)
# endif
#endif
#ifndef S_MAP_CODE
# define S_MAP_CODE 0
@ -428,10 +430,14 @@ typedef char tputsputcchar;
# define S_ENABLE_CODE_WRITE(on) do { } while (0)
#endif
/* Signals that an argument is unused when W&X memory pages are
supported. Relevant in relation to WRITE_XOR_EXECUTE_CODE. */
/* WX_UNUSED indicates that an argument is used only for
WRITE_XOR_EXECUTE_CODE mode */
#ifndef WX_UNUSED
# define WX_UNUSED UNUSED
# ifdef WRITE_XOR_EXECUTE_CODE
# define WX_UNUSED
# else
# define WX_UNUSED UNUSED
# endif
#endif
#ifdef PTHREADS