]> git.pld-linux.org Git - packages/qemu.git/blobdiff - qemu-0.7.2-dyngen-check-stack-clobbers.patch
- new
[packages/qemu.git] / qemu-0.7.2-dyngen-check-stack-clobbers.patch
diff --git a/qemu-0.7.2-dyngen-check-stack-clobbers.patch b/qemu-0.7.2-dyngen-check-stack-clobbers.patch
new file mode 100644 (file)
index 0000000..8743037
--- /dev/null
@@ -0,0 +1,137 @@
+2005-11-11  Gwenole Beauchesne  <gbeauchesne@mandriva.com>
+
+       * Check for stack clobbers in functions using GOTO_LABEL_PARAM().
+
+--- qemu-0.7.2/dyngen.c.dyngen-check-stack-clobbers    2005-11-11 16:26:33.000000000 +0100
++++ qemu-0.7.2/dyngen.c        2005-11-11 17:30:29.000000000 +0100
+@@ -1414,6 +1414,9 @@ int arm_emit_ldr_info(const char *name, 
+ #define FLAG_TARGET   (1 << 3)
+ /* This is a magic instruction that needs fixing up.  */
+ #define FLAG_EXIT     (1 << 4)
++/* This instruction clobbers the stack pointer.  */
++/* XXX only supports push, pop, add/sub $imm,%esp  */
++#define FLAG_STACK    (1 << 5)
+ #define MAX_EXITS     5
+ static void
+@@ -1454,6 +1457,7 @@ trace_i386_insn (const char *name, uint8
+     int is_jmp;
+     int is_exit;
+     int is_pcrel;
++    int is_stack;
+     int immed;
+     int seen_rexw;
+     int32_t disp;
+@@ -1476,6 +1480,7 @@ trace_i386_insn (const char *name, uint8
+     is_exit = 0;
+     seen_rexw = 0;
+     is_pcrel = 0;
++    is_stack = 0;
+     while (is_prefix) {
+         op = ptr[insn_size];
+@@ -1522,6 +1527,7 @@ trace_i386_insn (const char *name, uint8
+                     switch (op & 0x7) {
+                     case 0: /* push fs/gs */
+                     case 1: /* pop fs/gs */
++                        is_stack = 1;
+                     case 2: /* cpuid/rsm */
+                         modrm = 0;
+                         break;
+@@ -1594,6 +1600,7 @@ trace_i386_insn (const char *name, uint8
+ #endif
+         case 5: /* push/pop general register.  */
+             modrm = 0;
++            is_stack = 1;
+             break;
+         case 6:
+@@ -1601,6 +1608,7 @@ trace_i386_insn (const char *name, uint8
+             case 0: /* pusha */
+             case 1: /* popa */
+                 modrm = 0;
++                is_stack = 1;
+                 break;
+             case 2: /* bound */
+             case 3: /* arpl */
+@@ -1620,10 +1628,12 @@ trace_i386_insn (const char *name, uint8
+             case 8: /* push immediate */
+                 immed = op_size;
+                 modrm = 0;
++                is_stack = 1;
+                 break;
+             case 10: /* push 8-bit immediate */
+                 immed = 1;
+                 modrm = 0;
++                is_stack = 1;
+                 break;
+             case 9: /* imul immediate */
+                 immed = op_size;
+@@ -1653,8 +1663,22 @@ trace_i386_insn (const char *name, uint8
+                     immed = op_size;
+                 else
+                     immed = 1;
++                if (op == 0x81 || op == 0x83) {
++                    /* add, sub */
++                    op = ptr[insn_size];
++                    switch ((op >> 3) & 7) {
++                    case 0:
++                    case 5:
++                        is_stack = (op & 7) == 4;
++                        break;
++                    }
++                }
+             }
+-            /* else test, xchg, mov, lea or pop general.  */
++            else if ((op & 0xf) == 0xf) {
++                /* pop general.  */
++                is_stack = 1;
++            }
++            /* else test, xchg, mov, lea.  */
+             break;
+         case 9:
+@@ -1904,6 +1928,9 @@ trace_i386_insn (const char *name, uint8
+     if (is_exit)
+       flags[insn] |= FLAG_EXIT;
++    if (is_stack)
++      flags[insn] |= FLAG_STACK;
++
+     if (!(is_jmp || is_ret || is_exit))
+       flags[insn + insn_size] |= FLAG_INSN;
+ }
+@@ -1924,6 +1951,7 @@ static int trace_i386_op(const char * na
+     int num_exits;
+     int len;
+     int last_insn;
++    int stack_clobbered;
+     len = *plen;
+     flags = malloc(len + 1);
+@@ -1947,6 +1975,7 @@ static int trace_i386_op(const char * na
+     retpos = -1;
+     num_exits = 0;
+     last_insn = 0;
++    stack_clobbered = 0;
+     for (insn = 0; insn < len; insn++) {
+         if (flags[insn] & FLAG_RET) {
+             /* ??? In theory it should be possible to handle multiple return
+@@ -1956,6 +1985,8 @@ static int trace_i386_op(const char * na
+             retpos = insn;
+         }
+         if (flags[insn] & FLAG_EXIT) {
++            if (stack_clobbered)
++                error("Stack clobbered in %s", name);
+             if (num_exits == MAX_EXITS)
+                 error("Too many block exits in %s", name);
+             exit_addrs[num_exits] = insn;
+@@ -1963,6 +1994,8 @@ static int trace_i386_op(const char * na
+         }
+         if (flags[insn] & FLAG_INSN)
+             last_insn = insn;
++        if (flags[insn] & FLAG_STACK)
++            stack_clobbered = 1;
+     }
+     exit_addrs[num_exits] = -1;
This page took 0.038878 seconds and 4 git commands to generate.