diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-01-27 21:47:05 -1000 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-03-06 11:45:21 -0800 |
commit | 0610067ec032eb7fab3c3f68ec3fea5adbf4ec40 (patch) | |
tree | cbd200b125346f708a7198e1ac073417ee7c41ce | |
parent | db6b7d0c6936cd209e3e8d95aea61ad29ceef5e6 (diff) |
tcg: Manage splitwx in tc_ptr_to_region_tree by hand
The use in tcg_tb_lookup is given a random pc that comes from the pc
of a signal handler. Do not assert that the pointer is already within
the code gen buffer at all, much less the writable mirror of it.
Fixes: db0c51a3803
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | tcg/tcg.c | 20 |
1 files changed, 18 insertions, 2 deletions
@@ -513,11 +513,21 @@ static void tcg_region_trees_init(void) } } -static struct tcg_region_tree *tc_ptr_to_region_tree(const void *cp) +static struct tcg_region_tree *tc_ptr_to_region_tree(const void *p) { - void *p = tcg_splitwx_to_rw(cp); size_t region_idx; + /* + * Like tcg_splitwx_to_rw, with no assert. The pc may come from + * a signal handler over which the caller has no control. + */ + if (!in_code_gen_buffer(p)) { + p -= tcg_splitwx_diff; + if (!in_code_gen_buffer(p)) { + return NULL; + } + } + if (p < region.start_aligned) { region_idx = 0; } else { @@ -536,6 +546,7 @@ void tcg_tb_insert(TranslationBlock *tb) { struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr); + g_assert(rt != NULL); qemu_mutex_lock(&rt->lock); g_tree_insert(rt->tree, &tb->tc, tb); qemu_mutex_unlock(&rt->lock); @@ -545,6 +556,7 @@ void tcg_tb_remove(TranslationBlock *tb) { struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr); + g_assert(rt != NULL); qemu_mutex_lock(&rt->lock); g_tree_remove(rt->tree, &tb->tc); qemu_mutex_unlock(&rt->lock); @@ -561,6 +573,10 @@ TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr) TranslationBlock *tb; struct tb_tc s = { .ptr = (void *)tc_ptr }; + if (rt == NULL) { + return NULL; + } + qemu_mutex_lock(&rt->lock); tb = g_tree_lookup(rt->tree, &s); qemu_mutex_unlock(&rt->lock); |