Fix TCG relocation bug (exposed by fault after brcond op). Add FIXME for

annother potential bug.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3968 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2008-02-10 02:41:15 +00:00
parent 41df841110
commit 2ba1eeb62c
3 changed files with 24 additions and 21 deletions

View File

@ -97,6 +97,9 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
l = &s->labels[label_index]; l = &s->labels[label_index];
if (l->has_value) { if (l->has_value) {
/* FIXME: This is wrong. We can not resolve the relocation
immediately because the caller has not yet written the
initial value. */
patch_reloc(code_ptr, type, l->u.value + addend); patch_reloc(code_ptr, type, l->u.value + addend);
} else { } else {
/* add a new relocation entry */ /* add a new relocation entry */
@ -1649,8 +1652,7 @@ void dump_op_count(void)
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
int do_search_pc, long search_pc)
const uint8_t *searched_pc)
{ {
int opc, op_index, macro_op_index; int opc, op_index, macro_op_index;
const TCGOpDef *def; const TCGOpDef *def;
@ -1754,7 +1756,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
} }
#endif #endif
tcg_reg_alloc_bb_end(s); tcg_reg_alloc_bb_end(s);
if (do_search_pc) { if (search_pc >= 0) {
s->code_ptr += def->copy_size; s->code_ptr += def->copy_size;
args += def->nb_args; args += def->nb_args;
} else { } else {
@ -1771,13 +1773,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
} }
args += def->nb_args; args += def->nb_args;
next: ; next: ;
if (do_search_pc) { if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
if (searched_pc < s->code_ptr) { if (macro_op_index >= 0)
if (macro_op_index >= 0) return macro_op_index;
return macro_op_index; else
else return op_index;
return op_index;
}
} }
op_index++; op_index++;
#ifndef NDEBUG #ifndef NDEBUG
@ -1802,7 +1802,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
} }
#endif #endif
tcg_gen_code_common(s, gen_code_buf, 0, NULL); tcg_gen_code_common(s, gen_code_buf, -1);
/* flush instruction cache */ /* flush instruction cache */
flush_icache_range((unsigned long)gen_code_buf, flush_icache_range((unsigned long)gen_code_buf,
@ -1810,11 +1810,16 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
return s->code_ptr - gen_code_buf; return s->code_ptr - gen_code_buf;
} }
/* return the index of the micro operation such as the pc after is < static uint8_t *dummy_code_buf;
search_pc. Note: gen_code_buf is accessed during the operation, but
its content should not be modified. Return -1 if not found. */ /* Return the index of the micro operation such as the pc after is <
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, offset bytes from the start of the TB.
const uint8_t *searched_pc) We have to use a dummy code buffer here to avoid clobbering the
oringinal code. Because we terminate code generation part way through
we can end up with unresolved relocations. Return -1 if not found. */
int dyngen_code_search_pc(TCGContext *s, long offset)
{ {
return tcg_gen_code_common(s, gen_code_buf, 1, searched_pc); if (!dummy_code_buf)
dummy_code_buf = qemu_malloc(code_gen_max_block_size());
return tcg_gen_code_common(s, dummy_code_buf, offset);
} }

View File

@ -257,8 +257,7 @@ void tcg_context_init(TCGContext *s);
void tcg_func_start(TCGContext *s); void tcg_func_start(TCGContext *s);
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf); int dyngen_code(TCGContext *s, uint8_t *gen_code_buf);
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, int dyngen_code_search_pc(TCGContext *s, long offset);
const uint8_t *searched_pc);
void tcg_set_frame(TCGContext *s, int reg, void tcg_set_frame(TCGContext *s, int reg,
tcg_target_long start, tcg_target_long size); tcg_target_long start, tcg_target_long size);

View File

@ -187,8 +187,7 @@ int cpu_restore_state(TranslationBlock *tb,
s->tb_jmp_offset = NULL; s->tb_jmp_offset = NULL;
s->tb_next = tb->tb_next; s->tb_next = tb->tb_next;
#endif #endif
j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, j = dyngen_code_search_pc(s, searched_pc - tc_ptr);
(void *)searched_pc);
if (j < 0) if (j < 0)
return -1; return -1;
/* now find start of instruction before */ /* now find start of instruction before */