|
From: Geert F. <gee...@es...> - 2003-10-13 21:28:16
|
hello, i have a C++ program that exits with the message "Illegal instruction". when i let valgrind do its work, it says: disInstr: unhandled instruction bytes: 0xE0 0x6E 0x40 0x80 Illegal instruction any idea where i have to start searching? thnx, geert. ps:i use slackware 9.1, gcc 3.2.3 and gtk+ 2.0. |
|
From: Pavel R. <pr...@gn...> - 2003-10-13 22:12:31
|
On Mon, 13 Oct 2003, Geert Fannes wrote: > hello, > > i have a C++ program that exits with the message "Illegal instruction". > when i let valgrind do its work, it says: > > disInstr: unhandled instruction bytes: 0xE0 0x6E 0x40 0x80 > Illegal instruction > > any idea where i have to start searching? Perhaps on Google :-) According to http://www.ni.bekkoame.ne.jp/bilyzkid/us/cpu.htm, instruction 0xE0 is LOOPZ. According to http://courses.ece.uiuc.edu/ece291/archive/fall2001/books/labmanual/inst-ref-loop.html, LOOPNZ jumps only if the counter is nonzero and the zero flag is clear. Not look at the file vg_to_ucode.c, where the error message is printed. Indeed, its doesn't seem to implement this instruction. Look for "case 0xE3:" - that's a similar instruction JCXZ, and just below is LOOP (0xE2). LOOPNZ should be a hybrid of them :-) -- Regards, Pavel Roskin |
|
From: Abhijit Menon-S. <am...@wi...> - 2003-10-13 23:58:07
|
At 2003-10-13 18:12:25 -0400, pr...@gn... wrote:
>
> Geert Fannes wrote:
> >
> > disInstr: unhandled instruction bytes: 0xE0 0x6E 0x40 0x80
>
> Indeed, its doesn't seem to implement this instruction.
Would the following suffice to implement LOOPZ/LOOPNZ? (It just adds a
uCond() to the JIFZ; the rest is as for 0xE3/LOOP.) I'd appreciate any
comments, since I'm not yet familiar enough with valgrind to feel sure
that my approach is correct, and I couldn't figure out how to test it.
Thanks.
-- ams
--- vg_to_ucode.c~ Tue Oct 14 04:28:46 2003
+++ vg_to_ucode.c Tue Oct 14 05:00:09 2003
@@ -4876,6 +4876,24 @@
VG_(printf)("loop 0x%x\n", d32);
break;
+ case 0xE1: /* LOOPZ disp8 */
+ case 0xE0: /* LOOPNZ disp8 */
+ d32 = (eip+1) + getSDisp8(eip); eip++;
+ t1 = newTemp(cb);
+ uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
+ uInstr1(cb, DEC, 4, TempReg, t1);
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ECX);
+ uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
+ uLiteral(cb, eip);
+ uCond(cb, (opc == 0xE1 ? CondZ : CondNZ));
+ uInstr1(cb, JMP, 0, Literal, 0);
+ uLiteral(cb, d32);
+ uCond(cb, CondAlways);
+ *isEnd = True;
+ if (dis)
+ VG_(printf)("loopz 0x%x\n", d32);
+ break;
+
/* ------------------------ IMUL ----------------------- */
case 0x69: /* IMUL Iv, Ev, Gv */
|
|
From: Abhijit Menon-S. <am...@wi...> - 2003-10-14 00:36:55
|
At 2003-10-14 05:27:59 +0530, am...@wi... wrote:
>
> Would the following suffice to implement LOOPZ/LOOPNZ?
I guess not. :-)
I compiled and ran the following program under valgrind to see what my
patch would accomplish. I got the following:
-1: JIFZL t10, $0x80483BE [abcdSD]
opcode: 58
lit32: 0x80483BE
size: 4
val1,val2,val3: 10, 0, 0
tag1,tag2,tag3: 0, 5, 7
flags_r: 0x0
flags_w: 0x0
extra4b: 0x0
cond: 0x4
signed_widen: 0
jmpkind: 0
argc,regparms_n: 0, 0
has_ret_val: 0
regs_live_after: [abcdSD]
valgrind: vg_to_ucode.c:6528 (disInstr): Assertion `sane' failed.
I'll try to figure out what's happening in VG_(saneUInstr).
Suggestions and advice are welcome.
-- ams
.section .rodata
.s: .string "%d\n"
.text
.globl main
main:
pushl %ebp
movl %esp, %ebp
movl $10, %ecx
.L2:
pushl %ecx
pushl %ecx
pushl $.s
call printf
popl %ecx
popl %ecx
xorl %eax, %eax
loopz .L2
.L3:
xorl %eax, %eax
leave
ret
.size main, .-main
|
|
From: Tom H. <th...@cy...> - 2003-10-14 09:27:44
|
In message <200...@lu...>
Abhijit Menon-Sen <am...@wi...> wrote:
> At 2003-10-14 05:27:59 +0530, am...@wi... wrote:
> >
> > Would the following suffice to implement LOOPZ/LOOPNZ?
>
> I guess not. :-)
>
> I compiled and ran the following program under valgrind to see what my
> patch would accomplish. I got the following:
>
> -1: JIFZL t10, $0x80483BE [abcdSD]
> opcode: 58
> lit32: 0x80483BE
> size: 4
> val1,val2,val3: 10, 0, 0
> tag1,tag2,tag3: 0, 5, 7
> flags_r: 0x0
> flags_w: 0x0
> extra4b: 0x0
> cond: 0x4
> signed_widen: 0
> jmpkind: 0
> argc,regparms_n: 0, 0
> has_ret_val: 0
> regs_live_after: [abcdSD]
>
> valgrind: vg_to_ucode.c:6528 (disInstr): Assertion `sane' failed.
>
> I'll try to figure out what's happening in VG_(saneUInstr).
> Suggestions and advice are welcome.
You were trying to put a condition on the JIFZ instruction and that
isn't supported, hence the insanity assertion. Here's a patch that uses
a separate condition JMP instruction which does seem to work:
RCS file: /cvsroot/valgrind/valgrind/coregrind/vg_to_ucode.c,v
retrieving revision 1.98
diff -u -r1.98 vg_to_ucode.c
--- vg_to_ucode.c 13 Oct 2003 07:30:40 -0000 1.98
+++ vg_to_ucode.c 14 Oct 2003 09:25:01 -0000
@@ -4876,6 +4876,27 @@
VG_(printf)("loop 0x%x\n", d32);
break;
+ case 0xE1: /* LOOPZ disp8 */
+ case 0xE0: /* LOOPNZ disp8 */
+ d32 = (eip+1) + getSDisp8(eip); eip++;
+ t1 = newTemp(cb);
+ uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
+ uInstr1(cb, DEC, 4, TempReg, t1);
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ECX);
+ uInstr1(cb, JMP, 0, Literal, 0);
+ uLiteral(cb, d32);
+ uCond(cb, (opc == 0xE1 ? CondNZ : CondZ));
+ uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
+ uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
+ uLiteral(cb, eip);
+ uInstr1(cb, JMP, 0, Literal, 0);
+ uLiteral(cb, d32);
+ uCond(cb, CondAlways);
+ *isEnd = True;
+ if (dis)
+ VG_(printf)("loop%s 0x%x\n", (opc == 0xE1 ? "z" : "nz"), d32);
+ break;
+
/* ------------------------ IMUL ----------------------- */
case 0x69: /* IMUL Iv, Ev, Gv */
One thing I don't understand about this is why I had to declare that
the JMP instruction reads all those flags when it only really needs to
read the Z flag, but without that the JMP is asserted as insane.
Tom
--
Tom Hughes (th...@cy...)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/
|
|
From: Abhijit Menon-S. <am...@wi...> - 2003-10-14 12:58:30
|
At 2003-10-14 10:27:27 +0100, th...@cy... wrote:
>
> Here's a patch that uses a separate condition JMP instruction which
> does seem to work:
Hi Tom.
Thanks for your help. Unfortunately, your patch doesn't quite handle the
LOOPZ/LOOPNZ corner cases correctly. The problem is that the jump cannot
safely be decomposed into two independent jumps. Right now, the code you
wrote is doing the moral equivalent of:
decl %ecx
jnz $disp8
cmpl $0, %ecx
jnz $disp8
But what it really needs to be doing is:
decl %ecx
pushfl
cmpl $0, %ecx
jz $.after
popfl
jz $disp8
.after:
(You can see how your implementation goes wrong with the test program I
posted earlier, and changing loopz to loopnz, or the xorl %eax, %eax to
xorl $1, %eax. The program then loops forever under valgrind.)
The question is, how best to write this in disInstr()?
-- ams
|
|
From: Abhijit Menon-S. <am...@wi...> - 2003-10-14 16:17:45
|
At 2003-10-14 18:28:22 +0530, am...@wi... wrote:
>
> The question is, how best to write this in disInstr()?
Like this. (This passes all the tests I've thought up so far, but I'm
still not completely convinced that it preserves flags correctly.)
Geert, could you please try valgrind with this patch applied on your
program and see if it works?
-- ams
--- coregrind/vg_to_ucode.c~ Tue Oct 14 04:28:46 2003
+++ coregrind/vg_to_ucode.c Tue Oct 14 21:42:52 2003
@@ -4876,6 +4876,27 @@
VG_(printf)("loop 0x%x\n", d32);
break;
+ case 0xE1: /* LOOPZ disp8 */
+ case 0xE0: /* LOOPNZ disp8 */
+ d32 = (eip+1) + getSDisp8(eip); eip++;
+ t1 = newTemp(cb);
+ uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
+ uInstr1(cb, DEC, 4, TempReg, t1);
+ uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ECX);
+ uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
+ uLiteral(cb, eip);
+ uInstr1(cb, JMP, 0, Literal, 0);
+ uLiteral(cb, d32);
+ uCond(cb, (opc == 0xE1 ? CondZ : CondNZ));
+ uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
+ uInstr1(cb, JMP, 0, Literal, 0);
+ uLiteral(cb, eip);
+ uCond(cb, CondAlways);
+ *isEnd = True;
+ if (dis)
+ VG_(printf)("loop%s 0x%x\n", (opc == 0xE1 ? "z" : "nz"), d32);
+ break;
+
/* ------------------------ IMUL ----------------------- */
case 0x69: /* IMUL Iv, Ev, Gv */
|