ghidra icon indicating copy to clipboard operation
ghidra copied to clipboard

x86_64 RCR and RCL do not set CF flag correctly

Open treamology opened this issue 10 months ago • 0 comments

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

  1. Run the below RotateTest.java script.
  2. 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()));
	}
}

treamology avatar Apr 15 '24 03:04 treamology