Commit 2ba1eeb62c29d23238b95dc7e9ade3444b49f0a1
1 parent
41df8411
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
Showing
3 changed files
with
24 additions
and
21 deletions
tcg/tcg.c
| @@ -97,6 +97,9 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, | @@ -97,6 +97,9 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, | ||
| 97 | 97 | ||
| 98 | l = &s->labels[label_index]; | 98 | l = &s->labels[label_index]; |
| 99 | if (l->has_value) { | 99 | if (l->has_value) { |
| 100 | + /* FIXME: This is wrong. We can not resolve the relocation | ||
| 101 | + immediately because the caller has not yet written the | ||
| 102 | + initial value. */ | ||
| 100 | patch_reloc(code_ptr, type, l->u.value + addend); | 103 | patch_reloc(code_ptr, type, l->u.value + addend); |
| 101 | } else { | 104 | } else { |
| 102 | /* add a new relocation entry */ | 105 | /* add a new relocation entry */ |
| @@ -1649,8 +1652,7 @@ void dump_op_count(void) | @@ -1649,8 +1652,7 @@ void dump_op_count(void) | ||
| 1649 | 1652 | ||
| 1650 | 1653 | ||
| 1651 | static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | 1654 | static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, |
| 1652 | - int do_search_pc, | ||
| 1653 | - const uint8_t *searched_pc) | 1655 | + long search_pc) |
| 1654 | { | 1656 | { |
| 1655 | int opc, op_index, macro_op_index; | 1657 | int opc, op_index, macro_op_index; |
| 1656 | const TCGOpDef *def; | 1658 | const TCGOpDef *def; |
| @@ -1754,7 +1756,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | @@ -1754,7 +1756,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | ||
| 1754 | } | 1756 | } |
| 1755 | #endif | 1757 | #endif |
| 1756 | tcg_reg_alloc_bb_end(s); | 1758 | tcg_reg_alloc_bb_end(s); |
| 1757 | - if (do_search_pc) { | 1759 | + if (search_pc >= 0) { |
| 1758 | s->code_ptr += def->copy_size; | 1760 | s->code_ptr += def->copy_size; |
| 1759 | args += def->nb_args; | 1761 | args += def->nb_args; |
| 1760 | } else { | 1762 | } else { |
| @@ -1771,13 +1773,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | @@ -1771,13 +1773,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, | ||
| 1771 | } | 1773 | } |
| 1772 | args += def->nb_args; | 1774 | args += def->nb_args; |
| 1773 | next: ; | 1775 | next: ; |
| 1774 | - if (do_search_pc) { | ||
| 1775 | - if (searched_pc < s->code_ptr) { | ||
| 1776 | - if (macro_op_index >= 0) | ||
| 1777 | - return macro_op_index; | ||
| 1778 | - else | ||
| 1779 | - return op_index; | ||
| 1780 | - } | 1776 | + if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) { |
| 1777 | + if (macro_op_index >= 0) | ||
| 1778 | + return macro_op_index; | ||
| 1779 | + else | ||
| 1780 | + return op_index; | ||
| 1781 | } | 1781 | } |
| 1782 | op_index++; | 1782 | op_index++; |
| 1783 | #ifndef NDEBUG | 1783 | #ifndef NDEBUG |
| @@ -1802,7 +1802,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) | @@ -1802,7 +1802,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) | ||
| 1802 | } | 1802 | } |
| 1803 | #endif | 1803 | #endif |
| 1804 | 1804 | ||
| 1805 | - tcg_gen_code_common(s, gen_code_buf, 0, NULL); | 1805 | + tcg_gen_code_common(s, gen_code_buf, -1); |
| 1806 | 1806 | ||
| 1807 | /* flush instruction cache */ | 1807 | /* flush instruction cache */ |
| 1808 | flush_icache_range((unsigned long)gen_code_buf, | 1808 | flush_icache_range((unsigned long)gen_code_buf, |
| @@ -1810,11 +1810,16 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) | @@ -1810,11 +1810,16 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf) | ||
| 1810 | return s->code_ptr - gen_code_buf; | 1810 | return s->code_ptr - gen_code_buf; |
| 1811 | } | 1811 | } |
| 1812 | 1812 | ||
| 1813 | -/* return the index of the micro operation such as the pc after is < | ||
| 1814 | - search_pc. Note: gen_code_buf is accessed during the operation, but | ||
| 1815 | - its content should not be modified. Return -1 if not found. */ | ||
| 1816 | -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, | ||
| 1817 | - const uint8_t *searched_pc) | 1813 | +static uint8_t *dummy_code_buf; |
| 1814 | + | ||
| 1815 | +/* Return the index of the micro operation such as the pc after is < | ||
| 1816 | + offset bytes from the start of the TB. | ||
| 1817 | + We have to use a dummy code buffer here to avoid clobbering the | ||
| 1818 | + oringinal code. Because we terminate code generation part way through | ||
| 1819 | + we can end up with unresolved relocations. Return -1 if not found. */ | ||
| 1820 | +int dyngen_code_search_pc(TCGContext *s, long offset) | ||
| 1818 | { | 1821 | { |
| 1819 | - return tcg_gen_code_common(s, gen_code_buf, 1, searched_pc); | 1822 | + if (!dummy_code_buf) |
| 1823 | + dummy_code_buf = qemu_malloc(code_gen_max_block_size()); | ||
| 1824 | + return tcg_gen_code_common(s, dummy_code_buf, offset); | ||
| 1820 | } | 1825 | } |
tcg/tcg.h
| @@ -257,8 +257,7 @@ void tcg_context_init(TCGContext *s); | @@ -257,8 +257,7 @@ void tcg_context_init(TCGContext *s); | ||
| 257 | void tcg_func_start(TCGContext *s); | 257 | void tcg_func_start(TCGContext *s); |
| 258 | 258 | ||
| 259 | int dyngen_code(TCGContext *s, uint8_t *gen_code_buf); | 259 | int dyngen_code(TCGContext *s, uint8_t *gen_code_buf); |
| 260 | -int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, | ||
| 261 | - const uint8_t *searched_pc); | 260 | +int dyngen_code_search_pc(TCGContext *s, long offset); |
| 262 | 261 | ||
| 263 | void tcg_set_frame(TCGContext *s, int reg, | 262 | void tcg_set_frame(TCGContext *s, int reg, |
| 264 | tcg_target_long start, tcg_target_long size); | 263 | tcg_target_long start, tcg_target_long size); |
translate-all.c
| @@ -187,8 +187,7 @@ int cpu_restore_state(TranslationBlock *tb, | @@ -187,8 +187,7 @@ int cpu_restore_state(TranslationBlock *tb, | ||
| 187 | s->tb_jmp_offset = NULL; | 187 | s->tb_jmp_offset = NULL; |
| 188 | s->tb_next = tb->tb_next; | 188 | s->tb_next = tb->tb_next; |
| 189 | #endif | 189 | #endif |
| 190 | - j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, | ||
| 191 | - (void *)searched_pc); | 190 | + j = dyngen_code_search_pc(s, searched_pc - tc_ptr); |
| 192 | if (j < 0) | 191 | if (j < 0) |
| 193 | return -1; | 192 | return -1; |
| 194 | /* now find start of instruction before */ | 193 | /* now find start of instruction before */ |