ghidra
ghidra copied to clipboard
x86_64 RCR and RCL do not set CF flag correctly
Describe the bug
When using the p-code emulator to run the instruction RCR RCX, 0x2
, where RCX = 2
, the CF
flag is not set as expected. The same happens when overflow occurs on the left side when using RCL
.
ROR
and ROL
set the flag as expected, and rotating using RCR
and RCL
by 1 works correctly since this is a special case in the SLEIGH.
To Reproduce
- Run the below
RotateTest.java
script. - See that
CF
is still zero, even though it should contain the 1 that overflowed off the right.
Expected behavior
CF
should be set correctly.
Environment (please complete the following information):
- OS: Pop_OS 22.04
- Java Version: 18.0.2-ea
- Ghidra Version: 11.0.3
- Ghidra Origin: Official GitHub distro
Additional context
RotateTest.java
import ghidra.app.plugin.assembler.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.script.GhidraScript;
import ghidra.pcode.emu.PcodeEmulator;
import ghidra.pcode.emu.PcodeThread;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.LanguageID;
import ghidra.util.NumericUtilities;
public class RotateTest extends GhidraScript {
private SleighLanguage language;
private PcodeEmulator emulator;
@Override
protected void run() throws Exception {
/*
* Create an emulator and start a thread
*/
language = (SleighLanguage) getLanguage(new LanguageID("x86:LE:64:default"));
emulator = new PcodeEmulator(language);
PcodeThread<byte[]> thread = emulator.newThread();
// The emulator composes the full library for each thread
PcodeUseropLibrary<byte[]> library = thread.getUseropLibrary();
AddressSpace dyn = language.getDefaultSpace();
/*
* Assemble a little test program and write it into the emulator
*/
Address entry = dyn.getAddress(0x00400000);
Assembler asm = Assemblers.getAssembler(language);
AssemblyBuffer buffer = new AssemblyBuffer(asm, entry);
buffer.assemble("RCR RCX, 0x2");
byte[] code = buffer.getBytes();
println(NumericUtilities.convertBytesToString(code));
emulator.getSharedState().setVar(dyn, entry.getOffset(), code.length, true, code);
/*
* Initialize other parts of the emulator and thread state.
*/
PcodeProgram init = SleighProgramCompiler.compileProgram(language, "init", String.format("""
RCX = 0x2;
RIP = 0x%s;
RSP = 0x00001000;
""", entry), library);
thread.getExecutor().execute(init, library);
thread.overrideContextWithDefault();
thread.reInitialize();
thread.stepInstruction(1);
/*
* Inspect the machine. You can always do this by accessing the state directly, but for
* anything other than simple variables, you may find compiling an expression more
* convenient.
*/
println("CF = " +
Utils.bytesToLong(thread.getState().getVar(language.getRegister("CF"), Reason.INSPECT),
1, language.isBigEndian()));
println("RCX = " + Utils.bytesToLong(
SleighProgramCompiler.compileExpression(language, "RCX").evaluate(thread.getExecutor()),
8, language.isBigEndian()));
}
}