]> git.pld-linux.org Git - packages/qemu.git/blame - qemu-0.7.2-dyngen-check-stack-clobbers.patch
- gcc 3.4 segfault for mips
[packages/qemu.git] / qemu-0.7.2-dyngen-check-stack-clobbers.patch
CommitLineData
891bbdf5
AM
12005-11-11 Gwenole Beauchesne <gbeauchesne@mandriva.com>
2
3 * Check for stack clobbers in functions using GOTO_LABEL_PARAM().
4
5--- qemu-0.7.2/dyngen.c.dyngen-check-stack-clobbers 2005-11-11 16:26:33.000000000 +0100
6+++ qemu-0.7.2/dyngen.c 2005-11-11 17:30:29.000000000 +0100
7@@ -1414,6 +1414,9 @@ int arm_emit_ldr_info(const char *name,
8 #define FLAG_TARGET (1 << 3)
9 /* This is a magic instruction that needs fixing up. */
10 #define FLAG_EXIT (1 << 4)
11+/* This instruction clobbers the stack pointer. */
12+/* XXX only supports push, pop, add/sub $imm,%esp */
13+#define FLAG_STACK (1 << 5)
14 #define MAX_EXITS 5
15
16 static void
17@@ -1454,6 +1457,7 @@ trace_i386_insn (const char *name, uint8
18 int is_jmp;
19 int is_exit;
20 int is_pcrel;
21+ int is_stack;
22 int immed;
23 int seen_rexw;
24 int32_t disp;
25@@ -1476,6 +1480,7 @@ trace_i386_insn (const char *name, uint8
26 is_exit = 0;
27 seen_rexw = 0;
28 is_pcrel = 0;
29+ is_stack = 0;
30
31 while (is_prefix) {
32 op = ptr[insn_size];
33@@ -1522,6 +1527,7 @@ trace_i386_insn (const char *name, uint8
34 switch (op & 0x7) {
35 case 0: /* push fs/gs */
36 case 1: /* pop fs/gs */
37+ is_stack = 1;
38 case 2: /* cpuid/rsm */
39 modrm = 0;
40 break;
41@@ -1594,6 +1600,7 @@ trace_i386_insn (const char *name, uint8
42 #endif
43 case 5: /* push/pop general register. */
44 modrm = 0;
45+ is_stack = 1;
46 break;
47
48 case 6:
49@@ -1601,6 +1608,7 @@ trace_i386_insn (const char *name, uint8
50 case 0: /* pusha */
51 case 1: /* popa */
52 modrm = 0;
53+ is_stack = 1;
54 break;
55 case 2: /* bound */
56 case 3: /* arpl */
57@@ -1620,10 +1628,12 @@ trace_i386_insn (const char *name, uint8
58 case 8: /* push immediate */
59 immed = op_size;
60 modrm = 0;
61+ is_stack = 1;
62 break;
63 case 10: /* push 8-bit immediate */
64 immed = 1;
65 modrm = 0;
66+ is_stack = 1;
67 break;
68 case 9: /* imul immediate */
69 immed = op_size;
70@@ -1653,8 +1663,22 @@ trace_i386_insn (const char *name, uint8
71 immed = op_size;
72 else
73 immed = 1;
74+ if (op == 0x81 || op == 0x83) {
75+ /* add, sub */
76+ op = ptr[insn_size];
77+ switch ((op >> 3) & 7) {
78+ case 0:
79+ case 5:
80+ is_stack = (op & 7) == 4;
81+ break;
82+ }
83+ }
84 }
85- /* else test, xchg, mov, lea or pop general. */
86+ else if ((op & 0xf) == 0xf) {
87+ /* pop general. */
88+ is_stack = 1;
89+ }
90+ /* else test, xchg, mov, lea. */
91 break;
92
93 case 9:
94@@ -1904,6 +1928,9 @@ trace_i386_insn (const char *name, uint8
95 if (is_exit)
96 flags[insn] |= FLAG_EXIT;
97
98+ if (is_stack)
99+ flags[insn] |= FLAG_STACK;
100+
101 if (!(is_jmp || is_ret || is_exit))
102 flags[insn + insn_size] |= FLAG_INSN;
103 }
104@@ -1924,6 +1951,7 @@ static int trace_i386_op(const char * na
105 int num_exits;
106 int len;
107 int last_insn;
108+ int stack_clobbered;
109
110 len = *plen;
111 flags = malloc(len + 1);
112@@ -1947,6 +1975,7 @@ static int trace_i386_op(const char * na
113 retpos = -1;
114 num_exits = 0;
115 last_insn = 0;
116+ stack_clobbered = 0;
117 for (insn = 0; insn < len; insn++) {
118 if (flags[insn] & FLAG_RET) {
119 /* ??? In theory it should be possible to handle multiple return
120@@ -1956,6 +1985,8 @@ static int trace_i386_op(const char * na
121 retpos = insn;
122 }
123 if (flags[insn] & FLAG_EXIT) {
124+ if (stack_clobbered)
125+ error("Stack clobbered in %s", name);
126 if (num_exits == MAX_EXITS)
127 error("Too many block exits in %s", name);
128 exit_addrs[num_exits] = insn;
129@@ -1963,6 +1994,8 @@ static int trace_i386_op(const char * na
130 }
131 if (flags[insn] & FLAG_INSN)
132 last_insn = insn;
133+ if (flags[insn] & FLAG_STACK)
134+ stack_clobbered = 1;
135 }
136
137 exit_addrs[num_exits] = -1;
This page took 0.044835 seconds and 4 git commands to generate.