New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[esil] flag updates for three address instructions #8054
Comments
If I remember correctly |
Yes you are right, I picked a bad example. Let's focus on How should we update the missing flags (
Ah sorry, I simplified a bit too much by writing |
this is hard, maybe a design flaw. I need to think about it. One solution would be |
Great. I am looking forward to hearing your thoughts. Btw. the current ESIL semantics already need to disable updating if (ret && r_anal_esil_get_parm_type (esil, src) != R_ANAL_ESIL_PARM_INTERNAL) { //necessary for some flag-things
esil->cur = num2;
esil->old = num;
esil->lastsz = esil_internal_sizeof_reg (esil, dst);
} This might be worth considering when trying to come up with a solution to the problem we are trying to solve. |
uhm, afaik, esil does not update old and cur if you read from internal flags, or does it? Well, on my todo-list is a new abstract esil, aesil, that has no specific registers. this requires easier data-flow analysis given by the data-structures, that esil uses. That would possibly fix your problem. Radeco already provides SSA-esil, which results in the same. Creating new esil-specs therefore might be pointless work. For now I highly suggest going for |
here is an idea: Esil provides this functionallity of setting custom-ops, not just for adding new operations. You can also override operations, if this is required for some reason. This might be the case here, since this wouldn't affect other plugins. Every anal-plugin has a .esil_init and a .esil_fini, which get called on init and fini of esil. Replace the ops in the .esil_init and it should do what you want. .esil_fini must be set, bc esil_init allows allocating custom data-structures, and we want ppl not to forget freeing them. If this does not cause any problems for this plugin, then we can discuss making this change default behaviour. |
ok, so, I looked at the data-sheet, and I'm pretty sure, that we don't need to change esil parser for this, just generate more sophisticated esil expressions in the arm plugin |
tl;dr: current flag update behavior for ESIL (update only on
=
orcmp
) seems to make it difficult to implement three address instructions.Example
Let's look at the ADD (register) instruction from the ARMv7 instruction set. Most encodings (A1, T1 and T3) support
Rd
,Rn
andRm
to be independently specified. This requires the use of the+
and=
instructions for the ESIL translation, e.g.:If one source and the destination register are the same, the
+=
instruction is used in the translation:Let's compare this with the semantically equivalent instruction
add r1, r2, r1
:On the first look,
r2,r1,+=
(esil_addeq
) andr1,r2,+,r1,=
(esil_add
followed byesil_eq
) seem to do the same thing. For the simpleadd
instruction that is actually true.Updating Flags
However, if we want to implement the
adds
instruction which updates the ARM status flags (carryC
, negativeN
, overflowV
and zeroZ
), we will notice that there is an important difference between callingesil_addeq
andesil_add
followed byesil_eq
(all functions are found inlibr/anal/esil.c
).src,dest,+=
updates thecur
andold
values that are used to calculate ESIL's built in flags ($c31
,$s
,$o
,$z
etc.) like this (fromesil_addeq
):src,dest,=
however does the following (fromesil_eq
):Problems
1.) it is very confusing that
r2,r1,+=
andr1,r2,+,r1,=
are not semantically equivalent in ESIL2.) if we do not use a combined binop and assignment instruction (
+=
,-=
,/=
etc.) there does not seem to be straight forward way to access the overflow or carry flags [0][0]:
$s
and$z
only depend on the result, so they can be calculated fromesil->cur
only, which is the same for both instruction sequences.Solution?
In general I would suggest that flags should be updated whenever a binary (
+
,-
, ...) or unary (++
,!
, ...) operation is performed, not when a register is assigned.This would allow for
r2,r1,+=
andr1,r2,+,r1,=
to have the same semantics.However, I can see that this would cause some problems with
movs
like instructions. Thus one might have to update the flags on=
as well. In this case we would end up with ESIL translations like:r1,r2,+,$c,C,=,$s,N,=,$o,V,=,$z,Z,=,r1,=
orr1,r2,+,$c,C,=,$o,V,=,r1,=,$s,N,=,$z,Z,=
.Also, changing such a fundamental thing as how the flags are updated would probably introduce a lot of new bugs in stable ESIL translators. I have mostly looked at the ARM translator which is in dire need of repair, but I think that other implementations are actually a lot more complete and well tested.
I would love to hear your ideas on how to implement flag updates for three address instructions in ESIL.
The text was updated successfully, but these errors were encountered: