Open aswerw opened 6 years ago
Thanks for reporting. I'm aware of this problem and implementing a more advanced system for the flags is already on my todo-list (for the v3.0 release).
Nevertheless some of these conditions are beyond the scope of a disassembler. CLI
for example.:
If IOPL < 3 and either VME mode or PVI mode is active, CLI clears the VIF flag in the EFLAGS register, leaving IF unaffected.
There is no way to check IOPL/VME/PVI without making it somehow configurable by the user. And going this way, we would have to implement options for pretty much all CPU-modes, MSRs, system-context, ...
For now, zydis uses the "worst-case" action for these conditional flags e.g. UNDEFINED
for RCL/...
or MODIFIED
for SAL/...
.
Could you elaborate on how this would be useful for your project? I can't really think of a use case where the information of conditional flag writes would be more useful than a general write info unless the disassembler also tells you if it is actually written (which usually depends on a lot of context and thus is very hard to do).
In my case it's for knowing whether or not an optimization is safe to do.
A poor example:
stc ; CF=1
ror eax, <imm8> ; Or some other instruction that conditionally writes to CF
jc <rel8>
STC can't be optimized out in this case, because ROR may not overwrite the CF.
If ROR was an instruction that unconditionally modified CF (without testing it as well) then STC could be removed, but there is no way to distinguish the two cases with Zydis.
Allright. I can easily implement some logic for RCL/RCR/ROL/ROR
, SAL/SAR/SHL/SHR
, and SHLD/SHRD
by adding an opcode-filter that matches the IMMEDIATE value of the instruction.
CLI/STI
is beyond the scope of a disassembler for the reasons described above and DAA/DAS
is a special case as well (as it requires context; e.g. the content of the AL
register which is only available at runtime).
Hmm, I see.
@flobernd I don't know if that would be such a good idea. Well, it could be done additionally, but it doesn't really address the core problem. Even if special handling for those imm=0 variants were added, there are still dynamic versions of the instructions (e.g. ROR r/m8, CL
) where there is no certainty of a write being performed. I guess we'll just need a new flag access mode and do our best in fixing the tables. That will involve a lot of work, though.
Reminder for myself: Let's for now always include the conditional flags. For the register form of the rotate instructions we can't do much anyways ...
Some instructions will only conditionally modify a CPU flag. I think most instructions do so unconditionally.
Zydis exposes conditional reads and writes for operands.
Should it do the same for CPU flags?
Example: (conditional carry flag write)
Here are a few others:
RCL/RCR/ROL/ROR--Rotate "If the masked count is 0, the flags are not affected. If the masked count is 1, then the OF flag is affected, otherwise (masked count is greater than 1) the OF flag is undefined. The CF flag is affected when the masked count is non-zero."
DAA/DAS "The CF and AF flags are set if the adjustment of the value results in a decimal [carry/borrow] in either digit of the result.."
CLI/STI "Either the IF flag or the VIF flag is [cleared/set] to [0/1]."
SAL/SAR/SHL/SHR--Shift "If the count is 0, the flags are not affected."
SHLD/SHRD "If the count operand is 0, the flags are not affected."