Description of problem: valgrind does not handle address-size-override prefix with loopne instruction. valgrind gives an error if it encounters this instruction: vex amd64->IR: unhandled instruction bytes: 0x67 0xE0 0xFA 0xB8 0x2A 0x6 According to the source code, valgrind does not support the address-size-override prefix; from valgrind-3.4.1/VEX/priv/guest-amd64/toIR.c case 0xE0: /* LOOPNE disp8: decrement count, jump if count != 0 && ZF==0 */ case 0xE1: /* LOOPE disp8: decrement count, jump if count != 0 && ZF==1 */ case 0xE2: /* LOOP disp8: decrement count, jump if count != 0 */ { /* The docs say this uses rCX as a count depending on the address size override, not the operand one. Since we don't handle address size overrides, I guess that means RCX. */ ... if (have66orF2orF3(pfx) || haveASO(pfx)) goto decode_failure; The haveASO() function checks for the address-size-override prefix (0x67). Please add support for the address-size-override prefix. Version-Release number of selected component (if applicable): Fedora 11: valgrind-3.4.1-3.x86_64 How reproducible: every time Steps to Reproduce: 1. install Fedora 11 on x86_64 system 2. gcc -g loopnel.s 3. valgrind ./a.out Actual results: vex amd64->IR: unhandled instruction bytes: 0x67 0xE0 0xFA 0xB8 0x2A 0x6 Expected results: valgrind handles the instruction
Created attachment 37714 [details] loopnel.s demo program $ gcc -g loopnel.s $ valgrind -q ./a.out start count = 0 vex amd64->IR: unhandled instruction bytes: 0x67 0xE0 0xFA 0xB8 0x2A 0x6 ==4976== valgrind: Unrecognised instruction at address 0x4004f5. ==4976== Your program just tried to execute an instruction that Valgrind ==4976== did not recognise. There are two possible reasons for this. ==4976== 1. Your program has a bug and erroneously jumped to a non-code ==4976== location. If you are running Memcheck and you just saw a ==4976== warning about a bad jump, it's probably your program's fault. ==4976== 2. The instruction is legitimate but Valgrind doesn't handle it, ==4976== i.e. it's Valgrind's fault. If you think this is the case or ==4976== you are not sure, please let us know and we'll try to fix it. ==4976== Either way, Valgrind will now raise a SIGILL signal which will ==4976== probably kill your program. ==4976== ==4976== Process terminating with default action of signal 4 (SIGILL) ==4976== Illegal opcode at address 0x4004F5 ==4976== at 0x4004F5: main (loopnel.s:35) Illegal instruction $ objdump -d a.out ... 4004ed: b9 03 00 00 00 mov $0x3,%ecx 4004f2: 83 c3 01 add $0x1,%ebx 4004f5: 67 e0 fa loopnel 4004f2 <main+0x2e> ...
Created attachment 37715 [details] loopneq.s demo program Using 64-bit registers makes valgrind happy. $ diff loopnel.s loopneq.s 32c32 < movl $3, %ecx --- > movq $3, %rcx 35c35 < loopnel .L3 --- > loopneq .L3 $ gcc -g loopneq.s $ valgrind -q ./a.out start count = 0 end count = 3 $ objdump -d a.out ... 4004ed: 48 c7 c1 03 00 00 00 mov $0x3,%rcx 4004f4: 83 c3 01 add $0x1,%ebx 4004f7: e0 fb loopne 4004f4 <main+0x30> ...
Created attachment 37719 [details] valgrind-3.5.0-amd64-loopnel.patch Only compile tested patch (plus valgrind make check), but not on the actual loopnel.
Created attachment 37720 [details] valgrind-3.5.0-amd64-aso.patch Additional patch to handle 0x67 prefix in string insns.
Created attachment 37733 [details] valgrind-3.5.0-amd64-loopnel.patch Updated loopnel patch which adds also a testcase.
Created attachment 37737 [details] scas.c Testcase for the amd64-aso patch (not in patch form though).
The loopnel part of this was committed as VEX r2085 and valgrind r11507 to fix #256669.
I've committed Jakub's other patch, for ASO prefixed REP string instructions, as VEX r2194 and valgrind r11969.