https://bugs.kde.org/show_bug.cgi?id=359524
Bug ID: 359524 Summary: bt, btc, btr and bts instruction improperly translated by VEX on x86-64 Product: valgrind Version: unspecified Platform: Ubuntu Packages OS: Linux Status: UNCONFIRMED Severity: major Priority: NOR Component: vex Assignee: jsew...@acm.org Reporter: lm...@cam.ac.uk Platform: Ubuntu 12.04, AMD64, 3.2.0-53-generic See "Steps to reproduce" for valgrind's output. Reproducible: Always Steps to Reproduce: 1. Consider the code below: ----------------- code ------------------------ .text .globl _start _start: movq $8, %rbx movq $12, %rdx btq %rbx, %rdx #btc %rbx, %rdx #uncomment to reproduce #btr %rbx, %rdx #uncomment to reproduce #bts %rbx, %rdx #uncomment to reproduce # exit movq $60, %rax # use the _exit syscall movq $0, %rdi # error code 0 syscall # make syscall ----------------- end code ------------------------------- 2. Compile the code as follows: $as -o test.o test.s $ld -o test test.o 3. Run Valgrind as follows: $valgrind --vex-guest-chase-thresh=0 --trace-flags=10000000 --trace-notabove=999 ./test The out is as follows. ------------------------ Output ------------------------ 0x4000B0: movq $8, %rbx ------ IMark(0x4000B0, 7, 0) ------ PUT(40) = 0x8:I64 PUT(184) = 0x4000B7:I64 0x4000B7: movq $12, %rdx ------ IMark(0x4000B7, 7, 0) ------ PUT(32) = 0xC:I64 PUT(184) = 0x4000BE:I64 0x4000BE: btq %rbx, %rdx ------ IMark(0x4000BE, 4, 0) ------ t2 = GET:I64(40) t6 = Sub64(GET:I64(48),0x120:I64) PUT(48) = t6 STle(t6) = GET:I64(32) t7 = t6 t3 = And64(t2,0x3F:I64) t5 = Add64(t7,Sar64(t3,0x3:I8)) t4 = 64to8(And64(t3,0x7:I64)) t0 = LDle:I8(t5) PUT(144) = 0x0:I64 PUT(160) = 0x0:I64 PUT(152) = And64(Shr64(8Uto64(t0),t4),0x1:I64) PUT(168) = 0x0:I64 PUT(48) = Add64(t6,0x120:I64) PUT(184) = 0x4000C2:I64 [...] ---------------------- end output ----------------------- Actual Results: The VEX translation of bt, btc, btr, and bts seem incorrect. See below. x86-64 documetation says: bt, btc, btr and bts instructions test one bit of their first operand, whose index is given by the second operand, and store the value of that bit into the carry flag. However, as can be seen in valgrind output, 2 things don't add up: 1- line t6 = Sub64(GET:I64(48),0x120:I64) means it's reading register 48. However this register is never set prior to reading it. Maybe this is assumed to be 0 on startup? 2- the code is doing some erroneous calculations on certain registers that it interprets as memory addresses. Subsequently, these memory locations are used to read (t0 = LDle:I8(t5)) and store (STle(t6) = GET:I64(32)). This appears to be wrong because the bt instruction should not update its operands, let alone memory locations. Instructions btc, btr and bts update their operands. However, we found that when translated by VEX, their resulting IR accesses memory locations even if their operands are registers with constant values (see our test.s by un-commenting commented lines). When using memory address as operands for btc, btr and bts instruction, memory accesses also appear to be incorrect. -- You are receiving this mail because: You are watching all bug changes.