Closed pdamian closed 1 year ago
Indeed, there seems to be an issue. Triton seems to be updating the flag incorrectly. Inside an IT block, a 16-bit instruction should not set the flag condition (with the exception of CMP
, CMN
and TST
). I'll push a fix for this next week.
@pdamian I just pushed a fix for this into the dev-v1.0
branch. Could you confirm it fixes your issue?
@cnheitman: Awesome, thanks! I can confirm that this fixes the issue.
@cnheitman: I have another related question. Not sure though if this should be considered a Triton bug or is the intended behavior. Consider the following example:
#!/usr/bin/env python3
## -*- coding: utf-8 -*-
from triton import ARCH, Instruction, MODE, TritonContext
function = {
0x10: b"\x4f\xf0\x00\x00", # mov r0, #0
0x14: b"\x4f\xf0\x01\x01", # mov r1, #1
0x18: b"\x88\x42", # cmp r0, r1
0x1a: b"\x08\xbf", # it eq
0x1c: b"\x4f\xf0\x02\x00", # mov r0, #2
0x20: b"\x00\xbf", # nop
}
ctx = TritonContext(ARCH.ARM32)
ctx.setMode(MODE.ALIGNED_MEMORY, True)
ctx.setThumb(True)
pc = 0x10
while pc in function:
inst = Instruction(pc, function[pc])
ctx.processing(inst)
print(f"{str(inst):s}")
pc = ctx.getConcreteRegisterValue(ctx.registers.pc)
r0 = ctx.getConcreteRegisterValue(ctx.registers.r0)
print(f"r0 = {r0:d}")
The output when running above code is as follows:
0x10: mov.w r0, #0
0x14: mov.w r1, #1
0x18: cmp r0, r1
0x1a: it eq
0x1c: mov.w r0, #2
0x20: nop
r0 = 0
At the end, the value of register r0
is 0
, which is correct since the instruction mov.w r0, #2
should not be executed.
My issue now is that when I step through the very same code sequence in a debugger, the mov.w r0, #2
instruction is skipped, i.e. the pc
never is at 0x1c
. In Triton on the other hand, a pc
equals to 0x1c
happens.
Is that the intended behavior of Triton that the mov.w r0, #2
instruction is processed, however does not have any effect?
Context: I am using a debugger to collect the trace of a binary. This trace I subsequently run with Triton. The described behavior leads to a de-synchronization when I compare the addresses executed by the debugger and the ones by Triton.
Hey @pdamian . Yes, this is the intended behavior. The way we have to process IT
blocks in Triton is by utilizing the conditional mode of instruction. This means that we use the conditions of the IT
block to the instructions into conditional ones. This has the side effect that you mention. For now, this is something that has to be dealt with in the instruction processing loop. Perhaps, we can find a way to make it easier to handle this in the loop to better reflect the true behavior.
@cnheitman : OK, thanks for the clarifications. Now that I know it's the intended Triton behavior, I can handle that as well in my scripts.
Consider the following example:
When executing the above instructions without Triton, I observe the following output (the branch
bgt #0x4
is not taken):In Triton, however, the branch is taken:
If I take the following function instead (with another
cmp.w ip, #0xff
added just before the branch):Triton does fall-through the branch as well (as in the case without Triton):
Could it be that Triton incorrectly "clears" the comparison status or do I misunderstand something here?