use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class RcrTranslator method translate.
// TODO(timkornau): Check this code again
/**
* Translates a RCR instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The RCR instruction to translate.
* @param instructions The generated REIL code will be added to this list
*
* @throws InternalTranslationException if any of the arguments are null the passed instruction is
* not an RCR instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "rcr");
if (instruction.getOperands().size() != 2) {
throw new InternalTranslationException("Error: Argument instruction is not a rcr instruction (invalid number of operands)");
}
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final IOperandTree sourceOperand = operands.get(1);
// Load source operand.
final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(sourceResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load target operand.
final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(targetResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final OperandSize sourceSize = sourceResult.getSize();
final OperandSize targetSize = targetResult.getSize();
final OperandSize resultSize = TranslationHelpers.getNextSize(sourceSize);
final String sourceRegister = sourceResult.getRegister();
final String targetRegister = targetResult.getRegister();
final String rotateMask = environment.getNextVariableString();
final String rotateMaskZero = environment.getNextVariableString();
final String rotateMaskLessOne = environment.getNextVariableString();
final String rotateMaskOne = environment.getNextVariableString();
final String shiftedOp1 = environment.getNextVariableString();
final String realOp1 = environment.getNextVariableString();
final String shrValue = environment.getNextVariableString();
final String shredResult = environment.getNextVariableString();
final String shlValue = environment.getNextVariableString();
final String shledResult = environment.getNextVariableString();
final String result = environment.getNextVariableString();
final String shiftedResult = environment.getNextVariableString();
final String truncatedResult = environment.getNextVariableString();
final String tempOf = environment.getNextVariableString();
final String tempOfLsb = environment.getNextVariableString();
final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(sourceSize));
final String maskSize = String.valueOf(TranslationHelpers.getAllBitsMask(sourceSize));
final String modVal = String.valueOf(sourceSize.getBitSize());
final String shiftMsbLsb = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(sourceSize));
// Make sure to rotate less than the size of the register
instructions.add(ReilHelpers.createMod(offset, targetSize, targetRegister, targetSize, modVal, targetSize, rotateMask));
// Find out if the rotate mask is 0 and negate the result
instructions.add(ReilHelpers.createBisz(offset + 1, targetSize, rotateMask, OperandSize.BYTE, rotateMaskZero));
// Find out if the rotate mask is 1
instructions.add(ReilHelpers.createSub(offset + 2, targetSize, rotateMask, targetSize, "1", targetSize, rotateMaskLessOne));
instructions.add(ReilHelpers.createBisz(offset + 3, targetSize, rotateMaskLessOne, OperandSize.BYTE, rotateMaskOne));
// Rotating through the carry flag is like rotating through a 33 bit register
// For rotating rightwards, the CF must be added at the LSB of the 32 register
instructions.add(ReilHelpers.createBsh(offset + 4, sourceSize, sourceRegister, OperandSize.BYTE, "1", resultSize, shiftedOp1));
instructions.add(ReilHelpers.createOr(offset + 5, resultSize, shiftedOp1, OperandSize.BYTE, Helpers.CARRY_FLAG, resultSize, realOp1));
// Negate the rotate-mask => ROT to the right
instructions.add(ReilHelpers.createSub(offset + 6, OperandSize.BYTE, "0", OperandSize.BYTE, rotateMask, OperandSize.BYTE, shrValue));
// Perform the rotate
instructions.add(ReilHelpers.createBsh(offset + 7, sourceSize, realOp1, OperandSize.BYTE, shrValue, sourceSize, shredResult));
instructions.add(ReilHelpers.createSub(offset + 8, OperandSize.BYTE, modVal, OperandSize.BYTE, rotateMask, OperandSize.BYTE, shlValue));
instructions.add(ReilHelpers.createBsh(offset + 9, sourceSize, realOp1, OperandSize.BYTE, shlValue, sourceSize, shledResult));
instructions.add(ReilHelpers.createOr(offset + 10, sourceSize, shredResult, sourceSize, shledResult, sourceSize, result));
// Truncate the result (get rid of the CF in the LSB)
instructions.add(ReilHelpers.createBsh(offset + 11, resultSize, result, OperandSize.BYTE, "-1", resultSize, shiftedResult));
instructions.add(ReilHelpers.createAnd(offset + 12, resultSize, shiftedResult, sourceSize, maskSize, sourceSize, truncatedResult));
// Don't change the flags if the rotate value was zero
final String jmpGoal = "666";
instructions.add(ReilHelpers.createJcc(offset + 13, OperandSize.BYTE, rotateMaskZero, OperandSize.ADDRESS, jmpGoal));
// Properly update OF if the rotate value == 1
final String jmpGoal2 = "666";
instructions.add(ReilHelpers.createJcc(offset + 14, OperandSize.BYTE, rotateMaskZero, OperandSize.ADDRESS, jmpGoal2));
// Set the OF to undefined if the rotate-mask was positive but not 1
instructions.add(ReilHelpers.createUndef(offset + 15, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Update the CF now
final String jmpGoal3 = "666";
instructions.add(ReilHelpers.createJcc(offset + 15, OperandSize.BYTE, rotateMaskZero, OperandSize.ADDRESS, jmpGoal3));
instructions.add(ReilHelpers.createAnd(offset + 16, sourceSize, sourceRegister, sourceSize, msbMask, sourceSize, tempOf));
instructions.add(ReilHelpers.createBsh(offset + 17, sourceSize, tempOf, sourceSize, shiftMsbLsb, OperandSize.BYTE, tempOfLsb));
instructions.add(ReilHelpers.createXor(offset + 18, OperandSize.BYTE, tempOfLsb, OperandSize.BYTE, Helpers.CARRY_FLAG, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Set the CF to the LSB of the untruncated result
instructions.add(ReilHelpers.createAnd(offset + 19, resultSize, result, OperandSize.BYTE, "1", OperandSize.BYTE, Helpers.CARRY_FLAG));
Helpers.writeBack(environment, offset + 20, targetOperand, result, targetResult.getSize(), targetResult.getAddress(), targetResult.getType(), instructions);
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class RolTranslator method translate.
// TODO(timkornau): Check this code again
/**
* Translates a ROL instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The ROL instruction to translate.
* @param instructions The generated REIL code will be added to this list
*
* @throws InternalTranslationException if any of the arguments are null the passed instruction is
* not an ROL instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "rol");
if (instruction.getOperands().size() != 2) {
throw new InternalTranslationException("Error: Argument instruction is not a rol instruction (invalid number of operand)");
}
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final IOperandTree sourceOperand = operands.get(1);
// Load source operand.
final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(sourceResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load target operand.
final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(targetResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final OperandSize sourceSize = sourceResult.getSize();
final OperandSize targetSize = targetResult.getSize();
final String sourceRegister = sourceResult.getRegister();
final String targetRegister = targetResult.getRegister();
final String rotateMask = environment.getNextVariableString();
final String rotateMaskZero = environment.getNextVariableString();
final String rotateMaskLessOne = environment.getNextVariableString();
final String rotateMaskOne = environment.getNextVariableString();
final String shrValue = environment.getNextVariableString();
final String shredResult = environment.getNextVariableString();
final String shledResult = environment.getNextVariableString();
final String result = environment.getNextVariableString();
final String tempOf = environment.getNextVariableString();
final String tempOfLsb = environment.getNextVariableString();
final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(targetSize));
final String modVal = String.valueOf(targetSize.getBitSize());
final String shiftMsbLsb = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(targetSize));
final int linesBefore = instructions.size();
// Make sure to rotate less than the size of the register
instructions.add(ReilHelpers.createMod(offset, sourceSize, sourceRegister, targetSize, modVal, targetSize, rotateMask));
// Find out if the rotate mask is 0 and negate the result
instructions.add(ReilHelpers.createBisz(offset + 1, targetSize, rotateMask, OperandSize.BYTE, rotateMaskZero));
// Find out if the rotate mask is 1
instructions.add(ReilHelpers.createSub(offset + 2, targetSize, rotateMask, targetSize, "1", targetSize, rotateMaskLessOne));
instructions.add(ReilHelpers.createBisz(offset + 3, targetSize, rotateMaskLessOne, OperandSize.BYTE, rotateMaskOne));
// Perform the rotate
instructions.add(ReilHelpers.createBsh(offset + 4, targetSize, targetRegister, OperandSize.BYTE, rotateMask, targetSize, shledResult));
instructions.add(ReilHelpers.createAdd(offset + 5, OperandSize.BYTE, "-" + modVal, OperandSize.BYTE, rotateMask, OperandSize.BYTE, shrValue));
instructions.add(ReilHelpers.createBsh(offset + 6, targetSize, targetRegister, OperandSize.BYTE, shrValue, targetSize, shredResult));
instructions.add(ReilHelpers.createOr(offset + 7, targetSize, shledResult, targetSize, shredResult, targetSize, result));
// Don't change the flags if the rotate value was zero
final String jmpGoal = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 16);
instructions.add(ReilHelpers.createJcc(offset + 8, OperandSize.BYTE, rotateMaskZero, OperandSize.ADDRESS, jmpGoal));
// Set the CF to the new LSB
instructions.add(ReilHelpers.createAnd(offset + 9, targetSize, result, sourceSize, "1", OperandSize.BYTE, Helpers.CARRY_FLAG));
// The OF needs to be set to a different value if the rotate-mask was 1
final String jmpGoal2 = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 13);
instructions.add(ReilHelpers.createJcc(offset + 10, OperandSize.BYTE, rotateMaskOne, OperandSize.ADDRESS, jmpGoal2));
// Set the OF to undefined if the rotate-mask was positive but not 1
instructions.add(ReilHelpers.createUndef(offset + 11, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Jump to the end
final String jmpGoal3 = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 16);
instructions.add(ReilHelpers.createJcc(offset + 12, OperandSize.BYTE, "1", OperandSize.ADDRESS, jmpGoal3));
// OF = MSB(DEST) XOR CF
instructions.add(ReilHelpers.createAnd(offset + 13, targetSize, result, targetSize, msbMask, sourceSize, tempOf));
instructions.add(ReilHelpers.createBsh(offset + 14, targetSize, tempOf, targetSize, shiftMsbLsb, OperandSize.BYTE, tempOfLsb));
instructions.add(ReilHelpers.createBsh(offset + 15, OperandSize.BYTE, tempOfLsb, OperandSize.BYTE, Helpers.CARRY_FLAG, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
Helpers.writeBack(environment, offset + 16, targetOperand, result, targetResult.getSize(), targetResult.getAddress(), targetResult.getType(), instructions);
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class RorTranslator method translate.
// TODO(timkornau): Check this code again
/**
* Translates a ROR instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The ROR instruction to translate.
* @param instructions The generated REIL code will be added to this list
*
* @throws InternalTranslationException if any of the arguments are null the
* passed instruction is not an ROR instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
if (instruction.getOperands().size() != 2) {
throw new InternalTranslationException("Error: Argument instruction is not a ror instruction (invalid number of operands)");
}
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final IOperandTree sourceOperand = operands.get(1);
// Load source operand.
final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(sourceResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load destination operand.
final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(targetResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final int linesBefore = instructions.size();
final OperandSize sourceSize = sourceResult.getSize();
final OperandSize targetSize = targetResult.getSize();
final String sourceRegister = sourceResult.getRegister();
final String targetRegister = targetResult.getRegister();
final String rotateMask = environment.getNextVariableString();
final String rotateMaskZero = environment.getNextVariableString();
final String rotateMaskLessOne = environment.getNextVariableString();
final String rotateMaskOne = environment.getNextVariableString();
final String shrValue = environment.getNextVariableString();
final String shredResult = environment.getNextVariableString();
final String shlValue = environment.getNextVariableString();
final String shledResult = environment.getNextVariableString();
final String result = environment.getNextVariableString();
final String tempCf = environment.getNextVariableString();
final String tempOf = environment.getNextVariableString();
final String tempOfLsb = environment.getNextVariableString();
final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(targetSize));
final String modVal = String.valueOf(targetSize.getBitSize());
final String msbMask2nd = String.valueOf(TranslationHelpers.getMsbMask(targetSize) / 2);
final String shiftMsbLsb = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(targetSize));
final String shift2ndMsbLsb = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(targetSize) + 1);
// Make sure to rotate less than the size of the register
instructions.add(ReilHelpers.createMod(offset, sourceSize, sourceRegister, targetSize, modVal, targetSize, rotateMask));
// Find out if the rotate mask is 0 and negate the result
instructions.add(ReilHelpers.createBisz(offset + 1, targetSize, rotateMask, OperandSize.BYTE, rotateMaskZero));
// Find out if the rotate mask is 1
instructions.add(ReilHelpers.createSub(offset + 2, targetSize, rotateMask, targetSize, "1", targetSize, rotateMaskLessOne));
instructions.add(ReilHelpers.createBisz(offset + 3, targetSize, rotateMaskLessOne, OperandSize.BYTE, rotateMaskOne));
// Negate the rotate-mask => ROT to the right
instructions.add(ReilHelpers.createSub(offset + 4, OperandSize.BYTE, "0", OperandSize.BYTE, rotateMask, OperandSize.BYTE, shrValue));
// Perform the rotate
instructions.add(ReilHelpers.createBsh(offset + 5, targetSize, targetRegister, OperandSize.BYTE, shrValue, targetSize, shredResult));
instructions.add(ReilHelpers.createSub(offset + 6, OperandSize.BYTE, modVal, OperandSize.BYTE, rotateMask, OperandSize.BYTE, shlValue));
instructions.add(ReilHelpers.createBsh(offset + 7, targetSize, targetRegister, OperandSize.BYTE, shlValue, targetSize, shledResult));
instructions.add(ReilHelpers.createOr(offset + 8, targetSize, shredResult, targetSize, shledResult, targetSize, result));
// Don't change the flags if the rotate value was zero
final String jmpGoal = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 18);
instructions.add(ReilHelpers.createJcc(offset + 9, OperandSize.BYTE, rotateMaskZero, OperandSize.ADDRESS, jmpGoal));
// Set the CF to the new MSB
instructions.add(ReilHelpers.createAnd(offset + 10, targetSize, result, targetSize, msbMask, targetSize, tempCf));
instructions.add(ReilHelpers.createBsh(offset + 11, targetSize, tempCf, targetSize, shiftMsbLsb, OperandSize.BYTE, Helpers.CARRY_FLAG));
// The OF needs to be set to a different value if the rotate-mask was 1
final String jmpGoal2 = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 15);
instructions.add(ReilHelpers.createJcc(offset + 12, OperandSize.BYTE, rotateMaskOne, OperandSize.ADDRESS, jmpGoal2));
// Set the OF to undefined if the rotate-mask was positive but not 1
instructions.add(ReilHelpers.createUndef(offset + 13, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Jump to the end
final String jmpGoal3 = String.format("%d.%d", instruction.getAddress().toLong(), linesBefore + 18);
instructions.add(ReilHelpers.createJcc(offset + 14, OperandSize.BYTE, "1", OperandSize.ADDRESS, jmpGoal3));
// Set the OF to the old MSB
instructions.add(ReilHelpers.createAnd(offset + 15, targetSize, result, targetSize, msbMask2nd, targetSize, tempOf));
instructions.add(ReilHelpers.createBsh(offset + 16, targetSize, tempOf, targetSize, shift2ndMsbLsb, OperandSize.BYTE, tempOfLsb));
instructions.add(ReilHelpers.createXor(offset + 17, OperandSize.BYTE, tempOfLsb, OperandSize.BYTE, Helpers.CARRY_FLAG, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
Helpers.writeBack(environment, offset + 18, targetOperand, result, targetResult.getSize(), targetResult.getAddress(), targetResult.getType(), instructions);
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class SarTranslator method translate.
/**
* Translates a SAR instruction to REIL code by first performing an unsigned division and then
* (possibly) correcting the result afterwards.
*
* @param environment A valid translation environment.
* @param instruction The SAR instruction to translate.
* @param instructions The generated REIL code will be added to this list
* @throws InternalTranslationException if any of the arguments are null the passed instruction is
* not an SAR instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "sar");
Preconditions.checkArgument(instruction.getOperands().size() == 2, "Error: Argument instruction is not a sar instruction (invalid number of operands)");
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final IOperandTree sourceOperand = operands.get(1);
// Load source operand.
final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(sourceResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load target operand.
final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(targetResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final OperandSize sourceSize = sourceResult.getSize();
final OperandSize targetSize = targetResult.getSize();
final OperandSize resultSize = TranslationHelpers.getNextSize(sourceSize);
final String sourceRegister = sourceResult.getRegister();
final String targetRegister = targetResult.getRegister();
final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(sourceSize));
final String truncateMask = String.valueOf(TranslationHelpers.getAllBitsMask(sourceSize));
final String modValue = String.valueOf(targetSize.getBitSize());
final String shiftMask = environment.getNextVariableString();
final String shiftMaskZero = environment.getNextVariableString();
final String shiftMaskLessOne = environment.getNextVariableString();
final String shiftMaskOne = environment.getNextVariableString();
final String shiftMaskNeg = environment.getNextVariableString();
final String result = environment.getNextVariableString();
final String truncatedResult = environment.getNextVariableString();
final String msbResult = environment.getNextVariableString();
final String isPositive = environment.getNextVariableString();
final String divisor = environment.getNextVariableString();
final String divisionResult = environment.getNextVariableString();
final String negateMask = environment.getNextVariableString();
final String twoComplementResult = environment.getNextVariableString();
final String shiftBit = environment.getNextVariableString();
final String shiftedBitsMask = environment.getNextVariableString();
final String shiftedBits = environment.getNextVariableString();
final String shiftedBitsZero = environment.getNextVariableString();
final String shiftedBitsNonZero = environment.getNextVariableString();
final String shiftAmountMinOne = environment.getNextVariableString();
final String isNegative = environment.getNextVariableString();
final String roundTowNegInf = environment.getNextVariableString();
final String cfBitMask = environment.getNextVariableString();
final String cfBitResult = environment.getNextVariableString();
final String tmpCf = environment.getNextVariableString();
// Generate the unsigned value of the shift value
// Note: this code must not be moved further down, otherwise all the offset become invalid
final Pair<String, String> targetRegister1Abs = Helpers.generateAbs(environment, offset, targetRegister, targetSize, instructions);
final String targetRegister1Absolute = targetRegister1Abs.second();
offset = baseOffset + instructions.size();
// Since the Reil infrastructure lacks ability to establish branches between instructions
// objects in (as opposed to raw offsets) we need this hack to correct the jump target offsets
// The reason is that the are already some instructions in the list so, e.g., createMod(offset +
// 1) does not actually create an instruction at offset 1 but at offset delta + 1
final int delta = instructions.size();
// Make sure to shift less than the size of the target register
instructions.add(ReilHelpers.createMod(offset, sourceSize, sourceRegister, targetSize, modValue, targetSize, shiftMask));
// Find out if the shift mask is zero or non-zero
instructions.add(ReilHelpers.createBisz(offset + 1, targetSize, shiftMask, OperandSize.BYTE, shiftMaskZero));
// Bail out if shift count is zero
final String jmpEnd = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
instructions.add(ReilHelpers.createJcc(offset + 2, OperandSize.BYTE, shiftMaskZero, OperandSize.ADDRESS, jmpEnd));
// AF is undefined if shift count is non-zero
instructions.add(ReilHelpers.createUndef(offset + 3, OperandSize.BYTE, Helpers.AUXILIARY_FLAG));
// The carry flag corresponds to the last bit shifted out of the operand
instructions.add(ReilHelpers.createSub(offset + 4, OperandSize.BYTE, shiftMask, OperandSize.BYTE, "1", OperandSize.BYTE, shiftAmountMinOne));
instructions.add(ReilHelpers.createBsh(offset + 5, OperandSize.BYTE, "1", OperandSize.BYTE, shiftAmountMinOne, OperandSize.BYTE, cfBitMask));
instructions.add(ReilHelpers.createAnd(offset + 6, targetSize, targetRegister, OperandSize.BYTE, cfBitMask, OperandSize.BYTE, cfBitResult));
instructions.add(ReilHelpers.createBisz(offset + 7, OperandSize.BYTE, cfBitResult, OperandSize.BYTE, tmpCf));
instructions.add(ReilHelpers.createXor(offset + 8, OperandSize.BYTE, "1", OperandSize.BYTE, tmpCf, OperandSize.BYTE, Helpers.CARRY_FLAG));
// Find out if the shift mask is 1
instructions.add(ReilHelpers.createSub(offset + 9, targetSize, "1", targetSize, shiftMask, targetSize, shiftMaskLessOne));
instructions.add(ReilHelpers.createBisz(offset + 10, targetSize, shiftMaskLessOne, OperandSize.BYTE, shiftMaskOne));
// Negate the shift-mask so we can perform a right shift
instructions.add(ReilHelpers.createSub(offset + 11, targetSize, "0", targetSize, shiftMask, targetSize, shiftMaskNeg));
// Test if the highest bit of the input value was set; if so, we need to perform a sign
// extension on the shift result
instructions.add(ReilHelpers.createAnd(offset + 12, sourceSize, msbMask, targetSize, targetRegister, sourceSize, msbResult));
instructions.add(ReilHelpers.createBisz(offset + 13, sourceSize, msbResult, OperandSize.BYTE, isPositive));
instructions.add(ReilHelpers.createXor(offset + 14, OperandSize.BYTE, "1", OperandSize.BYTE, isPositive, OperandSize.BYTE, isNegative));
// Create divisor based on shift amount and calculate unsigned division
instructions.add(ReilHelpers.createBsh(offset + 15, OperandSize.DWORD, "1", OperandSize.BYTE, shiftMask, OperandSize.DWORD, divisor));
instructions.add(ReilHelpers.createDiv(offset + 16, targetSize, targetRegister1Absolute, OperandSize.DWORD, divisor, OperandSize.DWORD, divisionResult));
// If the MSB of the value to be shifted is set, we create a mask of 0xFFFFFFFF to convert the
// result to two's complement
instructions.add(ReilHelpers.createSub(offset + 17, OperandSize.BYTE, "0", OperandSize.BYTE, isNegative, OperandSize.DWORD, negateMask));
instructions.add(ReilHelpers.createXor(offset + 18, OperandSize.DWORD, divisionResult, OperandSize.DWORD, negateMask, OperandSize.DWORD, result));
// If the source value is positive we need to skip adding one to the result
final String jmpSkipTwosComplement = String.format("%s.%s", instruction.getAddress().toLong(), delta + 28);
instructions.add(ReilHelpers.createJcc(offset + 19, OperandSize.BYTE, isPositive, OperandSize.ADDRESS, jmpSkipTwosComplement));
// Convert to two's complement by adding one to the result
instructions.add(ReilHelpers.createAdd(offset + 20, OperandSize.DWORD, result, OperandSize.BYTE, "1", OperandSize.DWORD, twoComplementResult));
// We need to subtract one to realize "rounding towards infinity" iff the bits shifted out are
// not all zeros
// First we need to mask out all the bits which are shifted out on the right side
instructions.add(ReilHelpers.createBsh(offset + 21, OperandSize.BYTE, "1", targetSize, shiftMask, targetSize, shiftBit));
instructions.add(ReilHelpers.createSub(offset + 22, targetSize, shiftBit, OperandSize.BYTE, "1", targetSize, shiftedBitsMask));
instructions.add(ReilHelpers.createAnd(offset + 23, targetSize, targetRegister, targetSize, shiftedBitsMask, targetSize, shiftedBits));
// Possibly subtract one from the result, i.e. round towards negative infinity
instructions.add(ReilHelpers.createBisz(offset + 24, targetSize, shiftedBits, OperandSize.BYTE, shiftedBitsZero));
instructions.add(ReilHelpers.createXor(offset + 25, OperandSize.BYTE, "1", OperandSize.BYTE, shiftedBitsZero, OperandSize.BYTE, shiftedBitsNonZero));
instructions.add(ReilHelpers.createAnd(offset + 26, OperandSize.BYTE, isNegative, OperandSize.BYTE, shiftedBitsNonZero, OperandSize.BYTE, roundTowNegInf));
instructions.add(ReilHelpers.createSub(offset + 27, OperandSize.DWORD, twoComplementResult, OperandSize.BYTE, roundTowNegInf, targetSize, result));
// Truncate the result to the correct size (skip two complement conversion jump target)
instructions.add(ReilHelpers.createAnd(offset + 28, resultSize, result, sourceSize, truncateMask, sourceSize, truncatedResult));
// Don't change the flags if the shift value was zero
final String jmpGoal = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
instructions.add(ReilHelpers.createJcc(offset + 29, OperandSize.BYTE, shiftMaskZero, OperandSize.ADDRESS, jmpGoal));
// The SF is always 0
instructions.add(ReilHelpers.createBisz(offset + 30, OperandSize.BYTE, isPositive, OperandSize.BYTE, Helpers.SIGN_FLAG));
// Set the ZF
instructions.add(ReilHelpers.createBisz(offset + 31, sourceSize, truncatedResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
// If shift count is one, we need to zero the OF
final String jmpDontZeroOF = String.format("%s.%s", instruction.getAddress().toLong(), delta + 34);
instructions.add(ReilHelpers.createJcc(offset + 32, OperandSize.BYTE, shiftMaskOne, OperandSize.ADDRESS, jmpDontZeroOF));
instructions.add(ReilHelpers.createStr(offset + 33, OperandSize.BYTE, "0", OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Set the OF to undefined if the shift-mask was not zero and not one
final String shiftCountZeroOrOne = environment.getNextVariableString();
instructions.add(ReilHelpers.createOr(offset + 34, OperandSize.BYTE, shiftMaskOne, OperandSize.BYTE, shiftMaskZero, OperandSize.BYTE, shiftCountZeroOrOne));
final String jmpSkipUndefOF = String.format("%s.%s", instruction.getAddress().toLong(), delta + 38);
instructions.add(ReilHelpers.createJcc(offset + 35, OperandSize.BYTE, shiftCountZeroOrOne, OperandSize.ADDRESS, jmpSkipUndefOF));
instructions.add(ReilHelpers.createUndef(offset + 36, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// always jump to writeback instruction if OF was undefined
final String jmpGoal3 = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
instructions.add(ReilHelpers.createJcc(offset + 37, OperandSize.BYTE, "1", OperandSize.ADDRESS, jmpGoal3));
// OF is always zero for the SAR instruction
instructions.add(ReilHelpers.createStr(offset + 38, OperandSize.BYTE, "0", OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
final int sizeBefore = instructions.size();
Helpers.writeBack(environment, offset + 39, targetOperand, result, targetSize, targetResult.getAddress(), targetResult.getType(), instructions);
final int sizeAfter = instructions.size();
instructions.add(ReilHelpers.createNop((sizeAfter - sizeBefore - 1) + offset + 40));
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class SbbTranslator method translate.
/**
* Translates a SBB instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The SBB instruction to translate.
* @param instructions The generated REIL code will be added to this list
*
* @throws InternalTranslationException if any of the arguments are null the passed instruction is
* not an SBB instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "sbb");
if (instruction.getOperands().size() != 2) {
throw new InternalTranslationException("Error: Argument instruction is not a sbb instruction (invalid number of operand)");
}
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final IOperandTree sourceOperand = operands.get(1);
// Load source operand.
final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(sourceResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load target operand.
final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(targetResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
if (sourceResult.getSize() != targetResult.getSize()) {
throw new InternalTranslationException("Error: The operands of SBB instructions must have equal size");
}
final OperandSize size = sourceResult.getSize();
final String sourceRegister = sourceResult.getRegister();
final String targetRegister = targetResult.getRegister();
final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(size));
final String carryMask = String.valueOf(Helpers.getCarryMask(size));
final String truncateMask = String.valueOf(TranslationHelpers.getAllBitsMask(size));
final String shiftValue = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(size));
final String shiftCarry = String.valueOf(-size.getBitSize());
final OperandSize resultSize = TranslationHelpers.getNextSize(size);
final String msb1 = environment.getNextVariableString();
final String msb2 = environment.getNextVariableString();
final String subResult = environment.getNextVariableString();
final String subResultTemp = environment.getNextVariableString();
final String msbResult = environment.getNextVariableString();
final String msbSameBefore = environment.getNextVariableString();
final String msbChanged = environment.getNextVariableString();
final String tempOf = environment.getNextVariableString();
final String tempCf = environment.getNextVariableString();
final String truncatedResult = environment.getNextVariableString();
// Isolate the MSBs of the two operands
instructions.add(ReilHelpers.createAnd(offset, size, sourceRegister, size, msbMask, size, msb1));
instructions.add(ReilHelpers.createAnd(offset + 1, size, targetRegister, size, msbMask, size, msb2));
// Perform the subtraction
instructions.add(ReilHelpers.createSub(offset + 2, size, sourceRegister, size, targetRegister, resultSize, subResultTemp));
instructions.add(ReilHelpers.createSub(offset + 3, resultSize, subResultTemp, OperandSize.BYTE, Helpers.CARRY_FLAG, resultSize, subResult));
// Isolate the MSB of the result and put it into the Sign Flag
instructions.add(ReilHelpers.createAnd(offset + 4, resultSize, subResult, resultSize, msbMask, size, msbResult));
instructions.add(ReilHelpers.createBsh(offset + 5, size, msbResult, size, shiftValue, OperandSize.BYTE, Helpers.SIGN_FLAG));
// Find out if the MSB of the two operands were different and whether the MSB of the first
// operand changed
instructions.add(ReilHelpers.createXor(offset + 6, size, msb1, size, msb2, size, msbSameBefore));
instructions.add(ReilHelpers.createXor(offset + 7, size, msb1, size, msbResult, size, msbChanged));
instructions.add(ReilHelpers.createAnd(offset + 8, size, msbSameBefore, size, msbChanged, size, tempOf));
// Write the result into the Overflow Flag
instructions.add(ReilHelpers.createBsh(offset + 9, size, tempOf, size, shiftValue, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
// Update the Carry Flag
instructions.add(ReilHelpers.createAnd(offset + 10, resultSize, subResult, resultSize, carryMask, resultSize, tempCf));
instructions.add(ReilHelpers.createBsh(offset + 11, resultSize, tempCf, resultSize, shiftCarry, OperandSize.BYTE, Helpers.CARRY_FLAG));
// Truncate the result to fit into the target
instructions.add(ReilHelpers.createAnd(offset + 12, resultSize, subResult, resultSize, truncateMask, size, truncatedResult));
// Update the Zero Flag
instructions.add(ReilHelpers.createBisz(offset + 13, size, truncatedResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
// Write the result of the subtraction back to the target register
Helpers.writeBack(environment, offset + 14, targetOperand, truncatedResult, size, targetResult.getAddress(), targetResult.getType(), instructions);
}
Aggregations