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: db0c51a380
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
db6b7d0c69
commit
0610067ec0
20
tcg/tcg.c
20
tcg/tcg.c
@ -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;
|
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) {
|
if (p < region.start_aligned) {
|
||||||
region_idx = 0;
|
region_idx = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -536,6 +546,7 @@ void tcg_tb_insert(TranslationBlock *tb)
|
|||||||
{
|
{
|
||||||
struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr);
|
struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr);
|
||||||
|
|
||||||
|
g_assert(rt != NULL);
|
||||||
qemu_mutex_lock(&rt->lock);
|
qemu_mutex_lock(&rt->lock);
|
||||||
g_tree_insert(rt->tree, &tb->tc, tb);
|
g_tree_insert(rt->tree, &tb->tc, tb);
|
||||||
qemu_mutex_unlock(&rt->lock);
|
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);
|
struct tcg_region_tree *rt = tc_ptr_to_region_tree(tb->tc.ptr);
|
||||||
|
|
||||||
|
g_assert(rt != NULL);
|
||||||
qemu_mutex_lock(&rt->lock);
|
qemu_mutex_lock(&rt->lock);
|
||||||
g_tree_remove(rt->tree, &tb->tc);
|
g_tree_remove(rt->tree, &tb->tc);
|
||||||
qemu_mutex_unlock(&rt->lock);
|
qemu_mutex_unlock(&rt->lock);
|
||||||
@ -561,6 +573,10 @@ TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr)
|
|||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
struct tb_tc s = { .ptr = (void *)tc_ptr };
|
struct tb_tc s = { .ptr = (void *)tc_ptr };
|
||||||
|
|
||||||
|
if (rt == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_mutex_lock(&rt->lock);
|
qemu_mutex_lock(&rt->lock);
|
||||||
tb = g_tree_lookup(rt->tree, &s);
|
tb = g_tree_lookup(rt->tree, &s);
|
||||||
qemu_mutex_unlock(&rt->lock);
|
qemu_mutex_unlock(&rt->lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user