mirror of
https://github.com/gwenhael-le-moine/x49gp.git
synced 2024-12-27 21:58:33 +01:00
137 lines
4.4 KiB
Diff
137 lines
4.4 KiB
Diff
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;
|