Fix TCG relocation bug (exposed by fault after brcond op). Add FIXME for
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Feb 2008 02:41:15 +0000 (02:41 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 10 Feb 2008 02:41:15 +0000 (02:41 +0000)
annother potential bug.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3968 c046a42c-6fe2-441c-8c8c-71466251a162

tcg/tcg.c
tcg/tcg.h
translate-all.c

index 9d3765f..4ddc62f 100644 (file)
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -97,6 +97,9 @@ void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
 
     l = &s->labels[label_index];
     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);
     } else {
         /* 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,
-                                      int do_search_pc,
-                                      const uint8_t *searched_pc)
+                                      long search_pc)
 {
     int opc, op_index, macro_op_index;
     const TCGOpDef *def;
@@ -1754,7 +1756,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
             }
 #endif
             tcg_reg_alloc_bb_end(s);
-            if (do_search_pc) {
+            if (search_pc >= 0) {
                 s->code_ptr += def->copy_size;
                 args += def->nb_args;
             } else {
@@ -1771,13 +1773,11 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
         }
         args += def->nb_args;
     next: ;
-        if (do_search_pc) {
-            if (searched_pc < s->code_ptr) {
-                if (macro_op_index >= 0)
-                    return macro_op_index;
-                else
-                    return op_index;
-            }
+        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
+            if (macro_op_index >= 0)
+                return macro_op_index;
+            else
+                return op_index;
         }
         op_index++;
 #ifndef NDEBUG
@@ -1802,7 +1802,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
     }
 #endif
 
-    tcg_gen_code_common(s, gen_code_buf, 0, NULL);
+    tcg_gen_code_common(s, gen_code_buf, -1);
 
     /* flush instruction cache */
     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 the index of the micro operation such as the pc after is <
-   search_pc. Note: gen_code_buf is accessed during the operation, but
-   its content should not be modified. Return -1 if not found. */
-int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf,
-                          const uint8_t *searched_pc)
+static uint8_t *dummy_code_buf;
+
+/* Return the index of the micro operation such as the pc after is <
+   offset bytes from the start of the TB.
+   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);
 }
index 11e9d8a..11ffb0c 100644 (file)
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -257,8 +257,7 @@ void tcg_context_init(TCGContext *s);
 void tcg_func_start(TCGContext *s);
 
 int dyngen_code(TCGContext *s, uint8_t *gen_code_buf);
-int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf,
-                          const uint8_t *searched_pc);
+int dyngen_code_search_pc(TCGContext *s, long offset);
 
 void tcg_set_frame(TCGContext *s, int reg,
                    tcg_target_long start, tcg_target_long size);
index 9639612..2000083 100644 (file)
@@ -187,8 +187,7 @@ int cpu_restore_state(TranslationBlock *tb,
     s->tb_jmp_offset = NULL;
     s->tb_next = tb->tb_next;
 #endif
-    j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, 
-                              (void *)searched_pc); 
+    j = dyngen_code_search_pc(s, searched_pc - tc_ptr);
     if (j < 0)
         return -1;
     /* now find start of instruction before */