Merge remote-tracking branch 'origin/GP-0_Dan_movePcodeEmulatePackages'

This commit is contained in:
Ryan Kurtz 2023-04-25 06:25:29 -04:00
commit 520c77e77d
126 changed files with 5 additions and 6 deletions

View file

@ -1,63 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.pcoderaw.PcodeOpRaw;
import ghidra.program.model.address.Address;
/// \brief A breakpoint object
///
/// This is a base class for breakpoint objects in an emulator. The breakpoints are implemented
/// as callback method, which is overridden for the particular behavior needed by the emulator.
/// Each derived class must override either
/// - pcodeCallback()
/// - addressCallback()
///
/// depending on whether the breakpoint is tailored for a particular pcode op or for
/// a machine address.
public class BreakCallBack {
protected Emulate emulate; ///< The emulator currently associated with this breakpoint
public BreakCallBack() { ///< Generic breakpoint constructor
emulate = null;
}
/// This routine is invoked during emulation, if this breakpoint has somehow been associated with
/// this kind of pcode op. The callback can perform any operation on the emulator context it wants.
/// It then returns \b true if these actions are intended to replace the action of the pcode op itself.
/// Or it returns \b false if the pcode op should still have its normal effect on the emulator context.
/// \param op is the particular pcode operation where the break occurs.
/// \return \b true if the normal pcode op action should not occur
public boolean pcodeCallback(PcodeOpRaw op) { ///< Call back method for pcode based breakpoints
return false;
}
/// This routine is invoked during emulation, if this breakpoint has somehow been associated with
/// this address. The callback can perform any operation on the emulator context it wants. It then
/// returns \b true if these actions are intended to replace the action of the \b entire machine
/// instruction at this address. Or it returns \b false if the machine instruction should still be
/// executed normally.
/// \param addr is the address where the break has occurred
/// \return \b true if the machine instruction should not be executed
public boolean addressCallback(Address addr) { ///< Call back method for address based breakpoints
return false;
}
public void setEmulate(Emulate emu) { ///< Associate a particular emulator with this breakpoint
emulate = emu;
}
}

View file

@ -1,60 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.pcoderaw.PcodeOpRaw;
import ghidra.program.model.address.Address;
/// \brief A collection of breakpoints for the emulator
///
/// A BreakTable keeps track of an arbitrary number of breakpoints for an emulator.
/// Breakpoints are either associated with a particular user-defined pcode op,
/// or with a specific machine address (as in a standard debugger). Through the BreakTable
/// object, an emulator can invoke breakpoints through the two methods
/// - doPcodeOpBreak()
/// - doAddressBreak()
///
/// depending on the type of breakpoint they currently want to invoke
public interface BreakTable {
/// \brief Associate a particular emulator with breakpoints in this table
///
/// Breakpoints may need access to the context in which they are invoked. This
/// routine provides the context for all breakpoints in the table.
/// \param emu is the Emulate context
public abstract void setEmulate(Emulate emu);
/// \brief Invoke any breakpoints associated with this particular pcodeop
///
/// Within the table, the first breakpoint which is designed to work with this particular
/// kind of pcode operation is invoked. If there was a breakpoint and it was designed
/// to \e replace the action of the pcode op, then \b true is returned.
/// \param curop is the instance of a pcode op to test for breakpoints
/// \return \b true if the action of the pcode op is performed by the breakpoint
public abstract boolean doPcodeOpBreak(PcodeOpRaw curop);
/// \brief Invoke any breakpoints associated with this machine address
///
/// Within the table, the first breakpoint which is designed to work with at this address
/// is invoked. If there was a breakpoint, and if it was designed to \e replace
/// the action of the machine instruction, then \b true is returned.
/// \param addr is address to test for breakpoints
/// \return \b true is the machine instruction has been replaced by a breakpoint
public abstract boolean doAddressBreak(Address addr);
}

View file

@ -1,162 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import generic.stl.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.pcoderaw.PcodeOpRaw;
import ghidra.program.model.address.Address;
/// \brief A basic instantiation of a breakpoint table
///
/// This object allows breakpoints to registered in the table via either
/// - registerPcodeCallback() or
/// = registerAddressCallback()
///
/// Breakpoints are stored in map containers, and the core BreakTable methods
/// are implemented to search in these containers
public class BreakTableCallBack implements BreakTable {
public static final String DEFAULT_NAME = "*";
private Emulate emulate;
private SleighLanguage language;
// a container of address based breakpoints
private MapSTL<Address, BreakCallBack> addressCallback =
new ComparableMapSTL<>();
// a container of pcode based breakpoints
private MapSTL<Long, BreakCallBack> pcodeCallback = new ComparableMapSTL<>();
private BreakCallBack defaultPcodeCallback;
/// The break table needs a translator object so user-defined pcode ops can be registered against
/// by name.
/// \param t is the translator object
public BreakTableCallBack(SleighLanguage language) {
this.language = language;
}
/// Any time the emulator is about to execute a user-defined pcode op with the given name,
/// the indicated breakpoint is invoked first. The break table does \e not assume responsibility
/// for freeing the breakpoint object.
/// \param name is the name of the user-defined pcode op
/// \param func is the breakpoint object to associate with the pcode op
public void registerPcodeCallback(String name, BreakCallBack func) {
func.setEmulate(emulate);
if (DEFAULT_NAME.equals(name)) {
defaultPcodeCallback = func;
return;
}
int numUserOps = language.getNumberOfUserDefinedOpNames();
for (int i = 0; i < numUserOps; i++) {
if (name.equals(language.getUserDefinedOpName(i))) {
pcodeCallback.add((long) i, func);
return;
}
}
// tell them what names are valid, probably not worth doing, but hate just getting no context on an error...
StringBuilder names = new StringBuilder();
for (int i = 0; i < numUserOps; i++) {
names.append(language.getUserDefinedOpName(i));
if (i < (numUserOps - 1))
names.append(", ");
}
throw new LowlevelError("Bad userop name: " + name + "\n" + "Must be one of:\n" + names);
}
/// Unregister the currently registered PcodeCallback handler for the
/// specified name
/// \param name is the name of the user-defined pcode op
public void unregisterPcodeCallback(String name) {
if (DEFAULT_NAME.equals(name)) {
defaultPcodeCallback = null;
return;
}
int numUserOps = language.getNumberOfUserDefinedOpNames();
for (int i = 0; i < numUserOps; i++) {
if (name.equals(language.getUserDefinedOpName(i))) {
pcodeCallback.remove((long) i);
return;
}
}
throw new LowlevelError("Bad userop name: " + name);
}
/// Any time the emulator is about to execute (the pcode translation of) a particular machine
/// instruction at this address, the indicated breakpoint is invoked first. The break table
/// does \e not assume responsibility for freeing the breakpoint object.
/// \param addr is the address associated with the breakpoint
/// \param func is the breakpoint being registered
public void registerAddressCallback(Address addr, BreakCallBack func) {
func.setEmulate(emulate);
addressCallback.add(addr, func);
}
public void unregisterAddressCallback(Address addr) {
addressCallback.remove(addr);
}
/// This routine invokes the setEmulate method on each breakpoint currently in the table
/// \param emu is the emulator to be associated with the breakpoints
@Override
public void setEmulate(Emulate emu) {
// Make sure all callbbacks are aware of new emulator
emulate = emu;
IteratorSTL<Pair<Address, BreakCallBack>> iter1;
for (iter1 = addressCallback.begin(); !iter1.isEnd(); iter1.increment()) {
iter1.get().second.setEmulate(emu);
}
if (defaultPcodeCallback != null) {
defaultPcodeCallback.setEmulate(emu);
}
IteratorSTL<Pair<Long, BreakCallBack>> iter2;
for (iter2 = pcodeCallback.begin(); !iter2.isEnd(); iter2.increment()) {
iter2.get().second.setEmulate(emu);
}
}
/// This routine examines the pcode-op based container for any breakpoints associated with the
/// given op. If one is found, its pcodeCallback method is invoked.
/// \param curop is pcode op being checked for breakpoints
/// \return \b true if the breakpoint exists and returns \b true, otherwise return \b false
@Override
public boolean doPcodeOpBreak(PcodeOpRaw curop) {
long val = curop.getInput(0).getOffset();
IteratorSTL<Pair<Long, BreakCallBack>> iter = pcodeCallback.find(val);
if (iter.isEnd()) {
if (defaultPcodeCallback != null) {
return defaultPcodeCallback.pcodeCallback(curop);
}
return false;
}
return iter.get().second.pcodeCallback(curop);
}
/// This routine examines the address based container for any breakpoints associated with the
/// given address. If one is found, its addressCallback method is invoked.
/// \param addr is the address being checked for breakpoints
/// \return \b true if the breakpoint exists and returns \b true, otherwise return \b false
@Override
public boolean doAddressBreak(Address addr) {
IteratorSTL<Pair<Address, BreakCallBack>> iter = addressCallback.find(addr);
if (iter.isEnd()) {
return false;
}
return iter.get().second.addressCallback(addr);
}
}

View file

@ -1,774 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.memstate.MemoryState;
import ghidra.pcode.memstate.UniqueMemoryBank;
import ghidra.pcode.opbehavior.*;
import ghidra.pcode.pcoderaw.PcodeOpRaw;
import ghidra.program.disassemble.Disassembler;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
/// \brief A SLEIGH based implementation of the Emulate interface
///
/// This implementation uses a Translate object to translate machine instructions into
/// pcode and caches pcode ops for later use by the emulator. The pcode is cached as soon
/// as the execution address is set, either explicitly, or via branches and fallthrus. There
/// are additional methods for inspecting the pcode ops in the current instruction as a sequence.
public class Emulate {
private MemoryState memstate; // the memory state of the emulator.
private UniqueMemoryBank uniqueBank;
private BreakTable breaktable; ///< The table of breakpoints
private Address current_address; ///< Address of current instruction being executed
private Address last_execute_address;
private volatile EmulateExecutionState executionState = EmulateExecutionState.STOPPED;
private RuntimeException faultCause;
private int current_op; ///< Index of current pcode op within machine instruction
private int last_op; /// index of last pcode op executed
private int instruction_length; ///< Length of current instruction in bytes (must include any delay slots)
private final SleighLanguage language;
private final AddressFactory addrFactory;
private Register pcReg;
private InstructionBlock lastPseudoInstructionBlock;
private Disassembler pseudoDisassembler;
private Instruction pseudoInstruction;
private PcodeOp[] pcode; ///< The cache of current pcode ops
private RegisterValue nextContextRegisterValue = null;
private EmulateMemoryStateBuffer memBuffer; // used for instruction parsing
private EmulateInstructionStateModifier instructionStateModifier;
/// \param t is the SLEIGH translator
/// \param s is the MemoryState the emulator should manipulate
/// \param b is the table of breakpoints the emulator should invoke
public Emulate(SleighLanguage lang, MemoryState s, BreakTable b) {
memstate = s;
this.language = lang;
this.addrFactory = lang.getAddressFactory();
pcReg = lang.getProgramCounter();
breaktable = b;
breaktable.setEmulate(this);
memBuffer =
new EmulateMemoryStateBuffer(s, addrFactory.getDefaultAddressSpace().getMinAddress());
uniqueBank =
new UniqueMemoryBank(lang.getAddressFactory().getUniqueSpace(), lang.isBigEndian());
memstate.setMemoryBank(uniqueBank);
// emitterContext = new EmulateDisassemblerContext(lang, s);
pseudoDisassembler =
Disassembler.getDisassembler(lang, addrFactory, TaskMonitor.DUMMY, null);
initInstuctionStateModifier();
}
public void dispose() {
executionState = EmulateExecutionState.STOPPED;
}
@SuppressWarnings("unchecked")
private void initInstuctionStateModifier() {
String classname = language
.getProperty(GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
if (classname == null) {
return;
}
try {
Class<?> c = Class.forName(classname);
if (!EmulateInstructionStateModifier.class.isAssignableFrom(c)) {
Msg.error(this,
"Language " + language.getLanguageID() + " does not specify a valid " +
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
throw new RuntimeException(classname + " does not implement interface " +
EmulateInstructionStateModifier.class.getName());
}
Class<? extends EmulateInstructionStateModifier> instructionStateModifierClass =
(Class<? extends EmulateInstructionStateModifier>) c;
Constructor<? extends EmulateInstructionStateModifier> constructor =
instructionStateModifierClass.getConstructor(Emulate.class);
instructionStateModifier = constructor.newInstance(this);
}
catch (Exception e) {
Msg.error(this, "Language " + language.getLanguageID() + " does not specify a valid " +
GhidraLanguagePropertyKeys.EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS);
throw new RuntimeException(
"Failed to instantiate " + classname + " for language " + language.getLanguageID(),
e);
}
}
public Language getLanguage() {
return language;
}
/// Since the emulator can single step through individual pcode operations, the machine state
/// may be halted in the \e middle of a single machine instruction, unlike conventional debuggers.
/// This routine can be used to determine if execution is actually at the beginning of a machine
/// instruction.
/// \return \b true if the next pcode operation is at the start of the instruction translation
public boolean isInstructionStart() {
return executionState == EmulateExecutionState.STOPPED ||
executionState == EmulateExecutionState.BREAKPOINT;
}
/**
* @return the current emulator execution state
*/
public EmulateExecutionState getExecutionState() {
return executionState;
}
/// \return the currently executing machine address
public Address getExecuteAddress() {
return current_address;
}
/// \return the last address
public Address getLastExecuteAddress() {
return last_execute_address;
}
public EmulateDisassemblerContext getNewDisassemblerContext() {
return new EmulateDisassemblerContext(language, getContextRegisterValue());
}
/**
* Get length of instruction including any delay-slotted instructions.
* Must be called by emitPcode with lastPseudoInstructionBlock properly set.
* @param instr
* @return length of instruction in bytes for use in computing fall-through location
*/
private int getInstructionLength(Instruction instr) throws InstructionDecodeException {
int length = instr.getLength();
int delaySlots = instr.getDelaySlotDepth();
while (delaySlots != 0) {
try {
Address nextAddr = instr.getAddress().addNoWrap(instr.getLength());
Instruction nextInstr = lastPseudoInstructionBlock.getInstructionAt(nextAddr);
if (nextInstr == null) {
throw new InstructionDecodeException("Failed to parse delay slot instruction",
nextAddr);
}
instr = nextInstr;
length += instr.getLength();
--delaySlots;
}
catch (AddressOverflowException e) {
throw new InstructionDecodeException(
"Failed to parse delay slot instruction at end of address space",
instr.getAddress());
}
}
return length;
}
private PcodeOp[] emitPcode(Address addr) throws InstructionDecodeException {
memBuffer.setAddress(addr);
pcode = null;
pseudoInstruction = null;
if (lastPseudoInstructionBlock != null) {
pseudoInstruction = lastPseudoInstructionBlock.getInstructionAt(addr);
if (pseudoInstruction != null) {
instruction_length = getInstructionLength(pseudoInstruction);
return pseudoInstruction.getPcode(false);
}
InstructionError error = lastPseudoInstructionBlock.getInstructionConflict();
if (error != null && addr.equals(error.getInstructionAddress())) {
throw new InstructionDecodeException(error.getConflictMessage(), addr);
}
}
lastPseudoInstructionBlock =
pseudoDisassembler.pseudoDisassembleBlock(memBuffer, nextContextRegisterValue, 1);
nextContextRegisterValue = null;
if (lastPseudoInstructionBlock != null) {
pseudoInstruction = lastPseudoInstructionBlock.getInstructionAt(addr);
if (pseudoInstruction != null) {
instruction_length = getInstructionLength(pseudoInstruction);
return pseudoInstruction.getPcode(false);
}
InstructionError error = lastPseudoInstructionBlock.getInstructionConflict();
if (error != null && addr.equals(error.getInstructionAddress())) {
throw new InstructionDecodeException(error.getConflictMessage(), addr);
}
}
throw new InstructionDecodeException("unknown reason", addr);
}
/**
* Returns the current context register value. The context value returned reflects
* its state when the previously executed instruction was
* parsed/executed. The context value returned will feed into the next
* instruction to be parsed with its non-flowing bits cleared and
* any future context state merged in. If no instruction has been executed,
* the explicitly set context will be returned. A null value is returned
* if no context register is defined by the language or initial context has
* not been set.
*/
public RegisterValue getContextRegisterValue() {
Register contextReg = language.getContextBaseRegister();
if (contextReg == Register.NO_CONTEXT) {
return null;
}
if (pseudoInstruction != null) {
return pseudoInstruction.getRegisterValue(contextReg);
}
return nextContextRegisterValue;
}
/**
* Sets the context register value at the current execute address.
* The Emulator should not be running when this method is invoked.
* Only flowing context bits should be set, as non-flowing bits
* will be cleared prior to parsing on instruction. In addition,
* any future context state set by the pcode emitter will
* take precedence over context set using this method. This method
* is primarily intended to be used to establish the initial
* context state.
* @param regValue
*/
public void setContextRegisterValue(RegisterValue regValue) {
if (executionState != EmulateExecutionState.STOPPED &&
executionState != EmulateExecutionState.BREAKPOINT) {
throw new IllegalStateException("emulator is not STOPPED");
}
if (regValue != null) {
Register reg = regValue.getRegister();
if (!reg.isProcessorContext()) {
throw new IllegalArgumentException("processor context register required");
}
if (!reg.isBaseRegister()) {
regValue = regValue.getBaseRegisterValue();
reg = regValue.getRegister();
if (nextContextRegisterValue != null) {
regValue = nextContextRegisterValue.combineValues(regValue);
}
}
if (!reg.equals(language.getContextBaseRegister())) {
throw new IllegalArgumentException("invalid processor context register");
}
}
nextContextRegisterValue = regValue;
lastPseudoInstructionBlock = null;
pseudoInstruction = null;
}
/// Update the iterator into the current pcode cache, and if necessary, generate
/// the pcode for the fallthru instruction and reset the iterator.
public void fallthruOp() {
current_op += 1;
if (current_op >= pcode.length) {
last_op = -1;
setCurrentAddress(current_address.addWrap(instruction_length));
}
}
public void executeConditionalBranch(PcodeOpRaw op) {
Varnode condVar = op.getInput(1);
boolean takeBranch = false;
if (condVar.getSize() > 8) {
takeBranch = !memstate.getBigInteger(condVar, false).equals(BigInteger.ZERO);
}
else {
takeBranch = memstate.getValue(condVar) != 0;
}
if (takeBranch) {
executeBranch(op);
}
else {
fallthruOp();
}
}
/// Since the full instruction is cached, we can do relative branches properly
/// \param op is the particular branch op being executed
public void executeBranch(PcodeOpRaw op) {
Address destaddr = op.getInput(0).getAddress();
if (destaddr.getAddressSpace().isConstantSpace()) {
long id = destaddr.getOffset();
id = id + current_op;
current_op = (int) id;
if (current_op == pcode.length) {
fallthruOp();
}
else if ((current_op < 0) || (current_op >= pcode.length)) {
throw new LowlevelError("Bad intra-instruction branch");
}
}
else {
setCurrentAddress(destaddr);
}
}
/// Give instuctionStateModifier first shot at executing custom pcodeop,
/// if not supported look for a breakpoint for the given user-defined op and invoke it.
/// If it doesn't exist, or doesn't replace the action, throw an exception
/// \param op is the particular user-defined op being executed
public void executeCallother(PcodeOpRaw op) throws UnimplementedCallOtherException {
if ((instructionStateModifier == null || !instructionStateModifier.executeCallOther(op)) &&
!breaktable.doPcodeOpBreak(op)) {
int userOp = (int) op.getInput(0).getOffset();
String pcodeOpName = language.getUserDefinedOpName(userOp);
throw new UnimplementedCallOtherException(op, pcodeOpName);
}
fallthruOp();
}
/// Set the current execution address and cache the pcode translation of the machine instruction
/// at that address
/// \param addr is the address where execution should continue
public void setExecuteAddress(Address addr) {
if (addr != null && addr.equals(current_address)) {
return;
}
last_execute_address = null;
setCurrentAddress(addr);
}
private void setCurrentAddress(Address addr) {
current_address = addr;
memstate.setValue(pcReg, current_address.getAddressableWordOffset());
executionState = EmulateExecutionState.STOPPED;
faultCause = null;
}
/// This routine executes an entire machine instruction at once, as a conventional debugger step
/// function would do. If execution is at the start of an instruction, the breakpoints are checked
/// and invoked as needed for the current address. If this routine is invoked while execution is
/// in the middle of a machine instruction, execution is continued until the current instruction
/// completes.
public void executeInstruction(boolean stopAtBreakpoint, TaskMonitor monitor)
throws CancelledException, LowlevelError, InstructionDecodeException {
if (monitor == null) {
monitor = TaskMonitor.DUMMY;
}
if (executionState == EmulateExecutionState.STOPPED) {
if (last_execute_address == null && instructionStateModifier != null) {
instructionStateModifier.initialExecuteCallback(this, current_address,
nextContextRegisterValue);
}
if (breaktable.doAddressBreak(current_address) && stopAtBreakpoint) {
executionState = EmulateExecutionState.BREAKPOINT;
return;
}
}
else if (executionState == EmulateExecutionState.FAULT) {
// re-throw fault
throw faultCause;
}
else if (executionState != EmulateExecutionState.BREAKPOINT) {
// state is either INSTRUCTION_DECODE or EXECUTE
throw new LowlevelError("Already executing");
}
try {
executionState = EmulateExecutionState.INSTRUCTION_DECODE;
if (language.numSections() == 0) {
uniqueBank.clear(); // OK to clear if named sections and crossbuilds do not exist in language
}
pcode = emitPcode(current_address);
last_execute_address = current_address;
current_op = 0;
if (pcode == null) {
throw new InstructionDecodeException("Unexpected instruction pcode error",
current_address);
}
executionState = EmulateExecutionState.EXECUTE;
do {
monitor.checkCanceled();
executeCurrentOp();
}
while (executionState == EmulateExecutionState.EXECUTE);
if (instructionStateModifier != null) {
instructionStateModifier.postExecuteCallback(this, last_execute_address, pcode,
last_op, current_address);
}
}
catch (RuntimeException e) {
faultCause = e;
executionState = EmulateExecutionState.FAULT;
throw e;
}
}
/// \return the memory state object which this emulator uses
public MemoryState getMemoryState() {
return memstate;
}
/// This method executes a single pcode operation, the current one (returned by getCurrentOp()).
/// The MemoryState of the emulator is queried and changed as needed to accomplish this.
private void executeCurrentOp() throws LowlevelError {
if (current_op >= pcode.length) {
fallthruOp();
return;
}
last_op = current_op;
PcodeOp op = pcode[current_op];
if (op.getOpcode() == PcodeOp.UNIMPLEMENTED) {
throw new UnimplementedInstructionException(current_address);
}
PcodeOpRaw raw = new PcodeOpRaw(op);
OpBehavior behave = raw.getBehavior();
if (behave == null) {
// unsupported opcode
throw new LowlevelError(
"Unsupported pcode op (opcode=" + op.getOpcode() + ", seq=" + op.getSeqnum() + ")");
}
if (behave instanceof UnaryOpBehavior) {
UnaryOpBehavior unaryBehave = (UnaryOpBehavior) behave;
Varnode in1var = op.getInput(0);
Varnode outvar = op.getOutput();
if (in1var.getSize() > 8 || outvar.getSize() > 8) {
BigInteger in1 = memstate.getBigInteger(op.getInput(0), false);
BigInteger out = unaryBehave.evaluateUnary(op.getOutput().getSize(),
op.getInput(0).getSize(), in1);
memstate.setValue(op.getOutput(), out);
}
else {
long in1 = memstate.getValue(op.getInput(0));
long out = unaryBehave.evaluateUnary(op.getOutput().getSize(),
op.getInput(0).getSize(), in1);
memstate.setValue(op.getOutput(), out);
}
fallthruOp();
}
else if (behave instanceof BinaryOpBehavior) {
BinaryOpBehavior binaryBehave = (BinaryOpBehavior) behave;
Varnode in1var = op.getInput(0);
Varnode in2var = op.getInput(1);
Varnode outvar = op.getOutput();
if (in1var.getSize() > 8 || in2var.getSize() > 8 || outvar.getSize() > 8) {
BigInteger in1 = memstate.getBigInteger(op.getInput(0), false);
BigInteger in2 = memstate.getBigInteger(op.getInput(1), false);
BigInteger out = binaryBehave.evaluateBinary(outvar.getSize(),
op.getInput(0).getSize(), in1, in2);
memstate.setValue(outvar, out);
}
else {
long in1 = memstate.getValue(op.getInput(0));
long in2 = memstate.getValue(op.getInput(1));
long out = binaryBehave.evaluateBinary(outvar.getSize(), op.getInput(0).getSize(),
in1, in2);
memstate.setValue(outvar, out);
}
fallthruOp(); // All binary ops are fallthrus
}
else {
switch (behave.getOpCode()) {
case PcodeOp.LOAD:
executeLoad(raw);
fallthruOp();
break;
case PcodeOp.STORE:
executeStore(raw);
fallthruOp();
break;
case PcodeOp.BRANCH:
executeBranch(raw);
break;
case PcodeOp.CBRANCH:
executeConditionalBranch(raw);
break;
case PcodeOp.BRANCHIND:
executeBranchind(raw);
break;
case PcodeOp.CALL:
executeCall(raw);
break;
case PcodeOp.CALLIND:
executeCallind(raw);
break;
case PcodeOp.CALLOTHER:
executeCallother(raw);
break;
case PcodeOp.RETURN:
executeBranchind(raw);
break;
case PcodeOp.MULTIEQUAL:
executeMultiequal(raw);
fallthruOp();
break;
case PcodeOp.INDIRECT:
executeIndirect(raw);
fallthruOp();
break;
default:
throw new LowlevelError("Unsupported op (opcode=" + behave.getOpCode() + ")");
}
}
}
/// This routine performs a standard pcode \b load operation on the memory state
/// \param op is the particular \e load op being executed
public void executeLoad(PcodeOpRaw op) {
AddressSpace space =
addrFactory.getAddressSpace((int) op.getInput(0).getAddress().getOffset()); // Space to read from
long offset = memstate.getValue(op.getInput(1)); // Offset to read from
long byteOffset =
space.truncateAddressableWordOffset(offset) * space.getAddressableUnitSize();
Varnode outvar = op.getOutput();
if (outvar.getSize() > 8) {
BigInteger res =
memstate.getBigInteger(space, byteOffset, op.getOutput().getSize(), false);
memstate.setValue(outvar, res);
}
else {
long res = memstate.getValue(space, byteOffset, op.getOutput().getSize());
memstate.setValue(op.getOutput(), res);
}
}
/// This routine performs a standard pcode \b store operation on the memory state
/// \param op is the particular \e store op being executed
public void executeStore(PcodeOpRaw op) {
AddressSpace space =
addrFactory.getAddressSpace((int) op.getInput(0).getAddress().getOffset()); // Space to store in
long offset = memstate.getValue(op.getInput(1)); // Offset to store at
long byteOffset =
space.truncateAddressableWordOffset(offset) * space.getAddressableUnitSize();
Varnode storedVar = op.getInput(2); // Value being stored
if (storedVar.getSize() > 8) {
BigInteger val = memstate.getBigInteger(storedVar, false);
memstate.setValue(space, byteOffset, op.getInput(2).getSize(), val);
}
else {
long val = memstate.getValue(storedVar);
memstate.setValue(space, byteOffset, op.getInput(2).getSize(), val);
}
}
/// This routine performs a standard pcode \b branch \b indirect operation on the memory state
/// \param op is the particular \e branchind op being executed
public void executeBranchind(PcodeOpRaw op) {
long offset = memstate.getValue(op.getInput(0));
AddressSpace space = op.getAddress().getAddressSpace();
setCurrentAddress(space.getTruncatedAddress(offset, true));
}
/// This routine performs a standard pcode \b call operation on the memory state
/// \param op is the particular \e call op being executed
public void executeCall(PcodeOpRaw op) {
setCurrentAddress(op.getInput(0).getAddress());
}
/// This routine performs a standard pcode \b call \b indirect operation on the memory state
/// \param op is the particular \e callind op being executed
public void executeCallind(PcodeOpRaw op) {
executeBranchind(op); // same behavior as branch indirect
}
/// This kind of pcode op should not come up in ordinary emulation, so this routine
/// throws an exception.
/// \param op is the particular \e multiequal op being executed
public void executeMultiequal(PcodeOpRaw op) {
throw new LowlevelError("MULTIEQUAL appearing in unheritaged code?");
}
/// This kind of pcode op should not come up in ordinary emulation, so this routine
/// throws an exception.
/// \param op is the particular \e indirect op being executed
public void executeIndirect(PcodeOpRaw op) {
throw new LowlevelError("INDIRECT appearing in unheritaged code?");
}
}
/** \page sleighAPIemulate The SLEIGH Emulator
\section emu_overview Overview
\b SLEIGH provides a framework for emulating the processors which have a specification written
for them. The key classes in this framework are:
\b Key \b Classes
- \ref MemoryState
- \ref MemoryBank
- \ref BreakTable
- \ref BreakCallBack
- \ref Emulate
- \ref EmulatePcodeCache
The MemoryState object holds the representation of registers and memory during emulation. It
understands the address spaces defined in the \b SLEIGH specification and how data is encoded
in these spaces. It also knows any register names defined by the specification, so these
can be used to set or query the state of these registers naturally.
The emulation framework can be tailored to a particular environment by creating \b breakpoint
objects, which derive off the BreakCallBack interface. These can be used to create callbacks
during emulation that have full access to the memory state and the emulator, so any action
can be accomplished. The breakpoint callbacks can be designed to either augment or replace
the instruction at a particular address, or the callback can be used to implement the action
of a user-defined pcode op. The BreakCallBack objects are managed by the BreakTable object,
which takes care of invoking the callback at the appropriate time.
The Emulate object serves as a basic execution engine. Its main method is
Emulate::executeCurrentOp() which executes a single pcode operation on the memory state.
Methods exist for querying and setting the current execution address and examining the pcode
op being executed.
The main implementation of the Emulate interface is the EmulatePcodeCache object. It uses
SLEIGH to translate machine instructions as they are executed. The currently executing instruction
is translated into a cached sequence of pcode operations. Additional methods allow this entire
sequence to be inspected, and there is another stepping function which allows the emulator
to be stepped through an entire machine instruction at a time. The single pcode stepping methods
are of course still available and the two methods can be used together without conflict.
\section emu_membuild Building a Memory State
Assuming the SLEIGH Translate object and the LoadImage object have already been built
(see \ref sleighAPIbasic), the only required step left before instantiating an emulator
is to create a MemoryState object. The MemoryState object can be instantiated simply by
passing the constructor the Translate object, but before it will work properly, you need
to register individual MemoryBank objects with it, for each address space that might
get used by the emulator.
A MemoryBank is a representation of data stored in a single address space
There are some choices for the type of MemoryBank associated with an address space.
A MemoryImage is a read-only memory bank that gets its data from a LoadImage. In order
to make this writeable, or to create a writeable memory bank which starts with its bytes
initialized to zero, you can use a MemoryPageOverlay.
A MemoryPageOverlay overlays another memory bank as well. But it implements writes to the bank
by caching memory \e pages. Any write creates an aligned page to hold the new data. The class
takes care of loading and filling in pages as needed.
The Emulate constructor always adds a unique space memory bank using the UniqueMemoryBank,
the user needs not add this space.
All the memory bank constructors need a page size, which is most relevant to the page implementation. The
null pointers passed in, in place of a real memory bank, indicate that the memory bank has no initial
memory image. Once the memory banks are instantiated, they are registered with the memory state
via the MemoryState::setMemoryBank() method.
\section emu_breakpoints Breakpoints
In order to provide behavior within the emulator beyond just what the core instruction emulation
provides, the framework supports \b breakpoint classes. A breakpoint is created by deriving a
class from the BreakCallBack class and overriding either BreakCallBack::addressCallback() or
BreakCallBack::pcodeCallback(). Here is an example of a breakpoint that implements a
standard C library \e puts call an the x86 architecture. When the breakpoint is invoked,
a call to \e puts has just been made, so the stack pointer is pointing to the return address
and the next 4 bytes on the stack are a pointer to the string being passed in.
\code
class PutsCallBack : public BreakCallBack {
public:
virtual bool addressCallback(const Address &addr);
};
bool PutsCallBack::addressCallback(const Address &addr)
{
MemoryState *mem = emulate->getMemoryState();
uint1 buffer[256];
uint4 esp = mem->getValue("ESP");
AddrSpace *ram = mem->getTranslate()->getSpaceByName("ram");
uint4 param1 = mem->getValue(ram,esp+4,4);
mem->getChunk(buffer,ram,param1,255);
cout << (char *)&buffer << endl;
uint4 returnaddr = mem->getValue(ram,esp,4);
mem->setValue("ESP",esp+8);
emulate->setExecuteAddress(Address(ram,returnaddr));
return true; // This replaces the indicated instruction
}
\endcode
Notice that the callback retrieves the value of the stack pointer by name. Using this
value, the string pointer is retrieved, then the data for the actual string is retrieved.
After dumping the string to standard out, the return address is recovered and the \e return
instruction is emulated by explicitly setting the next execution address to be the return value.
\section emu_finalsetup Running the Emulator
Here is an example of instantiating an EmulatePcodeCache object. A breakpoint is also instantiated
and registered with the BreakTable.
\code
...
Sleigh trans(&loader,&context); // Instantiate the translator
...
MemoryState memstate(&trans); // Instantiate the memory state
...
BreakTableCallBack breaktable(&trans); // Instantiate a breakpoint table
EmulatePcodeCache emulator(&trans,&memstate,&breaktable); // Instantiate the emulator
// Set up the initial stack pointer
memstate.setValue("ESP",0xbffffffc);
emulator.setExecuteAddress(Address(trans.getDefaultSpace(),0x1D00114)); // Initial execution address
PutsCallBack putscallback;
breaktable.registerAddressCallback(Address(trans.getDefaultSpace(),0x1D00130),&putscallback);
AssemblyRaw assememit;
for(;;) {
Address addr = emulator.getExecuteAddress();
trans.printAssembly(assememit,addr);
emulator.executeInstruction();
}
\endcode
Notice how the initial stack pointer and initial execute address is set up. The breakpoint
is registered with the BreakTable, giving it a specific address. The executeInstruction method
is called inside the loop, to actually run the emulator. Notice that a disassembly of each
instruction is printed after each step of the emulator.
Other information can be examined from within this execution loop or in other tailored breakpoints.
In particular, the Emulate::getCurrentOp() method can be used to retrieve the an instance
of the currently executing pcode operation. From this starting point, you can examine the
low-level objects:
- PcodeOpRaw and
- VarnodeData
*/

View file

@ -1,209 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import java.math.BigInteger;
import java.util.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.*;
import ghidra.program.util.ProgramContextImpl;
public class EmulateDisassemblerContext implements DisassemblerContext {
private final Language language;
private final Map<Address, RegisterValue> futureContextMap;
private final Register contextReg;
private RegisterValue contextRegValue;
private byte[] flowingContextRegisterMask;
private boolean hasNonFlowingContext;
EmulateDisassemblerContext(Language language) {
this.language = language;
this.contextReg = language.getContextBaseRegister();
this.futureContextMap = new HashMap<Address, RegisterValue>();
initContext();
}
public EmulateDisassemblerContext(Language language, RegisterValue initialContextValue) {
this(language);
this.contextRegValue = initialContextValue;
}
@Override
public Register getBaseContextRegister() {
return contextReg;
}
public RegisterValue getCurrentContextRegisterValue() {
if (contextRegValue == null) {
return null;
}
return new RegisterValue(contextRegValue.getRegister(), contextRegValue.toBytes());
}
public void setCurrentAddress(Address addr) {
if (contextReg == Register.NO_CONTEXT) {
return;
}
RegisterValue partialValue = null;
if (contextRegValue != null && contextRegValue.getRegister() != contextReg) {
if (contextRegValue.getRegister().getBaseRegister() == contextReg) {
partialValue = contextRegValue;
}
contextRegValue = null;
}
if (contextRegValue == null) {
ProgramContextImpl defaultContext = new ProgramContextImpl(language);
language.applyContextSettings(defaultContext);
contextRegValue = defaultContext.getDefaultValue(contextReg, addr);
if (contextRegValue == null) {
contextRegValue = new RegisterValue(contextReg);
}
if (partialValue != null) {
contextRegValue = contextRegValue.combineValues(partialValue);
}
}
if (hasNonFlowingContext) {
byte[] contextBytes = contextRegValue.toBytes();
int valMaskLen = contextBytes.length >> 1;
for (int i = 0; i < valMaskLen; i++) {
contextBytes[i] &= flowingContextRegisterMask[i]; // clear non-flowing mask bits
contextBytes[valMaskLen + i] &= flowingContextRegisterMask[i]; // clear non-flowing value bits
}
contextRegValue = new RegisterValue(contextReg, contextBytes);
}
// WARNING: futureContextMap could accumulate a significant amount of context if it never gets purged
// although we may need it later (e.g., end-of-loop)
RegisterValue newContext = futureContextMap.get(addr);
if (newContext != null) {
contextRegValue = contextRegValue.combineValues(newContext);
}
}
private void initContext() {
if (contextReg == Register.NO_CONTEXT) {
return;
}
flowingContextRegisterMask = contextReg.getBaseMask().clone();
Arrays.fill(flowingContextRegisterMask, (byte) 0);
initContextBitMasks(contextReg);
}
/**
* Set those bits in the nonFlowingContextRegisterMask which should not
* flow with context.
* @param reg context register piece
*/
private void initContextBitMasks(Register reg) {
byte[] subMask = reg.getBaseMask();
if (!reg.followsFlow()) {
hasNonFlowingContext = true;
for (int i = 0; i < flowingContextRegisterMask.length; i++) {
flowingContextRegisterMask[i] &= ~subMask[i];
}
}
else {
for (int i = 0; i < flowingContextRegisterMask.length; i++) {
flowingContextRegisterMask[i] |= subMask[i];
}
if (reg.hasChildren()) {
for (Register childReg : reg.getChildRegisters()) {
initContextBitMasks(childReg);
}
}
}
}
@Override
public void clearRegister(Register register) {
throw new UnsupportedOperationException();
}
@Override
public Register getRegister(String name) {
throw new UnsupportedOperationException();
}
@Override
public RegisterValue getRegisterValue(Register register) {
if (!register.isProcessorContext()) {
throw new UnsupportedOperationException();
}
if (register.equals(contextReg)) {
return contextRegValue;
}
return new RegisterValue(register, contextRegValue.toBytes());
}
@Override
public List<Register> getRegisters() {
throw new UnsupportedOperationException();
}
@Override
public BigInteger getValue(Register register, boolean signed) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasValue(Register register) {
return true;
}
@Override
public void setRegisterValue(RegisterValue value) {
Register reg = value.getRegister();
if (!reg.isProcessorContext()) {
throw new UnsupportedOperationException();
}
if (contextRegValue == null) {
contextRegValue = value.getBaseRegisterValue();
}
else {
contextRegValue = contextRegValue.combineValues(value);
}
}
@Override
public void setValue(Register register, BigInteger value) {
throw new UnsupportedOperationException();
}
@Override
public void setFutureRegisterValue(Address address, RegisterValue value) {
Register reg = value.getRegister();
if (!reg.isProcessorContext()) {
throw new UnsupportedOperationException();
// Msg.warn(this, "Setting register " + reg.getName() + " during emulator disassembly ignored!");
// return;
}
RegisterValue registerValue = futureContextMap.get(address);
if (registerValue != null) {
value = registerValue.combineValues(value);
}
futureContextMap.put(address, value);
}
@Override
public void setFutureRegisterValue(Address fromAddr, Address toAddr, RegisterValue value) {
throw new UnsupportedOperationException();
}
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
public enum EmulateExecutionState {
/**
* Currently stopped
*/
STOPPED,
/**
* Currently stopped at a breakpoint
*/
BREAKPOINT,
/**
* Currently decoding instruction (i.e., generating pcode ops)
*/
INSTRUCTION_DECODE,
/**
* Currently executing instruction pcode
*/
EXECUTE,
/**
* Execution stopped due to a fault/error
*/
FAULT
}

View file

@ -1,114 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.emulate.callother.OpBehaviorOther;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode;
import java.util.HashMap;
import java.util.Map;
/**
* <code>EmulateInstructionStateModifier</code> defines a language specific
* handler to assist emulation with adjusting the current execution state,
* providing support for custom pcodeop's (i.e., CALLOTHER).
* The implementation of this interface must provide a public constructor which
* takes a single Emulate argument.
*/
public abstract class EmulateInstructionStateModifier {
protected final Emulate emu;
protected final Language language;
private Map<Integer, OpBehaviorOther> pcodeOpMap;
protected EmulateInstructionStateModifier(Emulate emu) {
this.emu = emu;
this.language = emu.getLanguage();
}
/**
* Register a pcodeop behavior corresponding to a CALLOTHER opcode.
* @param opName name as defined within language via "define pcodeop"
* @param pcodeOpBehavior
*/
protected final void registerPcodeOpBehavior(String opName, OpBehaviorOther pcodeOpBehavior) {
if (pcodeOpMap == null) {
pcodeOpMap = new HashMap<Integer, OpBehaviorOther>();
}
int numUserOps = language.getNumberOfUserDefinedOpNames();
for (int i = 0; i < numUserOps; i++) {
if (opName.equals(language.getUserDefinedOpName(i))) {
pcodeOpMap.put(i, pcodeOpBehavior);
return;
}
}
throw new LowlevelError("Undefined pcodeop name: " + opName);
}
/**
* Execute a CALLOTHER op
* @param op
* @return true if corresponding pcodeop was registered and emulation support is
* performed, or false if corresponding pcodeop is not supported by this class.
* @throws LowlevelError
*/
public final boolean executeCallOther(PcodeOp op) throws LowlevelError {
if (pcodeOpMap == null) {
return false;
}
Varnode[] inputs = op.getInputs();
OpBehaviorOther opBehaviorOther = pcodeOpMap.get((int) inputs[0].getOffset());
if (opBehaviorOther == null) {
return false;
}
opBehaviorOther.evaluate(emu, op.getOutput(), inputs);
return true;
}
/**
* Emulation callback immediately before the first instruction is executed.
* This callback permits any language specific initializations to be performed.
* @param emulate
* @param current_address intial execute address
* @param contextRegisterValue initial context value or null if not applicable or unknown
* @throws LowlevelError
*/
public void initialExecuteCallback(Emulate emulate, Address current_address, RegisterValue contextRegisterValue) throws LowlevelError {
// no default implementation
}
/**
* Emulation callback immediately following execution of the lastExecuteAddress.
* One use of this callback is to modify the flowing/future context state.
* @param emulate
* @param lastExecuteAddress
* @param lastExecutePcode
* @param lastPcodeIndex pcode index of last op or -1 if no pcode or fall-through occurred.
* @param currentAddress
* @throws LowlevelError
*/
public void postExecuteCallback(Emulate emulate, Address lastExecuteAddress,
PcodeOp[] lastExecutePcode, int lastPcodeIndex, Address currentAddress)
throws LowlevelError {
// no default implementation
}
}

View file

@ -1,122 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import java.math.BigInteger;
import ghidra.pcode.memstate.MemoryState;
import ghidra.program.model.address.Address;
import ghidra.program.model.mem.*;
/**
* <code>MemoryStateBuffer</code> provides a MemBuffer for instruction parsing use
* which wraps an emulator MemoryState. This implementation wraps all specified
* memory offsets within the associated address space.
*/
public class EmulateMemoryStateBuffer implements MemBuffer {
private final MemoryState memState;
private Address address;
public EmulateMemoryStateBuffer(MemoryState memState, Address addr) {
this.memState = memState;
setAddress(addr);
}
public void setAddress(Address addr) {
address = addr;
}
@Override
public Address getAddress() {
return address;
}
private long availableInSpace(Address startAddr) {
return address.getAddressSpace().getMaxAddress().subtract(startAddr) + 1;
}
private Address getWrappedAddress(int offset) {
return address.addWrap(offset);
}
/**
* Determine if request is valid and compute wrapped memory offset relative to
* current buffer address. A request is invalid if too close to the end of the
* memory space to read the requested number of bytes.
* @param offset relative offset
* @param size read request size
* @return absolute memory offset (wrapped)
* @throws MemoryAccessException
*/
private long checkGetRequest(int offset, int size) throws MemoryAccessException {
Address offsetAddr = getWrappedAddress(offset);
long available = availableInSpace(offsetAddr);
if (available > 0 && available < size) {
throw new MemoryAccessException();
}
return offsetAddr.getOffset();
}
@Override
public BigInteger getBigInteger(int offset, int size, boolean signed)
throws MemoryAccessException {
long memOffset = checkGetRequest(offset, size);
return memState.getBigInteger(address.getAddressSpace(), memOffset, size, signed);
}
@Override
public int getBytes(byte[] b, int offset) {
Address offsetAddr = getWrappedAddress(offset);
return memState.getChunk(b, address.getAddressSpace(), offsetAddr.getOffset(), b.length,
true);
}
@Override
public byte getByte(int offset) throws MemoryAccessException {
long memOffset = checkGetRequest(offset, 1);
return (byte) memState.getValue(address.getAddressSpace(), memOffset, 1);
}
@Override
public short getShort(int offset) throws MemoryAccessException {
long memOffset = checkGetRequest(offset, 2);
return (short) memState.getValue(address.getAddressSpace(), memOffset, 2);
}
@Override
public int getInt(int offset) throws MemoryAccessException {
long memOffset = checkGetRequest(offset, 4);
return (int) memState.getValue(address.getAddressSpace(), memOffset, 4);
}
@Override
public long getLong(int offset) throws MemoryAccessException {
long memOffset = checkGetRequest(offset, 8);
return memState.getValue(address.getAddressSpace(), memOffset, 8);
}
@Override
public Memory getMemory() {
return null;
}
@Override
public boolean isBigEndian() {
return memState.getMemoryBank(address.getAddressSpace()).isBigEndian();
}
}

View file

@ -1,35 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.address.Address;
public class InstructionDecodeException extends LowlevelError {
private Address pc;
public InstructionDecodeException(String reason, Address pc) {
super("Instruction decode failed (" + reason + "), PC=" + pc);
this.pc = pc;
}
public Address getProgramCounter() {
return pc;
}
}

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.pcoderaw.PcodeOpRaw;
public class UnimplementedCallOtherException extends LowlevelError {
private String opName;
private PcodeOpRaw op;
public UnimplementedCallOtherException(PcodeOpRaw op, String opName) {
super("Unimplemented CALLOTHER pcodeop (" + opName + "), PC=" + op.getAddress());
this.op = op;
this.opName = opName;
}
public PcodeOpRaw getCallOtherOp() {
return op;
}
public String getCallOtherOpName() {
return opName;
}
}

View file

@ -1,35 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.address.Address;
public class UnimplementedInstructionException extends LowlevelError {
private Address addr;
public UnimplementedInstructionException(Address addr) {
super("Unimplemented instruction, PC=" + addr);
this.addr = addr;
}
public Address getInstructionAddress() {
return addr;
}
}

View file

@ -1,37 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate.callother;
import ghidra.pcode.emulate.Emulate;
import ghidra.program.model.pcode.Varnode;
public interface OpBehaviorOther {
/**
* Evaluate the CALLOTHER op which corresponds to this behavior.
* @param emu emulator which contains associated memory state
* @param out output varnode or null if no assignment has been
* made. Implementation is responsible for updating memory
* state appropriately.
* @param inputs input varnodes passed as parameters to this
* pcodeop. The inputs[0] value corresponds to the index value of this
* pcodeop and can generally be ignored. The inputs[1] value
* corresponds to the first (leftmost) parameter passed to
* this pcodeop within the language implementation.
*/
public void evaluate(Emulate emu, Varnode out, Varnode[] inputs);
}

View file

@ -1,29 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.emulate.callother;
import ghidra.pcode.emulate.Emulate;
import ghidra.program.model.pcode.Varnode;
public class OpBehaviorOtherNOP implements OpBehaviorOther {
@Override
public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) {
// do nothing
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,11 +17,11 @@ package ghidra.pcode.error;
public class LowlevelError extends RuntimeException {
public LowlevelError( String message ) {
super( message );
public LowlevelError(String message) {
super(message);
}
public LowlevelError( String message, Throwable throwable ) {
super( message, throwable );
public LowlevelError(String message, Throwable throwable) {
super(message, throwable);
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.loadimage;
import ghidra.pcode.memstate.MemoryPage;
import ghidra.program.model.address.Address;
// API for accessing a binary load image
// using 1 of possibly many different methods behind the scenes
public interface LoadImage {
// TODO this doesn't appear to be used.
// /**
// *
// * @param ptr
// * @param size
// * @param addr
// * @param bufOffset
// * @param generateInitializedMask if true the function should return an initialized bit mask
// * or null if all loaded bytes were known. If true, uninitialized memory reads should only be
// * reflected in the mask and should not be reported via the memory fault handler.
// * @return initialized bit mask or null (see generateInitializedMask parameter)
// * @see MemoryPage
// */
public byte[] loadFill( byte[] buf, int size, Address addr, int bufOffset, boolean generateInitializedMask );
}

View file

@ -1,25 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.loadimage;
import ghidra.program.model.address.Address;
public class LoadImageFunc {
public Address address; // Start of function
public String name; // Name of function
}

View file

@ -1,269 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import java.math.BigInteger;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.pcode.Varnode;
public abstract class AbstractMemoryState implements MemoryState {
final Language language;
public AbstractMemoryState(Language language) {
this.language = language;
}
/**
* A convenience method for setting a value directly on a varnode rather than breaking out the
* components
*
* @param vn the varnode location to be written
* @param cval the value to write into the varnode location
*/
@Override
public final void setValue(Varnode vn, long cval) {
Address addr = vn.getAddress();
setValue(addr.getAddressSpace(), addr.getOffset(), vn.getSize(), cval);
}
/**
* A convenience method for setting a value directly on a register rather than breaking out the
* components
*
* @param reg the register location to be written
* @param cval the value to write into the register location
*/
@Override
public final void setValue(Register reg, long cval) {
Address addr = reg.getAddress();
setValue(addr.getAddressSpace(), addr.getOffset(), reg.getMinimumByteSize(), cval);
}
/**
* This is a convenience method for setting registers by name. Any register name known to the
* language can be used as a write location. The associated address space, offset, and size is
* looked up and automatically passed to the main setValue routine.
*
* @param nm is the name of the register
* @param cval is the value to write to the register
*/
@Override
public final void setValue(String nm, long cval) {
// Set a "register" value
setValue(language.getRegister(nm), cval);
}
/**
* This is the main interface for writing values to the MemoryState. If there is no registered
* MemoryBank for the desired address space, or if there is some other error, an exception is
* thrown.
*
* @param spc is the address space to write to
* @param off is the offset where the value should be written
* @param size is the number of bytes to be written
* @param cval is the value to be written
*/
@Override
public final void setValue(AddressSpace spc, long off, int size, long cval) {
setChunk(Utils.longToBytes(cval, size, language.isBigEndian()), spc, off, size);
}
/**
* A convenience method for reading a value directly from a varnode rather than querying for the
* offset and space
*
* @param vn the varnode location to be read
* @return the value read from the varnode location
*/
@Override
public final long getValue(Varnode vn) {
Address addr = vn.getAddress();
return getValue(addr.getAddressSpace(), addr.getOffset(), vn.getSize());
}
/**
* A convenience method for reading a value directly from a register rather than querying for
* the offset and space
*
* @param reg the register location to be read
* @return the value read from the register location
*/
@Override
public final long getValue(Register reg) {
Address addr = reg.getAddress();
return getValue(addr.getAddressSpace(), addr.getOffset(), reg.getMinimumByteSize());
}
/**
* This is a convenience method for reading registers by name. any register name known to the
* language can be used as a read location. The associated address space, offset, and size is
* looked up and automatically passed to the main getValue routine.
*
* @param nm is the name of the register
* @return the value associated with that register
*/
@Override
public final long getValue(String nm) {
// Get a "register" value
return getValue(language.getRegister(nm));
}
/**
* This is the main interface for reading values from the MemoryState. If there is no registered
* MemoryBank for the desired address space, or if there is some other error, an exception is
* thrown.
*
* @param spc is the address space being queried
* @param off is the offset of the value being queried
* @param size is the number of bytes to query
* @return the queried value
*/
@Override
public final long getValue(AddressSpace spc, long off, int size) {
if (spc.isConstantSpace()) {
return off;
}
byte[] bytes = new byte[size];
getChunk(bytes, spc, off, size, false);
return Utils.bytesToLong(bytes, size, language.isBigEndian());
}
/**
* A convenience method for setting a value directly on a varnode rather than breaking out the
* components
*
* @param vn the varnode location to be written
* @param cval the value to write into the varnode location
*/
@Override
public final void setValue(Varnode vn, BigInteger cval) {
Address addr = vn.getAddress();
setValue(addr.getAddressSpace(), addr.getOffset(), vn.getSize(), cval);
}
/**
* A convenience method for setting a value directly on a register rather than breaking out the
* components
*
* @param reg the register location to be written
* @param cval the value to write into the register location
*/
@Override
public final void setValue(Register reg, BigInteger cval) {
Address addr = reg.getAddress();
setValue(addr.getAddressSpace(), addr.getOffset(), reg.getMinimumByteSize(), cval);
}
/**
* This is a convenience method for setting registers by name. Any register name known to the
* language can be used as a write location. The associated address space, offset, and size is
* looked up and automatically passed to the main setValue routine.
*
* @param nm is the name of the register
* @param cval is the value to write to the register
*/
@Override
public final void setValue(String nm, BigInteger cval) {
// Set a "register" value
setValue(language.getRegister(nm), cval);
}
/**
* This is the main interface for writing values to the MemoryState. If there is no registered
* MemoryBank for the desired address space, or if there is some other error, an exception is
* thrown.
*
* @param spc is the address space to write to
* @param off is the offset where the value should be written
* @param size is the number of bytes to be written
* @param cval is the value to be written
*/
@Override
public final void setValue(AddressSpace spc, long off, int size, BigInteger cval) {
setChunk(Utils.bigIntegerToBytes(cval, size, language.isBigEndian()), spc, off, size);
}
/**
* A convenience method for reading a value directly from a varnode rather than querying for the
* offset and space
*
* @param vn the varnode location to be read
* @param signed true if signed value should be returned, false for unsigned value
* @return the unsigned value read from the varnode location
*/
@Override
public final BigInteger getBigInteger(Varnode vn, boolean signed) {
Address addr = vn.getAddress();
return getBigInteger(addr.getAddressSpace(), addr.getOffset(), vn.getSize(), signed);
}
/**
* A convenience method for reading a value directly from a register rather than querying for
* the offset and space
*
* @param reg the register location to be read
* @return the unsigned value read from the register location
*/
@Override
public final BigInteger getBigInteger(Register reg) {
Address addr = reg.getAddress();
return getBigInteger(addr.getAddressSpace(), addr.getOffset(), reg.getMinimumByteSize(),
false);
}
/**
* This is a convenience method for reading registers by name. any register name known to the
* language can be used as a read location. The associated address space, offset, and size is
* looked up and automatically passed to the main getValue routine.
*
* @param nm is the name of the register
* @return the unsigned value associated with that register
*/
@Override
public final BigInteger getBigInteger(String nm) {
// Get a "register" value
return getBigInteger(language.getRegister(nm));
}
/**
* This is the main interface for reading values from the MemoryState. If there is no registered
* MemoryBank for the desired address space, or if there is some other error, an exception is
* thrown.
*
* @param spc is the address space being queried
* @param off is the offset of the value being queried
* @param size is the number of bytes to query
* @param signed true if signed value should be returned, false for unsigned value
* @return the queried unsigned value
*/
@Override
public final BigInteger getBigInteger(AddressSpace spc, long off, int size, boolean signed) {
if (spc.isConstantSpace()) {
if (!signed && off < 0) {
return new BigInteger(1, Utils.longToBytes(off, 8, true));
}
return BigInteger.valueOf(off);
}
byte[] bytes = new byte[size];
getChunk(bytes, spc, off, size, false);
return Utils.bytesToBigInteger(bytes, size, language.isBigEndian(), signed);
}
}

View file

@ -1,148 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import generic.stl.VectorSTL;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Language;
/**
* All storage/state for a pcode emulator machine
*
* Every piece of information in a pcode emulator machine is representable as a triple
* (AddressSpace,offset,size). This class allows getting and setting of all state information of
* this form.
*/
public class DefaultMemoryState extends AbstractMemoryState {
VectorSTL<MemoryBank> memspace = new VectorSTL<MemoryBank>();
/**
* MemoryState constructor for a specified processor language
*
* @param language
*/
public DefaultMemoryState(Language language) {
super(language);
}
/**
* MemoryBanks associated with specific address spaces must be registers with this MemoryState
* via this method. Each address space that will be used during emulation must be registered
* separately. The MemoryState object does not assume responsibility for freeing the MemoryBank.
*
* @param bank is a pointer to the MemoryBank to be registered
*/
@Override
public final void setMemoryBank(MemoryBank bank) {
AddressSpace spc = bank.getSpace();
int index = spc.getUnique();
while (index >= memspace.size())
memspace.push_back(null);
memspace.set(index, bank);
}
/**
* Any MemoryBank that has been registered with this MemoryState can be retrieved via this
* method if the MemoryBank's associated address space is known.
*
* @param spc is the address space of the desired MemoryBank
* @return the MemoryBank or null if no bank is associated with spc.
*/
@Override
public final MemoryBank getMemoryBank(AddressSpace spc) {
int index = spc.getUnique();
if (index >= memspace.size())
return null;
return memspace.get(index);
}
/**
* This is the main interface for reading a range of bytes from the MemorySate. The MemoryBank
* associated with the address space of the query is looked up and the request is forwarded to
* the getChunk method on the MemoryBank. If there is no registered MemoryBank or some other
* error, an exception is thrown. All getLongValue methods utilize this method to read the bytes
* from the appropriate memory bank.
*
* @param res the result buffer for storing retrieved bytes
* @param spc the desired address space
* @param off the starting offset of the byte range being read
* @param size the number of bytes being read
* @param stopOnUnintialized if true a partial read is permitted and returned size may be
* smaller than size requested
* @return number of bytes actually read
* @throws LowlevelError if spc has not been mapped within this MemoryState or memory fault
* handler generated error
*/
@Override
public int getChunk(byte[] res, AddressSpace spc, long off, int size,
boolean stopOnUnintialized) {
if (spc.isConstantSpace()) {
System.arraycopy(Utils.longToBytes(off, size, language.isBigEndian()), 0, res, 0, size);
return size;
}
MemoryBank mspace = getMemoryBank(spc);
if (mspace == null)
throw new LowlevelError("Getting chunk from unmapped memory space: " + spc.getName());
return mspace.getChunk(off, size, res, stopOnUnintialized);
}
/**
* This is the main interface for setting values for a range of bytes in the MemoryState. The
* MemoryBank associated with the desired address space is looked up and the write is forwarded
* to the setChunk method on the MemoryBank. If there is no registered MemoryBank or some other
* error, an exception is throw. All setValue methods utilize this method to read the bytes from
* the appropriate memory bank.
*
* @param val the byte values to be written into the MemoryState
* @param spc the address space being written
* @param off the starting offset of the range being written
* @param size the number of bytes to write
* @throws LowlevelError if spc has not been mapped within this MemoryState
*/
@Override
public void setChunk(byte[] val, AddressSpace spc, long off, int size) {
MemoryBank mspace = getMemoryBank(spc);
if (mspace == null)
throw new LowlevelError("Setting chunk of unmapped memory space: " + spc.getName());
mspace.setChunk(off, size, val);
}
/**
* This is the main interface for setting the initialization status for a range of bytes in the
* MemoryState. The MemoryBank associated with the desired address space is looked up and the
* write is forwarded to the setInitialized method on the MemoryBank. If there is no registered
* MemoryBank or some other error, an exception is throw. All setValue methods utilize this
* method to read the bytes from the appropriate memory bank.
*
* @param initialized indicates if range should be marked as initialized or not
* @param spc the address space being written
* @param off the starting offset of the range being written
* @param size the number of bytes to write
*/
@Override
public void setInitialized(boolean initialized, AddressSpace spc, long off, int size) {
MemoryBank mspace = getMemoryBank(spc);
if (mspace == null)
throw new LowlevelError("Setting intialization status of unmapped memory space: " +
spc.getName());
mspace.setInitialized(off, size, initialized);
}
}

View file

@ -1,310 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import ghidra.program.model.address.AddressSpace;
public abstract class MemoryBank {
private final int pagesize; ///< Number of bytes in an aligned page access
private final AddressSpace space; ///< The address space associated with this memory
private final boolean isBigEndian;
private final int initializedMaskSize; // number of bytes required for uninitialized mask
protected final MemoryFaultHandler faultHandler;
/**
* A MemoryBank must be associated with a specific address space, have a preferred or natural
* pagesize. The pagesize must be a power of 2.
* @param spc is the associated address space
* @param isBigEndian memory endianess
* @param ps ps is the number of bytes in a page (must be a power of 2)
* @param faultHandler memory fault handler
*/
public MemoryBank(AddressSpace spc, boolean isBigEndian, int ps, MemoryFaultHandler faultHandler) {
space = spc;
pagesize = ps;
this.isBigEndian = isBigEndian;
this.faultHandler = faultHandler;
initializedMaskSize = (ps + 7) / 8;
}
/**
* @return memory fault handler (may be null)
*/
public MemoryFaultHandler getMemoryFaultHandler() {
return faultHandler;
}
/**
* @return true if memory bank is big endian
*/
public boolean isBigEndian() {
return isBigEndian;
}
/**
* A MemoryBank is instantiated with a \e natural page size. Requests for large chunks of data
* may be broken down into units of this size.
* @return the number of bytes in a page.
*/
public int getPageSize() {
return pagesize;
}
/**
* @return the size of a page initialized mask in bytes. Each bit within the
* mask corresponds to a data byte within a page.
*/
public int getInitializedMaskSize() {
return initializedMaskSize;
}
/**
* @return the AddressSpace associated with this bank.
*/
public AddressSpace getSpace() {
return space;
}
/// This routine only retrieves data from a single \e page in the memory bank. Bytes need not
/// be retrieved from the exact start of a page, but all bytes must come from \e one page.
/// A page is a fixed number of bytes, and the address of a page is always aligned based
/// on that number of bytes. This routine may be overridden for a page based implementation
/// of the MemoryBank. The default implementation retrieves the page as aligned words
/// using the find method.
/// \param addr is the \e aligned offset of the desired page
/// \param res is a pointer to where fetched data should be written
/// \param skip is the offset \e into \e the \e page to get the bytes from
/// \param size is the number of bytes to retrieve
/// \param ignoreFault if true ignore fault and return
//protected abstract void getPage(long addr,MemoryPage res,int skip,int size, int bufOffset);
protected abstract MemoryPage getPage(long addr);
/// This routine writes data only to a single \e page of the memory bank. Bytes need not be
/// written to the exact start of the page, but all bytes must be written to only one page
/// when using this routine. A page is a
/// fixed number of bytes, and the address of a page is always aligned based on this size.
/// This routine may be overridden for a page based implementation of the MemoryBank. The
/// default implementation writes the page as a sequence of aligned words, using the
/// insert method.
/// \param addr is the \e aligned offset of the desired page
/// \param val is a pointer to the bytes to be written into the page
/// \param skip is the offset \e into \e the \e page where bytes will be written
/// \param size is the number of bytes to be written
/// \param bufOffset the offset in val from which to get the bytes
protected abstract void setPage(long addr, byte[] val, int skip, int size, int bufOffset);
/// This routine marks a range within a single \e page of the memory bank as initialized or
/// uninitialized. A page is a
/// fixed number of bytes, and the address of a page is always aligned based on this size.
/// This routine may be overridden for a page based implementation of the MemoryBank. The
/// default implementation writes the page as a sequence of aligned words, using the
/// insert method.
/// \param addr is the \e aligned offset of the desired page
/// \param initialized true if range should be marked as initialized, false if uninitialized
/// \param skip is the offset \e into \e the \e page where bytes will be written
/// \param size is the number of bytes to be written
/// \param bufOffset the offset in val from which to get the bytes
protected abstract void setPageInitialized(long addr, boolean initialized, int skip, int size,
int bufOffset);
/// This the most general method for writing a sequence of bytes into the memory bank.
/// The initial offset and page writes will be wrapped within the address space.
/// \param offset is the start of the byte range to be written. This offset will be wrapped
/// within the space
/// \param size is the number of bytes to write
/// \param val is a pointer to the sequence of bytes to be written into the bank
public void setChunk(long offset, int size, byte[] val) {
int cursize;
int count;
long pagemask = (pagesize - 1);
long offalign;
int skip;
int bufOffset = 0;
count = 0;
while (count < size) {
cursize = pagesize;
offset = space.truncateOffset(offset);
offalign = offset & ~pagemask;
skip = 0;
if (offalign != offset) {
skip = (int) (offset - offalign);
cursize -= skip;
}
if (size - count < cursize)
cursize = size - count;
setPage(offalign, val, skip, cursize, bufOffset);
count += cursize;
offset += cursize;
bufOffset += cursize;
}
}
/// This method allows ranges of bytes to marked as initialized or not.
/// There is no restriction on the offset to write to or the number of bytes to be written,
/// except that the range must be contained in the address space.
/// \param offset is the start of the byte range to be written
/// \param size is the number of bytes to write
/// \param initialized indicates if the range should be marked as initialized or not
public void setInitialized(long offset, int size, boolean initialized) {
int cursize;
int count;
long pagemask = (pagesize - 1);
long offalign;
int skip;
int bufOffset = 0;
count = 0;
while (count < size) {
cursize = pagesize;
offalign = offset & ~pagemask;
skip = 0;
if (offalign != offset) {
skip = (int) (offset - offalign);
cursize -= skip;
}
if (size - count < cursize)
cursize = size - count;
setPageInitialized(offalign, initialized, skip, cursize, bufOffset);
count += cursize;
offset += cursize;
bufOffset += cursize;
}
}
/// This is the most general method for reading a sequence of bytes from the memory bank.
/// There is no restriction on the offset or the number of bytes to read, except that the
/// range must be contained in the address space.
/// \param offset is the start of the byte range to read
/// \param size is the number of bytes to read
/// \param res is a pointer to where the retrieved bytes should be stored
/// \param stopOnUnintialized if true a partial read is permitted and returned size may be
/// smaller than size requested if uninitialized data is encountered.
/// \return number of bytes actually read
public int getChunk(long addrOffset, int size, byte[] res, boolean stopOnUnintialized) {
int cursize, count;
long pagemask = (pagesize - 1);
long offalign;
int skip;
int bufOffset = 0;
addrOffset = space.truncateOffset(addrOffset);
count = 0;
while (count < size) {
cursize = pagesize;
offalign = addrOffset & ~pagemask;
skip = 0;
if (offalign != addrOffset) {
skip = (int) (addrOffset - offalign);
cursize -= skip;
}
if (size - count < cursize)
cursize = size - count;
MemoryPage page = getPage(offalign);
// Read initialized data which is available
int initializedByteCount = page.getInitializedByteCount(skip, cursize);
System.arraycopy(page.data, skip, res, bufOffset, initializedByteCount);
count += initializedByteCount;
long nextAddrOffset = space.truncateOffset(addrOffset + initializedByteCount);
addrOffset += initializedByteCount;
bufOffset += initializedByteCount;
cursize -= initializedByteCount;
if (cursize != 0) {
// Handle incomplete read from current page
skip += initializedByteCount;
if (faultHandler.uninitializedRead(getSpace().getAddress(offalign + skip), cursize,
page.data, skip)) {
page.setInitialized(skip, cursize);
}
else if (stopOnUnintialized) {
return count;
}
System.arraycopy(page.data, skip, res, bufOffset, cursize);
count += cursize;
nextAddrOffset = space.truncateOffset(nextAddrOffset + cursize);
addrOffset += cursize;
bufOffset += cursize;
}
// stop if wrapped midway
if (addrOffset < 0) {
if (nextAddrOffset > 0) {
break;
}
}
else if (nextAddrOffset < addrOffset) {
break;
}
}
return count;
}
/// This is a static convenience routine for decoding a value from a sequence of bytes depending
/// on the desired endianness
/// \param ptr is the pointer to the bytes to decode
/// \param size is the number of bytes
/// \param bigendian is \b true if the bytes are encoded in big endian form
/// \return the decoded value
public static long constructValue(byte[] ptr, int offset, int size, boolean bigendian) {
long res = 0;
if (bigendian) {
for (int i = 0; i < size; ++i) {
res <<= 8;
res |= ptr[i + offset] & 0xffL;
}
}
else {
for (int i = size - 1; i >= 0; --i) {
res <<= 8;
res |= ptr[i + offset] & 0xffL;
}
}
return res;
}
/// This is a static convenience routine for encoding bytes from a given value, depending on
/// the desired endianness
/// \param ptr is a pointer to the location to write the encoded bytes
/// \param val is the value to be encoded
/// \param size is the number of bytes to encode
/// \param bigendian is \b true if a big endian encoding is desired
public static void deconstructValue(byte[] ptr, int offset, long val, int size,
boolean bigendian) {
if (bigendian) {
for (int i = size - 1; i >= 0; --i) {
ptr[i + offset] = (byte) (val & 0xff);
val >>= 8;
}
}
else {
for (int i = 0; i < size; ++i) {
ptr[i + offset] = (byte) (val & 0xff);
val >>= 8;
}
}
}
}

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import ghidra.program.model.address.Address;
public interface MemoryFaultHandler {
/**
* An attempt has been made to read uninitialized memory at the
* specified address.
* @param address uninitialized storage address (memory, register or unique)
* @param size number of uninitialized bytes
* @param buf storage buffer
* @param bufOffset read offset within buffer
* @return true if data should be treated as initialized
*/
boolean uninitializedRead(Address address, int size, byte[] buf, int bufOffset);
/**
* Unable to translate the specified address
* @param address address which failed to be translated
* @param write true if memory operation was a write vs. read
* @return true if fault was handled
*/
boolean unknownAddress(Address address, boolean write);
}

View file

@ -1,252 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import java.util.Arrays;
/**
* <code>MemoryPage</code> is allows the contents/data of a memory page
* to be maintained along with an initializedMask. Each bit within the
* initializedMask corresponds to a data byte within the page. A null
* mask indicates that all data within the page is initialized. A one-bit
* within the mask indicates that the corresponding data byte is initialized.
*/
public class MemoryPage {
public final byte[] data;
private byte[] initializedMask;
/**
* Construct a new fully initialized page containing
* all zero (0) byte data.
*/
public MemoryPage(int pageSize) {
data = new byte[pageSize];
}
/**
* Construct a memory page with an existing data bytes buffer
* @param bytes buffer
*/
public MemoryPage(byte[] bytes) {
data = bytes;
}
public byte[] getInitializedMask() {
return initializedMask;
}
/**
* Mark entire page as uninitialized
*/
public void setUninitialized() {
initializedMask = getInitializedMask(data.length, false);
}
/**
* Mark entire page as uninitialized
*/
public void setInitialized() {
initializedMask = getInitializedMask(data.length, true);
}
/**
* Update initialization mask
* @param pageOffset
* @param size
* @param maskUpdate
*/
public void setInitialized(int pageOffset, int size, byte[] maskUpdate) {
int maskOffset = pageOffset / 8;
int firstBit = pageOffset % 8;
while (size > 0) {
int s = Math.min(size, 8 - firstBit);
size -= s;
int mask = (0xff << firstBit) & ((1 << (firstBit + s)) - 1);
int val = mask;
if (maskUpdate != null) {
val &= maskUpdate[maskOffset];
}
if (initializedMask == null) {
// allocate mask if needed
byte test = (byte) (val | ~mask);
if (test == (byte) -1) {
++maskOffset;
firstBit = 0;
continue;
}
initializedMask = getInitializedMask(data.length, true);
}
initializedMask[maskOffset] = (byte) ((initializedMask[maskOffset] & ~mask) | val);
++maskOffset;
firstBit = 0;
}
}
/**
* Mark specified page region as initialized.
* @param pageOffset
* @param size
*/
public void setInitialized(int pageOffset, int size) {
if (initializedMask == null) {
return;
}
if (pageOffset == 0 && size == data.length) {
initializedMask = null;
return;
}
setInitialized(initializedMask, pageOffset, size);
}
/**
* Mark specified page region as uninitialized.
* @param pageOffset
* @param size
*/
public void setUninitialized(int pageOffset, int size) {
if (initializedMask == null) {
initializedMask = getInitializedMask(data.length, true);
}
setUninitialized(initializedMask, pageOffset, size);
}
/**
* Get number of leading bytes within page range which have been
* initialized.
* @param pageOffset
* @param size
* @return number of leading bytes within page range which have been
* initialized.
*/
public int getInitializedByteCount(int pageOffset, int size) {
return getInitializedByteCount(initializedMask, pageOffset, size);
}
/**
* Generate an initialized mask for the specified page size
* @param pageSize
* @param initialized
* @return
*/
public static byte[] getInitializedMask(int pageSize, boolean initialized) {
byte[] mask = new byte[(pageSize + 7) / 8];
if (initialized) {
Arrays.fill(mask, (byte) -1);
}
return mask;
}
/**
* Generate an initialized mask for the specified page size.
* The region is identified by offset and size. The remaining portions
* of the mask will be set based upon !initialized.
* @param pageSize
* @param offset
* @param size
* @param initialized
* @return
*/
public static byte[] getInitializedMask(int pageSize, int offset, int size,
boolean initialized) {
byte[] mask = getInitializedMask(pageSize, true);
if (initialized) {
if (offset != 0) {
setUninitialized(mask, 0, offset);
}
int end = offset + size;
if (end < pageSize) {
setUninitialized(mask, end, pageSize - end);
}
}
else if (size != 0) {
setUninitialized(mask, offset, size);
}
return mask;
}
/**
* Mark specified page region as initialized.
* @param initializedMask
* @param pageOffset
* @param size
*/
public static void setInitialized(byte[] initializedMask, int pageOffset, int size) {
int maskOffset = pageOffset / 8;
int firstBit = pageOffset % 8;
while (size > 0) {
int s = Math.min(size, 8 - firstBit);
size -= s;
int mask = (0xff << firstBit) & ((1 << (firstBit + s)) - 1);
initializedMask[maskOffset] |= (byte) mask;
++maskOffset;
firstBit = 0;
}
}
/**
* Mark specified page region as uninitialized.
* @param initializedMask
* @param pageOffset
* @param size
*/
public static void setUninitialized(byte[] initializedMask, int pageOffset, int size) {
int maskOffset = pageOffset / 8;
int firstBit = pageOffset % 8;
while (size > 0) {
int s = Math.min(size, 8 - firstBit);
size -= s;
int mask = (0xff << firstBit) & ((1 << (firstBit + s)) - 1);
initializedMask[maskOffset] &= (byte) ~mask;
++maskOffset;
firstBit = 0;
}
}
/**
* Determine how many leading bytes of a specified page region is marked as
* initialized. Valid page region defined by pageOffset and size is assumed.
* @param initializedMask
* @param pageOffset
* @param size
* @return number of leading bytes at pageOffset (upto size) are initialized.
*/
public static int getInitializedByteCount(byte[] initializedMask, int pageOffset, int size) {
if (initializedMask == null) {
return size;
}
int initializedSize = 0;
int maskOffset = pageOffset / 8;
int firstBit = pageOffset % 8;
while (size > 0) {
int s = Math.min(size, 8 - firstBit); // number of bytes represented by mask
size -= s;
int mask = (0xff << firstBit) & ((1 << (firstBit + s)) - 1);
int result = initializedMask[maskOffset] & mask;
if (result != mask) {
// count leading bits
for (result >>= firstBit; (result & 1) != 0; result >>= 1) {
++initializedSize;
}
return initializedSize;
}
initializedSize += s;
++maskOffset;
firstBit = 0;
}
return initializedSize;
}
}

View file

@ -1,91 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import generic.stl.*;
import ghidra.program.model.address.AddressSpace;
public class MemoryPageBank extends MemoryBank {
protected MapSTL<Long, MemoryPage> page = new ComparableMapSTL<>();
public MemoryPageBank(AddressSpace spc, boolean isBigEndian, int ps,
MemoryFaultHandler faultHandler) {
super(spc, isBigEndian, ps, faultHandler);
}
@Override
protected MemoryPage getPage(long addr) {
IteratorSTL<Pair<Long, MemoryPage>> iter;
iter = page.find(addr);
if (iter.equals(page.end())) {
int size = getPageSize();
MemoryPage pageptr = new MemoryPage(size);
page.add(addr, pageptr);
pageptr.setUninitialized();
return pageptr;
}
return (iter.get()).second;
}
@Override
protected void setPage(long addr, byte[] val, int skip, int size, int bufOffset) {
if (size == getPageSize() && bufOffset == 0) {
page.put(addr, new MemoryPage(val));
return;
}
MemoryPage pageptr = getPage(addr);
System.arraycopy(val, bufOffset, pageptr.data, skip, size);
pageptr.setInitialized(skip, size);
}
@Override
protected void setPageInitialized(long addr, boolean initialized, int skip, int size,
int bufOffset) {
MemoryPage pageptr;
IteratorSTL<Pair<Long, MemoryPage>> iter;
iter = page.find(addr);
if (iter.equals(page.end())) {
if (!initialized) {
return;
}
int pagesize = getPageSize();
pageptr = new MemoryPage(pagesize);
page.add(addr, pageptr);
}
else {
pageptr = (iter.get()).second;
}
if (size == getPageSize() && bufOffset == 0) {
if (initialized) {
pageptr.setInitialized();
}
else {
pageptr.setUninitialized();
}
}
else if (initialized) {
pageptr.setInitialized(skip, size);
}
else {
pageptr.setUninitialized(skip, size);
}
}
}

View file

@ -1,64 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import generic.stl.IteratorSTL;
import generic.stl.Pair;
import ghidra.program.model.address.AddressSpace;
/// \brief Memory bank that overlays some other memory bank, using a "copy on write" behavior.
///
/// Pages are copied from the underlying object only when there is
/// a write. The underlying access routines are overridden to make optimal use
/// of this page implementation. The underlying memory bank can be a \b null pointer
/// in which case, this memory bank behaves as if it were initially filled with zeros.
public class MemoryPageOverlay extends MemoryPageBank {
protected MemoryBank underlie; // underlying memory object
/// A page overlay memory bank needs all the parameters for a generic memory bank
/// and it needs to know the underlying memory bank being overlayed.
/// \param spc is the address space associated with the memory bank
/// \param ul is the underlying MemoryBank
public MemoryPageOverlay(AddressSpace spc, MemoryBank ul, MemoryFaultHandler faultHandler) {
super(spc,ul.isBigEndian(),ul.getPageSize(),faultHandler);
underlie = ul;
}
@Override
protected MemoryPage getPage(long addr) {
IteratorSTL<Pair<Long, MemoryPage>> iter;
iter = page.find(addr);
if (iter.equals(page.end())) {
MemoryPage pageptr;
if (underlie == null) {
int size = getPageSize();
pageptr = new MemoryPage(size);
for(int i=0;i<size;++i) {
pageptr.data[i] = 0;
}
pageptr.setUninitialized();
return pageptr;
}
// defer to underlie memory bank
pageptr = underlie.getPage(addr);
page.add(addr, pageptr);
return pageptr;
}
return (iter.get()).second;
}
}

View file

@ -1,243 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import java.math.BigInteger;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
import ghidra.program.model.pcode.Varnode;
public interface MemoryState {
/**
* MemoryBanks associated with specific address spaces must be registers with this MemoryState
* via this method. Each address space that will be used during emulation must be registered
* separately. The MemoryState object does not assume responsibility for freeing the MemoryBank.
* @param bank is a pointer to the MemoryBank to be registered
*/
void setMemoryBank(MemoryBank bank);
/**
* Any MemoryBank that has been registered with this MemoryState can be retrieved via this
* method if the MemoryBank's associated address space is known.
* @param spc is the address space of the desired MemoryBank
* @return the MemoryBank or null if no bank is associated with spc.
*/
MemoryBank getMemoryBank(AddressSpace spc);
/**
* A convenience method for setting a value directly on a varnode rather than
* breaking out the components
* @param vn the varnode location to be written
* @param cval the value to write into the varnode location
*/
void setValue(Varnode vn, long cval);
/**
* A convenience method for setting a value directly on a register rather than
* breaking out the components
* @param reg the register location to be written
* @param cval the value to write into the register location
*/
void setValue(Register reg, long cval);
/**
* This is a convenience method for setting registers by name.
* Any register name known to the language can be used as a write location.
* The associated address space, offset, and size is looked up and automatically
* passed to the main setValue routine.
* @param nm is the name of the register
* @param cval is the value to write to the register
*/
void setValue(String nm, long cval);
/**
* This is the main interface for writing values to the MemoryState.
* If there is no registered MemoryBank for the desired address space, or
* if there is some other error, an exception is thrown.
* @param spc is the address space to write to
* @param off is the offset where the value should be written
* @param size is the number of bytes to be written
* @param cval is the value to be written
*/
void setValue(AddressSpace spc, long off, int size, long cval);
/**
* A convenience method for reading a value directly from a varnode rather
* than querying for the offset and space
* @param vn the varnode location to be read
* @return the value read from the varnode location
*/
long getValue(Varnode vn);
/**
* A convenience method for reading a value directly from a register rather
* than querying for the offset and space
* @param reg the register location to be read
* @return the value read from the register location
*/
long getValue(Register reg);
/**
* This is a convenience method for reading registers by name.
* any register name known to the language can be used as a read location.
* The associated address space, offset, and size is looked up and automatically
* passed to the main getValue routine.
* @param nm is the name of the register
* @return the value associated with that register
*/
long getValue(String nm);
/**
* This is the main interface for reading values from the MemoryState.
* If there is no registered MemoryBank for the desired address space, or
* if there is some other error, an exception is thrown.
* @param spc is the address space being queried
* @param off is the offset of the value being queried
* @param size is the number of bytes to query
* @return the queried value
*/
long getValue(AddressSpace spc, long off, int size);
/**
* A convenience method for setting a value directly on a varnode rather than
* breaking out the components
* @param vn the varnode location to be written
* @param cval the value to write into the varnode location
*/
void setValue(Varnode vn, BigInteger cval);
/**
* A convenience method for setting a value directly on a register rather than
* breaking out the components
* @param reg the register location to be written
* @param cval the value to write into the register location
*/
void setValue(Register reg, BigInteger cval);
/**
* This is a convenience method for setting registers by name.
* Any register name known to the language can be used as a write location.
* The associated address space, offset, and size is looked up and automatically
* passed to the main setValue routine.
* @param nm is the name of the register
* @param cval is the value to write to the register
*/
void setValue(String nm, BigInteger cval);
/**
* This is the main interface for writing values to the MemoryState.
* If there is no registered MemoryBank for the desired address space, or
* if there is some other error, an exception is thrown.
* @param spc is the address space to write to
* @param off is the offset where the value should be written
* @param size is the number of bytes to be written
* @param cval is the value to be written
*/
void setValue(AddressSpace spc, long off, int size, BigInteger cval);
/**
* A convenience method for reading a value directly from a varnode rather
* than querying for the offset and space
* @param vn the varnode location to be read
* @param signed true if signed value should be returned, false for unsigned value
* @return the unsigned value read from the varnode location
*/
BigInteger getBigInteger(Varnode vn, boolean signed);
/**
* A convenience method for reading a value directly from a register rather
* than querying for the offset and space
* @param reg the register location to be read
* @return the unsigned value read from the register location
*/
BigInteger getBigInteger(Register reg);
/**
* This is a convenience method for reading registers by name.
* any register name known to the language can be used as a read location.
* The associated address space, offset, and size is looked up and automatically
* passed to the main getValue routine.
* @param nm is the name of the register
* @return the unsigned value associated with that register
*/
BigInteger getBigInteger(String nm);
/**
* This is the main interface for reading values from the MemoryState.
* If there is no registered MemoryBank for the desired address space, or
* if there is some other error, an exception is thrown.
* @param spc is the address space being queried
* @param off is the offset of the value being queried
* @param size is the number of bytes to query
* @param signed true if signed value should be returned, false for unsigned value
* @return the queried unsigned value
*/
BigInteger getBigInteger(AddressSpace spc, long off, int size, boolean signed);
/**
* This is the main interface for reading a range of bytes from the MemorySate.
* The MemoryBank associated with the address space of the query is looked up
* and the request is forwarded to the getChunk method on the MemoryBank. If there
* is no registered MemoryBank or some other error, an exception is thrown.
* All getLongValue methods utilize this method to read the bytes from the
* appropriate memory bank.
* @param res the result buffer for storing retrieved bytes
* @param spc the desired address space
* @param off the starting offset of the byte range being read
* @param size the number of bytes being read
* @param stopOnUnintialized if true a partial read is permitted and returned size may be
* smaller than size requested
* @return number of bytes actually read
* @throws LowlevelError if spc has not been mapped within this MemoryState or memory fault
* handler generated error
*/
int getChunk(byte[] res, AddressSpace spc, long off, int size,
boolean stopOnUnintialized);
/**
* This is the main interface for setting values for a range of bytes in the MemoryState.
* The MemoryBank associated with the desired address space is looked up and the
* write is forwarded to the setChunk method on the MemoryBank. If there is no
* registered MemoryBank or some other error, an exception is throw.
* All setValue methods utilize this method to read the bytes from the
* appropriate memory bank.
* @param val the byte values to be written into the MemoryState
* @param spc the address space being written
* @param off the starting offset of the range being written
* @param size the number of bytes to write
* @throws LowlevelError if spc has not been mapped within this MemoryState
*/
void setChunk(byte[] val, AddressSpace spc, long off, int size);
/**
* This is the main interface for setting the initialization status for a range of bytes
* in the MemoryState.
* The MemoryBank associated with the desired address space is looked up and the
* write is forwarded to the setInitialized method on the MemoryBank. If there is no
* registered MemoryBank or some other error, an exception is throw.
* All setValue methods utilize this method to read the bytes from the
* appropriate memory bank.
* @param initialized indicates if range should be marked as initialized or not
* @param spc the address space being written
* @param off the starting offset of the range being written
* @param size the number of bytes to write
*/
void setInitialized(boolean initialized, AddressSpace spc, long off, int size);
}

View file

@ -1,254 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import generic.stl.ComparableMapSTL;
import generic.stl.MapSTL;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.address.AddressSpace;
/**
* An subclass of {@link MemoryBank} intended for modeling the "unique" memory
* space. The space is byte-addressable and paging is not supported.
*/
public class UniqueMemoryBank extends MemoryBank {
/**A map from {@link Long} offsets to byte values would require many lookups.
* As an optimization, this map is defined from {@link Long} values to
* {@link WordInfo} objects, each of which represents an eight-byte word
* of memory. Each key in this map must be 0 mod 8.
*/
protected MapSTL<Long, WordInfo> map = new ComparableMapSTL<Long, WordInfo>();
private static final long ALIGNMENT_MASK = 0xfffffffffffffff8L;
//note that WordInfo use the bits in a byte to record whether
//or not a given byte has been written to, so you can't just
//change WORD_SIZE to another value and without also changing
//the implementation of WordInfo
private static final int WORD_SIZE = 8;
private byte[] buffer = new byte[WORD_SIZE];
public UniqueMemoryBank(AddressSpace spc, boolean isBigEndian) {
super(spc, isBigEndian, 0, null);
}
@Override
protected MemoryPage getPage(long addr) {
throw new UnsupportedOperationException("UniqueMemoryBank does not support paging");
}
@Override
protected void setPage(long addr, byte[] val, int skip, int size, int bufOffset) {
throw new UnsupportedOperationException("UniqueMemoryBank does not support paging");
}
@Override
protected void setPageInitialized(long addr, boolean initialized, int skip, int size,
int bufOffset) {
throw new UnsupportedOperationException("UniqueMemoryBank does not support paging");
}
@Override
public int getChunk(long offset, int size, byte[] dest, boolean stopOnUninitialized) {
int bytesRead = 0;
if (size == 0) {
return bytesRead;
}
try {
//align if necessary
int adjustment = (int) offset % WORD_SIZE;
if (adjustment != 0) {
WordInfo word = map.get(offset & ALIGNMENT_MASK);
if (word == null) {
throw new LowlevelError("Attempted to read uninitialized word in unique space");
}
for (int i = adjustment; i < WORD_SIZE && bytesRead < size; ++i) {
dest[bytesRead++] = word.getByte(i);
offset += 1;
}
}
//copy a word at a time
while (size - bytesRead > 0) {
WordInfo word = map.get(offset & ALIGNMENT_MASK);
if (word == null) {
throw new LowlevelError("Attempted to read uninitialized word in unique space");
}
offset += WORD_SIZE;
//whole word is initialized, copy it (or the appropriate
//initial segment) all at once
int bytesToRead = Math.min(WORD_SIZE, size - bytesRead);
if (word.isEntireWordInitialized()) {
word.getWord(buffer);
System.arraycopy(buffer, 0, dest, bytesRead,
Math.min(WORD_SIZE, size - bytesRead));
bytesRead += bytesToRead;
continue;
}
//not entirely initialized, copy one byte at a time until
//all requested bytes read (or word.getByte throws an exception)
int base = bytesRead;
for (int i = 0; i < bytesToRead; ++i) {
dest[base + i] = word.getByte(i);
bytesRead += 1;
}
}
return bytesRead;
}
catch (LowlevelError e) {
if (stopOnUninitialized) {
return bytesRead;
}
throw e;
}
}
@Override
public void setChunk(long offset, int size, byte[] src) {
if (size == 0 || src.length == 0) {
return;
}
int currentPosition = 0;
//align if necessary
int adjustment = (int) offset % WORD_SIZE;
if (adjustment != 0) {
WordInfo word = map.get(offset & ALIGNMENT_MASK);
if (word == null) {
word = new WordInfo();
map.put(offset & ALIGNMENT_MASK, word);
}
for (int i = adjustment; i < WORD_SIZE; ++i) {
word.setByte(src[currentPosition], i);
offset += 1;
currentPosition += 1;
}
}
while (size > currentPosition) {
WordInfo word = map.get(offset & ALIGNMENT_MASK);
if (word == null) {
word = new WordInfo();
map.put(offset & ALIGNMENT_MASK, word);
}
int bytesToWrite = Math.min(WORD_SIZE, size - currentPosition);
for (int i = 0; i < bytesToWrite; i++) {
word.setByte(src[currentPosition + i], i);
}
offset += bytesToWrite;
currentPosition += bytesToWrite;
}
return;
}
/**
* Clear unique storage at the start of an instruction
*/
public void clear() {
map.clear();
}
/**
* A simple class representing a byte-addressable word of memory. Each
* byte can be either initialized to a byte value or uninitialized.
* It is an error to attempt to read an uninitialized byte.
*/
public static class WordInfo {
public byte initialized;
public long word;
/**
* Constructs a {@link WordInfo} object with all bytes uninitialized.
*/
public WordInfo() {
initialized = 0;
word = 0;
}
/**
* Initializes the byte at {@code index} and sets its value to
* {@code val}
* @param val new value
* @param index index
* @throws LowlevelError if the index is invalid
*/
public void setByte(byte val, int index) {
validateIndex(index);
word &= ~(0xffL << (WORD_SIZE * index));
long shifted = ((long) val) << (WORD_SIZE * index);
word |= shifted;
initialized |= (1 << index);
}
/**
* Returns the byte at the given index
* @param index index
* @return corresponding byte value
* @throws LowlevelError if the index is invalid or the requested byte
* is not initialized.
*/
public byte getByte(int index) {
validateIndex(index);
checkInitialized(index);
long selected = word & (0xffL << (WORD_SIZE * index));
long adjusted = selected >> (WORD_SIZE * index);
return (byte) adjusted;
}
/**
* Writes an entire word into {@code buffer}
* @param buffer buffer to write a single word to. Must have
* length 8.
* @throws LowlevelError if the entire word is not initialized
*/
public void getWord(byte[] buffer) {
if (initialized != ((byte) (0xff))) {
throw new LowlevelError("Attempted to read uninitialized word in unique space");
}
if (buffer.length != WORD_SIZE) {
throw new IllegalArgumentException("Buffer must have length 8");
}
for (int i = 0; i < WORD_SIZE; ++i) {
buffer[i] = (byte) ((word & (0xffL << (WORD_SIZE * i))) >> (WORD_SIZE * i));
}
}
/**
* Returns true precisely when the entire word is initialized.
* @return true if entire work initialized
*/
protected boolean isEntireWordInitialized() {
return initialized == (byte) 0xff;
}
//assumes 0 <= index <= 7
private void checkInitialized(int index) {
if ((initialized & (1 << (index))) == 0) {
throw new LowlevelError(
"Attempted to read uninitialized memory in the unique space.");
}
}
//ensure that the provided index is valid
private void validateIndex(int index) {
if (index < 0 || index > 7) {
throw new LowlevelError("Invalid index: " + Integer.toString(index));
}
return;
}
}
}

View file

@ -1,63 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import java.math.BigInteger;
public abstract class BinaryOpBehavior extends OpBehavior {
BinaryOpBehavior(int opcode) {
super(opcode);
}
/**
* Evaluate the binary (2 input args) operation using long data
* @param sizeout intended output size (bytes)
* @param sizein in1 size (bytes)
* @param unsignedIn1 unsigned input 1
* @param unsignedIn2 unsigned input 2
* @return operation result. NOTE: if the operation overflows bits may be
* set beyond the specified sizeout. Even though results should be treated
* as unsigned it may be returned as a signed long value. It is expected that the
* returned result always be properly truncated by the caller since the evaluation
* may not - this is done to conserve emulation cycles.
* @see Utils#longToBytes(long, int, boolean)
* @see Utils#bytesToLong(byte[], int, boolean)
*/
public abstract long evaluateBinary(int sizeout, int sizein, long unsignedIn1, long unsignedIn2);
/**
* Evaluate the binary (2 input args) operation using BigInteger data
* @param sizeout intended output size (bytes)
* @param sizein in1 size (bytes)
* @param unsignedIn1 unsigned input 1
* @param unsignedIn2 unsigned input 2
* @return operation result. NOTE: if the operation overflows bits may be
* set beyond the specified sizeout. Even though results should be treated
* as unsigned it may be returned as a signed value. It is expected that the
* returned result always be properly truncated by the caller since the evaluation
* may not - this is done to conserve emulation cycles.
* @see Utils#bigIntegerToBytes(BigInteger, int, boolean)
* @see Utils#bytesToBigInteger(byte[], int, boolean, boolean)
*/
public abstract BigInteger evaluateBinary(int sizeout, int sizein, BigInteger unsignedIn1,
BigInteger unsignedIn2);
}

View file

@ -1,31 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
public class OpBehavior {
final int opcode;
OpBehavior(int opcode) {
this.opcode = opcode;
}
public int getOpCode() {
return opcode;
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorBoolAnd extends BinaryOpBehavior {
public OpBehaviorBoolAnd() {
super(PcodeOp.BOOL_AND);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 & in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.and(in2);
return res;
}
}

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorBoolNegate extends UnaryOpBehavior {
public OpBehaviorBoolNegate() {
super(PcodeOp.BOOL_NEGATE);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
long res = in1 ^ 1;
return res;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
BigInteger res = in1.xor(BigInteger.ONE);
return res;
}
}

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorBoolOr extends BinaryOpBehavior {
public OpBehaviorBoolOr() {
super(PcodeOp.BOOL_OR);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 | in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.or(in2);
return res;
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorBoolXor extends BinaryOpBehavior {
public OpBehaviorBoolXor() {
super(PcodeOp.BOOL_XOR);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 ^ in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.xor(in2);
return res;
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorCopy extends UnaryOpBehavior {
public OpBehaviorCopy() {
super(PcodeOp.COPY);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
return in1;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
return in1;
}
// @Override
// public long recoverInputUnary( int sizeout, long out, int sizein ) {
// return out;
// }
}

View file

@ -1,39 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorEqual extends BinaryOpBehavior {
public OpBehaviorEqual() {
super(PcodeOp.INT_EQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
return (in1 == in2) ? 1 : 0;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.equals(in2) ? BigInteger.ONE : BigInteger.ZERO;
return res;
}
}

View file

@ -1,117 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.util.HashMap;
import java.util.Map;
import ghidra.program.model.pcode.PcodeOp;
public class OpBehaviorFactory {
private static Map<Integer, OpBehavior> opBehaviorMap = new HashMap<Integer, OpBehavior>();
static {
// TODO: should pass float format factory
opBehaviorMap.put(PcodeOp.COPY, new OpBehaviorCopy());
opBehaviorMap.put(PcodeOp.LOAD, new SpecialOpBehavior(PcodeOp.LOAD));
opBehaviorMap.put(PcodeOp.STORE, new SpecialOpBehavior(PcodeOp.STORE));
opBehaviorMap.put(PcodeOp.BRANCH, new SpecialOpBehavior(PcodeOp.BRANCH));
opBehaviorMap.put(PcodeOp.CBRANCH, new SpecialOpBehavior(PcodeOp.CBRANCH));
opBehaviorMap.put(PcodeOp.BRANCHIND, new SpecialOpBehavior(PcodeOp.BRANCHIND));
opBehaviorMap.put(PcodeOp.CALL, new SpecialOpBehavior(PcodeOp.CALL));
opBehaviorMap.put(PcodeOp.CALLIND, new SpecialOpBehavior(PcodeOp.CALLIND));
opBehaviorMap.put(PcodeOp.CALLOTHER, new SpecialOpBehavior(PcodeOp.CALLOTHER));
opBehaviorMap.put(PcodeOp.RETURN, new SpecialOpBehavior(PcodeOp.RETURN));
opBehaviorMap.put(PcodeOp.MULTIEQUAL, new SpecialOpBehavior(PcodeOp.MULTIEQUAL));
opBehaviorMap.put(PcodeOp.INDIRECT, new SpecialOpBehavior(PcodeOp.INDIRECT));
opBehaviorMap.put(PcodeOp.PIECE, new OpBehaviorPiece());
opBehaviorMap.put(PcodeOp.SUBPIECE, new OpBehaviorSubpiece());
opBehaviorMap.put(PcodeOp.INT_EQUAL, new OpBehaviorEqual());
opBehaviorMap.put(PcodeOp.INT_NOTEQUAL, new OpBehaviorNotEqual());
opBehaviorMap.put(PcodeOp.INT_SLESS, new OpBehaviorIntSless());
opBehaviorMap.put(PcodeOp.INT_SLESSEQUAL, new OpBehaviorIntSlessEqual());
opBehaviorMap.put(PcodeOp.INT_LESS, new OpBehaviorIntLess());
opBehaviorMap.put(PcodeOp.INT_LESSEQUAL, new OpBehaviorIntLessEqual());
opBehaviorMap.put(PcodeOp.INT_ZEXT, new OpBehaviorIntZext());
opBehaviorMap.put(PcodeOp.INT_SEXT, new OpBehaviorIntSext());
opBehaviorMap.put(PcodeOp.INT_ADD, new OpBehaviorIntAdd());
opBehaviorMap.put(PcodeOp.INT_SUB, new OpBehaviorIntSub());
opBehaviorMap.put(PcodeOp.INT_CARRY, new OpBehaviorIntCarry());
opBehaviorMap.put(PcodeOp.INT_SCARRY, new OpBehaviorIntScarry());
opBehaviorMap.put(PcodeOp.INT_SBORROW, new OpBehaviorIntSborrow());
opBehaviorMap.put(PcodeOp.INT_2COMP, new OpBehaviorInt2Comp());
opBehaviorMap.put(PcodeOp.INT_NEGATE, new OpBehaviorIntNegate());
opBehaviorMap.put(PcodeOp.INT_XOR, new OpBehaviorIntXor());
opBehaviorMap.put(PcodeOp.INT_AND, new OpBehaviorIntAnd());
opBehaviorMap.put(PcodeOp.INT_OR, new OpBehaviorIntOr());
opBehaviorMap.put(PcodeOp.INT_LEFT, new OpBehaviorIntLeft());
opBehaviorMap.put(PcodeOp.INT_RIGHT, new OpBehaviorIntRight());
opBehaviorMap.put(PcodeOp.INT_SRIGHT, new OpBehaviorIntSright());
opBehaviorMap.put(PcodeOp.INT_MULT, new OpBehaviorIntMult());
opBehaviorMap.put(PcodeOp.INT_DIV, new OpBehaviorIntDiv());
opBehaviorMap.put(PcodeOp.INT_SDIV, new OpBehaviorIntSdiv());
opBehaviorMap.put(PcodeOp.INT_REM, new OpBehaviorIntRem());
opBehaviorMap.put(PcodeOp.INT_SREM, new OpBehaviorIntSrem());
opBehaviorMap.put(PcodeOp.BOOL_NEGATE, new OpBehaviorBoolNegate());
opBehaviorMap.put(PcodeOp.BOOL_XOR, new OpBehaviorBoolXor());
opBehaviorMap.put(PcodeOp.BOOL_AND, new OpBehaviorBoolAnd());
opBehaviorMap.put(PcodeOp.BOOL_OR, new OpBehaviorBoolOr());
opBehaviorMap.put(PcodeOp.CAST, new SpecialOpBehavior(PcodeOp.CAST));
opBehaviorMap.put(PcodeOp.PTRADD, new SpecialOpBehavior(PcodeOp.PTRADD));
opBehaviorMap.put(PcodeOp.PTRSUB, new SpecialOpBehavior(PcodeOp.PTRSUB));
opBehaviorMap.put(PcodeOp.FLOAT_EQUAL, new OpBehaviorFloatEqual());
opBehaviorMap.put(PcodeOp.FLOAT_NOTEQUAL, new OpBehaviorFloatNotEqual());
opBehaviorMap.put(PcodeOp.FLOAT_LESS, new OpBehaviorFloatLess());
opBehaviorMap.put(PcodeOp.FLOAT_LESSEQUAL, new OpBehaviorFloatLessEqual());
opBehaviorMap.put(PcodeOp.FLOAT_NAN, new OpBehaviorFloatNan());
opBehaviorMap.put(PcodeOp.FLOAT_ADD, new OpBehaviorFloatAdd());
opBehaviorMap.put(PcodeOp.FLOAT_DIV, new OpBehaviorFloatDiv());
opBehaviorMap.put(PcodeOp.FLOAT_MULT, new OpBehaviorFloatMult());
opBehaviorMap.put(PcodeOp.FLOAT_SUB, new OpBehaviorFloatSub());
opBehaviorMap.put(PcodeOp.FLOAT_NEG, new OpBehaviorFloatNeg());
opBehaviorMap.put(PcodeOp.FLOAT_ABS, new OpBehaviorFloatAbs());
opBehaviorMap.put(PcodeOp.FLOAT_SQRT, new OpBehaviorFloatSqrt());
opBehaviorMap.put(PcodeOp.FLOAT_INT2FLOAT, new OpBehaviorFloatInt2Float());
opBehaviorMap.put(PcodeOp.FLOAT_FLOAT2FLOAT, new OpBehaviorFloatFloat2Float());
opBehaviorMap.put(PcodeOp.FLOAT_TRUNC, new OpBehaviorFloatTrunc());
opBehaviorMap.put(PcodeOp.FLOAT_CEIL, new OpBehaviorFloatCeil());
opBehaviorMap.put(PcodeOp.FLOAT_FLOOR, new OpBehaviorFloatFloor());
opBehaviorMap.put(PcodeOp.FLOAT_ROUND, new OpBehaviorFloatRound());
opBehaviorMap.put(PcodeOp.SEGMENTOP, new SpecialOpBehavior(PcodeOp.SEGMENTOP));
opBehaviorMap.put(PcodeOp.CPOOLREF, new SpecialOpBehavior(PcodeOp.CPOOLREF));
opBehaviorMap.put(PcodeOp.NEW, new SpecialOpBehavior(PcodeOp.NEW));
opBehaviorMap.put(PcodeOp.INSERT, new SpecialOpBehavior(PcodeOp.INSERT));
opBehaviorMap.put(PcodeOp.EXTRACT, new SpecialOpBehavior(PcodeOp.EXTRACT));
opBehaviorMap.put(PcodeOp.POPCOUNT, new OpBehaviorPopcount());
opBehaviorMap.put(PcodeOp.LZCOUNT, new OpBehaviorLzcount());
}
private OpBehaviorFactory() {
}
public static OpBehavior getOpBehavior(int opcode) {
return opBehaviorMap.get(opcode);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatAbs extends UnaryOpBehavior {
public OpBehaviorFloatAbs() {
super(PcodeOp.FLOAT_ABS);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opAbs(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opAbs(in1);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatAdd extends BinaryOpBehavior {
public OpBehaviorFloatAdd() {
super(PcodeOp.FLOAT_ADD);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opAdd(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opAdd(in1, in2);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatCeil extends UnaryOpBehavior {
public OpBehaviorFloatCeil() {
super(PcodeOp.FLOAT_CEIL);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opCeil(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opCeil(in1);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatDiv extends BinaryOpBehavior {
public OpBehaviorFloatDiv() {
super(PcodeOp.FLOAT_DIV);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opDiv(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opDiv(in1, in2);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatEqual extends BinaryOpBehavior {
public OpBehaviorFloatEqual() {
super(PcodeOp.FLOAT_EQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opEqual(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opEqual(in1, in2);
}
}

View file

@ -1,45 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatFloat2Float extends UnaryOpBehavior {
public OpBehaviorFloatFloat2Float() {
super(PcodeOp.FLOAT_FLOAT2FLOAT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat formatout = FloatFormatFactory.getFloatFormat(sizeout);
FloatFormat formatin = FloatFormatFactory.getFloatFormat(sizein);
return formatin.opFloat2Float(in1, formatout);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat formatout = FloatFormatFactory.getFloatFormat(sizeout);
FloatFormat formatin = FloatFormatFactory.getFloatFormat(sizein);
return formatin.opFloat2Float(in1, formatout);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatFloor extends UnaryOpBehavior {
public OpBehaviorFloatFloor() {
super(PcodeOp.FLOAT_FLOOR);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opFloor(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opFloor(in1);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatInt2Float extends UnaryOpBehavior {
public OpBehaviorFloatInt2Float() {
super(PcodeOp.FLOAT_INT2FLOAT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizeout);
return format.opInt2Float(in1, sizein);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizeout);
return format.opInt2Float(in1, sizein, true);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatLess extends BinaryOpBehavior {
public OpBehaviorFloatLess() {
super(PcodeOp.FLOAT_LESS);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opLess(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opLess(in1, in2);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatLessEqual extends BinaryOpBehavior {
public OpBehaviorFloatLessEqual() {
super(PcodeOp.FLOAT_LESSEQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opLessEqual(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opLessEqual(in1, in2);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatMult extends BinaryOpBehavior {
public OpBehaviorFloatMult() {
super(PcodeOp.FLOAT_MULT);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opMult(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opMult(in1, in2);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatNan extends UnaryOpBehavior {
public OpBehaviorFloatNan() {
super(PcodeOp.FLOAT_NAN);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNan(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNan(in1);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatNeg extends UnaryOpBehavior {
public OpBehaviorFloatNeg() {
super(PcodeOp.FLOAT_NEG);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNeg(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNeg(in1);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatNotEqual extends BinaryOpBehavior {
public OpBehaviorFloatNotEqual() {
super(PcodeOp.FLOAT_NOTEQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNotEqual(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opNotEqual(in1, in2);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatRound extends UnaryOpBehavior {
public OpBehaviorFloatRound() {
super(PcodeOp.FLOAT_ROUND);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opRound(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opRound(in1);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatSqrt extends UnaryOpBehavior {
public OpBehaviorFloatSqrt() {
super(PcodeOp.FLOAT_SQRT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opSqrt(in1);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opSqrt(in1);
}
}

View file

@ -1,43 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatSub extends BinaryOpBehavior {
public OpBehaviorFloatSub() {
super(PcodeOp.FLOAT_SUB);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opSub(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opSub(in1, in2);
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorFloatTrunc extends UnaryOpBehavior {
public OpBehaviorFloatTrunc() {
super(PcodeOp.FLOAT_TRUNC);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opTrunc(in1, sizeout);
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
FloatFormat format = FloatFormatFactory.getFloatFormat(sizein);
return format.opTrunc(in1, sizeout);
}
}

View file

@ -1,45 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
import java.math.BigInteger;
public class OpBehaviorInt2Comp extends UnaryOpBehavior {
public OpBehaviorInt2Comp() {
super(PcodeOp.INT_2COMP);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
long res = Utils.uintb_negate(in1 - 1, sizein);
return res;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
if (in1.signum() < 0) {
throw new AssertException("Expected unsigned in value");
}
BigInteger res = in1.negate();
return res;
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntAdd extends BinaryOpBehavior {
public OpBehaviorIntAdd() {
super(PcodeOp.INT_ADD);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = (in1 + in2) & Utils.calc_mask(sizeout);
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.add(in2);
return res;
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntAnd extends BinaryOpBehavior {
public OpBehaviorIntAnd() {
super(PcodeOp.INT_AND);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 & in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.and(in2);
return res;
}
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
public class OpBehaviorIntCarry extends BinaryOpBehavior {
public OpBehaviorIntCarry() {
super(PcodeOp.INT_CARRY);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
return (Long.compareUnsigned(in1, (in1 + in2) & Utils.calc_mask(sizein)) > 0) ? 1 : 0;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in1.signum() < 0 || in2.signum() < 0) {
throw new AssertException("Expected unsigned in values");
}
BigInteger res =
(in1.compareTo(in1.add(in2).and(Utils.calc_bigmask(sizein))) > 0) ? BigInteger.ONE
: BigInteger.ZERO;
return res;
}
}

View file

@ -1,69 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntDiv extends BinaryOpBehavior {
public OpBehaviorIntDiv() {
super(PcodeOp.INT_DIV);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (sizein <= 0 || in2 == 0)
return 0;
if (in1 == in2)
return 1;
if (sizein == 8) {
long mask = (0x1<<63);
long bit1 = in1 & mask; // Get the sign bits
long bit2 = in2 & mask;
if (bit1 != 0 || bit2 != 0) {
// use BigInteger to perform 64-bit unsigned division if one negative input
BigInteger bigIn1 =
Utils.bytesToBigInteger(Utils.longToBytes(in1, sizein, true), sizein, true,
false);
if (bigIn1.signum() < 0) {
bigIn1 = Utils.convertToUnsignedValue(bigIn1, sizein);
}
BigInteger bigIn2 =
Utils.bytesToBigInteger(Utils.longToBytes(in2, sizein, true), sizein, true,
false);
if (bigIn2.signum() < 0) {
bigIn2 = Utils.convertToUnsignedValue(bigIn2, sizein);
}
BigInteger result = bigIn1.divide(bigIn2);
return result.longValue() & Utils.calc_mask(sizeout);
}
}
return (in1 / in2) & Utils.calc_mask(sizeout);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (sizein <= 0 || in2.signum() == 0)
return BigInteger.ZERO;
BigInteger res = in1.divide(in2);
return res;
}
}

View file

@ -1,51 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
import java.math.BigInteger;
public class OpBehaviorIntLeft extends BinaryOpBehavior {
public OpBehaviorIntLeft() {
super(PcodeOp.INT_LEFT);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (in2 < 0 || in2 >= (8 * sizein)) {
return 0;
}
return (in1 << in2) & Utils.calc_mask(sizeout);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in1.signum() < 0 || in2.signum() < 0) {
throw new AssertException("Expected unsigned in values");
}
BigInteger maxShift = BigInteger.valueOf(sizein * 8);
if (in2.compareTo(maxShift) >= 0) {
return BigInteger.ZERO;
}
return in1.shiftLeft(in2.intValue());
}
}

View file

@ -1,66 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntLess extends BinaryOpBehavior {
public OpBehaviorIntLess() {
super(PcodeOp.INT_LESS);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res, mask, bit1, bit2;
if (sizein <= 0) {
res = 0;
}
else {
mask = Utils.calc_mask(sizein);
in1 &= mask;
in2 &= mask;
if (in1 == in2) {
res = 0;
}
else if (sizein < 8) {
res = (in1 < in2) ? 1 : 0;
}
else {
mask = 0x80;
mask <<= 8 * (sizein - 1);
bit1 = in1 & mask; // Get the sign bits
bit2 = in2 & mask;
if (bit1 != bit2)
res = (bit1 != 0) ? 0 : 1;
else
res = (in1 < in2) ? 1 : 0;
}
}
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = (in1.compareTo(in2) < 0) ? BigInteger.ONE : BigInteger.ZERO;
return res;
}
}

View file

@ -1,66 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntLessEqual extends BinaryOpBehavior {
public OpBehaviorIntLessEqual() {
super(PcodeOp.INT_LESSEQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res, mask, bit1, bit2;
if (sizein <= 0) {
res = 0;
}
else {
mask = Utils.calc_mask(sizein);
in1 &= mask;
in2 &= mask;
if (in1 == in2) {
res = 1;
}
else if (sizein < 8) {
res = (in1 < in2) ? 1 : 0;
}
else {
mask = 0x80;
mask <<= 8 * (sizein - 1);
bit1 = in1 & mask; // Get the sign bits
bit2 = in2 & mask;
if (bit1 != bit2)
res = (bit1 != 0) ? 0 : 1;
else
res = (in1 < in2) ? 1 : 0;
}
}
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = (in1.compareTo(in2) <= 0) ? BigInteger.ONE : BigInteger.ZERO;
return res;
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntMult extends BinaryOpBehavior {
public OpBehaviorIntMult() {
super(PcodeOp.INT_MULT);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = (in1 * in2) & Utils.calc_mask(sizeout);
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.multiply(in2);
return res;
}
}

View file

@ -1,45 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
import java.math.BigInteger;
public class OpBehaviorIntNegate extends UnaryOpBehavior {
public OpBehaviorIntNegate() {
super(PcodeOp.INT_NEGATE);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
long res = Utils.uintb_negate(in1, sizein);
return res;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
if (in1.signum() < 0) {
throw new AssertException("Expected unsigned in value");
}
return in1.not();
}
}

View file

@ -1,41 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntOr extends BinaryOpBehavior {
public OpBehaviorIntOr() {
super(PcodeOp.INT_OR);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 | in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.or(in2);
return res;
}
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import ghidra.pcode.error.LowlevelError;
import ghidra.program.model.pcode.PcodeOp;
public class OpBehaviorIntRem extends BinaryOpBehavior {
public OpBehaviorIntRem() {
super(PcodeOp.INT_REM);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (in2 == 0) {
throw new LowlevelError("Remainder by 0");
}
return Long.remainderUnsigned(in1, in2);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in2.signum() == 0) {
throw new LowlevelError("Remainder by 0");
}
BigInteger res = in1.remainder(in2);
return res;
}
}

View file

@ -1,52 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
import java.math.BigInteger;
public class OpBehaviorIntRight extends BinaryOpBehavior {
public OpBehaviorIntRight() {
super(PcodeOp.INT_RIGHT);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (in2 < 0 || in2 >= (8 * sizein)) {
return 0;
}
return (in1 >>> in2) & Utils.calc_mask(sizeout);
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in1.signum() < 0 || in2.signum() < 0) {
throw new AssertException("Expected unsigned in values");
}
BigInteger maxShift = BigInteger.valueOf(sizein * 8);
if (in2.compareTo(maxShift) >= 0) {
return BigInteger.ZERO;
}
return in1.shiftRight(in2.intValue());
}
}

View file

@ -1,58 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSborrow extends BinaryOpBehavior {
public OpBehaviorIntSborrow() {
super(PcodeOp.INT_SBORROW);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 - in2;
int a = (int) (in1 >> (sizein * 8 - 1)) & 1; // Grab sign bit
int b = (int) (in2 >> (sizein * 8 - 1)) & 1; // Grab sign bit
int r = (int) (res >> (sizein * 8 - 1)) & 1; // Grab sign bit
a ^= r;
r ^= b;
r ^= 1;
a &= r;
return a;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.subtract(in2);
boolean a = in1.testBit(sizein * 8 - 1); // Grab sign bit
boolean b = in2.testBit(sizein * 8 - 1); // Grab sign bit
boolean r = res.testBit(sizein * 8 - 1); // Grab sign bit
a ^= r;
r ^= b;
r ^= true;
a &= r;
return a ? BigInteger.ONE : BigInteger.ZERO;
}
}

View file

@ -1,59 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntScarry extends BinaryOpBehavior {
public OpBehaviorIntScarry() {
super(PcodeOp.INT_SCARRY);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 + in2;
int a = (int) (in1 >> (sizein * 8 - 1)) & 1; // Grab sign bit
int b = (int) (in2 >> (sizein * 8 - 1)) & 1; // Grab sign bit
int r = (int) (res >> (sizein * 8 - 1)) & 1; // Grab sign bit
r ^= a;
a ^= b;
a ^= 1;
r &= a;
return r;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.add(in2);
boolean a = in1.testBit(sizein * 8 - 1); // Grab sign bit
boolean b = in2.testBit(sizein * 8 - 1); // Grab sign bit
boolean r = res.testBit(sizein * 8 - 1); // Grab sign bit
r ^= a;
a ^= b;
a ^= true;
r &= a;
return r ? BigInteger.ONE : BigInteger.ZERO;
}
}

View file

@ -1,55 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSdiv extends BinaryOpBehavior {
public OpBehaviorIntSdiv() {
super(PcodeOp.INT_SDIV);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (in2 == 0)
throw new LowlevelError("Divide by 0");
long num = in1; // Convert to signed
long denom = in2;
num = Utils.zzz_sign_extend(num, 8 * sizein - 1);
denom = Utils.zzz_sign_extend(denom, 8 * sizein - 1);
long sres = num / denom; // Do the signed division
// Cut to appropriate size
sres = Utils.zzz_zero_extend(sres, 8 * sizeout - 1);
return sres; // Recast as unsigned
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in2.signum() == 0)
throw new LowlevelError("Divide by 0");
// convert to signed
in1 = Utils.convertToSignedValue(in1, sizein);
in2 = Utils.convertToSignedValue(in2, sizein);
return in1.divide(in2);
}
}

View file

@ -1,57 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSext extends UnaryOpBehavior {
public OpBehaviorIntSext() {
super(PcodeOp.INT_SEXT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
long res = Utils.sign_extend(in1, sizein, sizeout);
return res;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
return Utils.convertToSignedValue(in1, sizein);
}
// @Override
// public long recoverInputUnary(int sizeout, long out, int sizein) {
// long masklong = Utils.calc_mask(sizeout);
// long maskshort = Utils.calc_mask(sizein);
//
// if ((out & (maskshort ^ (maskshort >>> 1))) == 0) { // Positive input
// if ((out & maskshort) != out)
// throw new LowlevelError(
// "Output is not in range of sext operation");
// } else { // Negative input
// if ((out & (masklong ^ maskshort)) != (masklong ^ maskshort))
// throw new LowlevelError(
// "Output is not in range of sext operation");
// }
// return (out & maskshort);
// }
}

View file

@ -1,59 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSless extends BinaryOpBehavior {
public OpBehaviorIntSless() {
super(PcodeOp.INT_SLESS);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res, mask, bit1, bit2;
if (sizein <= 0)
res = 0;
else {
mask = 0x80;
mask <<= 8 * (sizein - 1);
bit1 = in1 & mask; // Get the sign bits
bit2 = in2 & mask;
if (bit1 != bit2)
res = (bit1 != 0) ? 1 : 0;
else
res = (in1 < in2) ? 1 : 0;
}
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (sizein <= 0)
return BigInteger.ZERO;
// convert to signed
in1 = Utils.convertToSignedValue(in1, sizein);
in2 = Utils.convertToSignedValue(in2, sizein);
return (in1.compareTo(in2) < 0) ? BigInteger.ONE : BigInteger.ZERO;
}
}

View file

@ -1,59 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSlessEqual extends BinaryOpBehavior {
public OpBehaviorIntSlessEqual() {
super(PcodeOp.INT_SLESSEQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res, mask, bit1, bit2;
if (sizein <= 0)
res = 0;
else {
mask = 0x80;
mask <<= 8 * (sizein - 1);
bit1 = in1 & mask; // Get the sign bits
bit2 = in2 & mask;
if (bit1 != bit2)
res = (bit1 != 0) ? 1 : 0;
else
res = (in1 <= in2) ? 1 : 0;
}
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (sizein <= 0)
return BigInteger.ZERO;
// convert to signed
in1 = Utils.convertToSignedValue(in1, sizein);
in2 = Utils.convertToSignedValue(in2, sizein);
return (in1.compareTo(in2) <= 0) ? BigInteger.ONE : BigInteger.ZERO;
}
}

View file

@ -1,57 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSrem extends BinaryOpBehavior {
public OpBehaviorIntSrem() {
super(PcodeOp.INT_SREM);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
if (in2 == 0)
throw new LowlevelError("Remainder by 0");
long val = in1;
long mod = in2;
// Convert inputs to signed values
val = Utils.zzz_sign_extend(val, 8 * sizein - 1);
mod = Utils.zzz_sign_extend(mod, 8 * sizein - 1);
// Do the remainder
long sres = val % mod;
// Convert back to unsigned
sres = Utils.zzz_zero_extend(sres, 8 * sizeout - 1);
return sres;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in2.signum() == 0)
throw new LowlevelError("Remainder by 0");
// convert to signed
in1 = Utils.convertToSignedValue(in1, sizein);
in2 = Utils.convertToSignedValue(in2, sizein);
return in1.remainder(in2);
}
}

View file

@ -1,69 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.AssertException;
import java.math.BigInteger;
public class OpBehaviorIntSright extends BinaryOpBehavior {
public OpBehaviorIntSright() {
super(PcodeOp.INT_SRIGHT);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long maxShift = (sizein * 8) - 1;
if (in2 < 0 || in2 > maxShift) {
if (Utils.signbit_negative(in1, sizein)) {
return Utils.calc_mask(sizein);
}
return 0;
}
long res;
if (Utils.signbit_negative(in1, sizein)) {
res = in1 >> in2;
long mask = Utils.calc_mask(sizein);
mask = (mask >>> in2) ^ mask;
res |= mask;
}
else {
res = in1 >>> in2;
}
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
if (in1.signum() < 0 || in2.signum() < 0) {
throw new AssertException("Expected unsigned in values");
}
int signbit = (sizein * 8) - 1;
BigInteger maxShift = BigInteger.valueOf(signbit);
if (in2.compareTo(maxShift) > 0) {
in2 = maxShift;
}
if (in1.testBit(signbit)) {
in1 = Utils.convertToSignedValue(in1, sizein);
}
return in1.shiftRight(in2.intValue());
}
}

View file

@ -1,42 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntSub extends BinaryOpBehavior {
public OpBehaviorIntSub() {
super(PcodeOp.INT_SUB);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = (in1 - in2) & Utils.calc_mask(sizeout);
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.subtract(in2);
return res;
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntXor extends BinaryOpBehavior {
public OpBehaviorIntXor() {
super(PcodeOp.INT_XOR);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = in1 ^ in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.xor(in2);
return res;
}
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorIntZext extends UnaryOpBehavior {
public OpBehaviorIntZext() {
super(PcodeOp.INT_ZEXT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long in1) {
return in1;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger in1) {
return in1;
}
// @Override
// public long recoverInputUnary(int sizeout, long out, int sizein) {
// long mask = Utils.calc_mask(sizein);
// if ((mask & out) != out)
// throw new LowlevelError("Output is not in range of zext operation");
// return out;
// }
}

View file

@ -1,62 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import ghidra.program.model.pcode.PcodeOp;
public class OpBehaviorLzcount extends UnaryOpBehavior {
public OpBehaviorLzcount() {
super(PcodeOp.LZCOUNT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long val) {
long mask = 1L << ((sizein * 8) - 1);
long count = 0;
while (mask != 0) {
if ((mask & val) != 0) {
break;
}
++count;
mask >>>= 1;
}
return count;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger unsignedIn1) {
int bitcount = 0;
sizein = sizein * 8 - 1;
while (sizein >= 0) {
if (unsignedIn1.testBit(sizein)) {
break;
}
bitcount += 1;
sizein -= 1;
}
if (sizeout == 1) {
bitcount &= 0xff;
}
else if (sizeout == 2) {
bitcount &= 0xffff;
}
return BigInteger.valueOf(bitcount);
}
}

View file

@ -1,38 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorNotEqual extends BinaryOpBehavior {
public OpBehaviorNotEqual() {
super(PcodeOp.INT_NOTEQUAL);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
return in1 != in2 ? 1 : 0;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
return in1.equals(in2) ? BigInteger.ZERO : BigInteger.ONE;
}
}

View file

@ -1,40 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorPiece extends BinaryOpBehavior {
public OpBehaviorPiece() {
super(PcodeOp.PIECE);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = (in1 << (sizein * 8)) | in2;
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
BigInteger res = in1.shiftLeft(sizein * 8).or(in2);
return res;
}
}

View file

@ -1,64 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import ghidra.program.model.pcode.PcodeOp;
public class OpBehaviorPopcount extends UnaryOpBehavior {
public OpBehaviorPopcount() {
super(PcodeOp.POPCOUNT);
}
@Override
public long evaluateUnary(int sizeout, int sizein, long val) {
val = (val & 0x5555555555555555L) + ((val >>> 1) & 0x5555555555555555L);
val = (val & 0x3333333333333333L) + ((val >>> 2) & 0x3333333333333333L);
val = (val & 0x0f0f0f0f0f0f0f0fL) + ((val >>> 4) & 0x0f0f0f0f0f0f0f0fL);
val = (val & 0x00ff00ff00ff00ffL) + ((val >>> 8) & 0x00ff00ff00ff00ffL);
val = (val & 0x0000ffff0000ffffL) + ((val >>> 16) & 0x0000ffff0000ffffL);
int res = (int) (val & 0xff);
res += (int) ((val >> 32) & 0xff);
return res;
}
@Override
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger unsignedIn1) {
int bitcount = 0;
while (sizein >= 8) {
bitcount += evaluateUnary(1, 8, unsignedIn1.longValue());
sizein -= 8;
if (sizein == 0) {
break;
}
unsignedIn1 = unsignedIn1.shiftRight(64);
}
if (sizein > 0) {
long mask = sizein * 8 - 1;
bitcount += evaluateUnary(1, 8, unsignedIn1.longValue() & mask);
}
if (sizeout == 1) {
bitcount &= 0xff;
}
else if (sizeout == 2) {
bitcount &= 0xffff;
}
return BigInteger.valueOf(bitcount);
}
}

View file

@ -1,55 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import ghidra.program.model.pcode.PcodeOp;
import java.math.BigInteger;
public class OpBehaviorSubpiece extends BinaryOpBehavior {
public OpBehaviorSubpiece() {
super(PcodeOp.SUBPIECE);
}
@Override
public long evaluateBinary(int sizeout, int sizein, long in1, long in2) {
long res = (in1 >>> (in2 * 8)) & Utils.calc_mask(sizeout);
return res;
}
@Override
public BigInteger evaluateBinary(int sizeout, int sizein, BigInteger in1, BigInteger in2) {
// must eliminate sign extension bits produced by BigInteger.shiftRight
int signbit = (sizein * 8) - 1;
BigInteger res = in1;
boolean negative = res.testBit(signbit);
if (negative) {
res = res.and(Utils.calc_bigmask(sizein));
res = res.clearBit(signbit);
}
int shift = in2.intValue() * 8;
res = res.shiftRight(shift);
signbit -= shift;
if (negative && signbit >= 0) {
res = res.setBit(signbit); // restore shifted sign bit
}
return res;
}
}

View file

@ -1,25 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
public class SpecialOpBehavior extends OpBehavior {
SpecialOpBehavior(int opcode) {
super(opcode);
}
}

View file

@ -1,58 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import ghidra.pcode.utils.Utils;
import java.math.BigInteger;
public abstract class UnaryOpBehavior extends OpBehavior {
UnaryOpBehavior(int opcode) {
super(opcode);
}
/**
* Evaluate the unary operation using long data
* @param sizeout intended output size (bytes)
* @param sizein in1 size (bytes)
* @param unsignedIn1 unsigned input 1
* @return operation result. NOTE: if the operation overflows bits may be
* set beyond the specified sizeout. Even though results should be treated
* as unsigned it may be returned as a signed long value. It is expected that the
* returned result always be properly truncated by the caller since the evaluation
* may not - this is done to conserve emulation cycles.
* @see Utils#longToBytes(long, int, boolean)
* @see Utils#bytesToLong(byte[], int, boolean)
*/
public abstract long evaluateUnary(int sizeout, int sizein, long unsignedIn1);
/**
* Evaluate the unary operation using BigInteger data
* @param sizeout intended output size (bytes)
* @param sizein in1 size (bytes)
* @param unsignedIn1 unsigned input 1
* @return operation result. NOTE: if the operation overflows bits may be
* set beyond the specified sizeout. Even though results should be treated
* as unsigned it may be returned as a signed value. It is expected that the
* returned result always be properly truncated by the caller since the evaluation
* may not - this is done to conserve emulation cycles.
* @see Utils#bigIntegerToBytes(BigInteger, int, boolean)
* @see Utils#bytesToBigInteger(byte[], int, boolean, boolean)
*/
public abstract BigInteger evaluateUnary(int sizeout, int sizein, BigInteger unsignedIn1);
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.pcoderaw;
import ghidra.pcode.opbehavior.OpBehavior;
import ghidra.pcode.opbehavior.OpBehaviorFactory;
import ghidra.program.model.address.Address;
import ghidra.program.model.pcode.PcodeOp;
public class PcodeOpRaw extends PcodeOp {
private OpBehavior behave;
public PcodeOpRaw(PcodeOp op) {
super(op.getSeqnum(), op.getOpcode(), op.getInputs(), op.getOutput());
behave = OpBehaviorFactory.getOpBehavior(op.getOpcode());
}
// Get the underlying behavior object for this pcode operation. From this
// object you can determine how the object evaluates inputs to get the output
// \return the behavior object
public OpBehavior getBehavior() {
return behave;
}
// This is a convenience function to get the address of the machine instruction
// (of which this pcode op is a translation)
// \return the machine instruction address
public Address getAddress() {
return getSeqnum().getTarget();
}
}

View file

@ -1,255 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.memstate;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import generic.test.AbstractGenericTest;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.memstate.UniqueMemoryBank.WordInfo;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.GenericAddressSpace;
import ghidra.program.model.lang.SpaceNames;
public class UniqueMemoryBankTest extends AbstractGenericTest {
private AddressSpace uniqueSpace;
private UniqueMemoryBank uniqueBank;
private byte[] eightTestBytes = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 };
private byte[] eightZeroBytes = new byte[8];
private byte[] sixteenTestBytes = new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,
0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
@Before
public void setUp() {
uniqueSpace =
new GenericAddressSpace(SpaceNames.UNIQUE_SPACE_NAME, 64, AddressSpace.TYPE_UNIQUE, 0);
uniqueBank = new UniqueMemoryBank(uniqueSpace, false);
}
public UniqueMemoryBankTest() {
super();
}
@Test
public void WordInfoBasicTest() {
WordInfo info = new WordInfo();
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x0, 0);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x1, 1);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x2, 2);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x3, 3);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x4, 4);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x5, 5);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x6, 6);
assertFalse(info.isEntireWordInitialized());
info.setByte((byte) 0x7, 7);
assertTrue(info.isEntireWordInitialized());
for (int i = 0; i < 8; ++i) {
assertEquals((byte) i, info.getByte(i));
}
}
@Test(expected = LowlevelError.class)
public void testGetUninitializedByte() {
WordInfo info = new WordInfo();
info.setByte((byte) 0, 0);
info.setByte((byte) 1, 1);
info.setByte((byte) 3, 3);
info.setByte((byte) 4, 4);
info.setByte((byte) 5, 5);
info.setByte((byte) 6, 6);
info.setByte((byte) 7, 7);
@SuppressWarnings("unused")
byte val = info.getByte(2);
}
@Test
public void testSimpleRead() {
uniqueBank.setChunk(0x1000, 8, eightTestBytes);
byte[] dest = new byte[8];
int numBytes = uniqueBank.getChunk(0x1000, 8, dest, true);
assertEquals(8, numBytes);
assertTrue(Arrays.equals(dest, eightTestBytes));
}
@Test
public void testDifferentlySizedReads() {
uniqueBank.setChunk(0x1000, 8, eightTestBytes);
byte[] dest = new byte[4];
int numBytes = uniqueBank.getChunk(0x1000, 4, dest, true);
assertEquals(4, numBytes);
assertTrue(Arrays.equals(dest, new byte[] { 0x0, 0x1, 0x2, 0x3 }));
numBytes = uniqueBank.getChunk(0x1004, 4, dest, true);
assertEquals(4, numBytes);
assertTrue(Arrays.equals(dest, new byte[] { 0x4, 0x5, 0x6, 0x7 }));
}
@Test
public void testLargeReadWrite() {
uniqueBank.setChunk(0x1004, 16, sixteenTestBytes);
byte[] dest = new byte[16];
int numBytes = uniqueBank.getChunk(0x1004, 16, dest, true);
assertEquals(16, numBytes);
assertTrue(Arrays.equals(dest, sixteenTestBytes));
byte[] largeSrc = new byte[64];
for (int i = 0; i < 64; ++i) {
largeSrc[i] = (byte) (i + 1);
}
uniqueBank.setChunk(0x1007, 64, largeSrc);
dest = new byte[64];
numBytes = uniqueBank.getChunk(0x1007, 64, dest, true);
assertEquals(64, numBytes);
assertTrue(Arrays.equals(dest, largeSrc));
}
@Test
public void testReadAcrossUndefined() {
byte[] fourBytes = new byte[] { 0x11, 0x22, 0x33, 0x44 };
uniqueBank.setChunk(0x1007, 4, fourBytes);
uniqueBank.setChunk(0x100c, 4, fourBytes);
byte[] dest = new byte[9];
int numBytes = uniqueBank.getChunk(0x1007, 9, dest, true);
assertEquals(4, numBytes);
assertEquals(0x11, dest[0]);
assertEquals(0x22, dest[1]);
assertEquals(0x33, dest[2]);
assertEquals(0x44, dest[3]);
}
@Test
public void testNonAlignedReadWrite() {
byte[] fourBytes = new byte[] { 0x11, 0x22, 0x33, 0x44 };
uniqueBank.setChunk(0x1004, 4, fourBytes);
byte[] dest = new byte[4];
int numBytes = uniqueBank.getChunk(0x1004, 4, dest, true);
assertEquals(4, numBytes);
assertTrue(Arrays.equals(fourBytes, dest));
}
@Test
public void testOverlappingReadWrite() {
uniqueBank.setChunk(0x1000, 16, sixteenTestBytes);
uniqueBank.setChunk(0x1004, 8, eightZeroBytes);
byte[] dest = new byte[16];
int numBytes = uniqueBank.getChunk(0x1000, 16, dest, true);
assertEquals(16, numBytes);
for (int i = 0; i < 16; ++i) {
if (i > 3 && i < 12) {
assertEquals(0, dest[i]);
}
else {
assertEquals(i, dest[i]);
}
}
}
@Test
public void testOneByteRead() {
byte[] one = new byte[] { (byte) 0x7f };
uniqueBank.setChunk(0x1000, 1, one);
byte[] dest = new byte[16];
int numBytes = uniqueBank.getChunk(0x1000, 1, dest, false);
assertEquals(1, numBytes);
assertEquals(dest[0], (byte) 0x7f);
}
@Test
public void testClear() {
uniqueBank.setChunk(0x1000, 8, eightTestBytes);
byte[] dest = new byte[8];
uniqueBank.clear();
int numBytes = uniqueBank.getChunk(0x1000, 8, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 7, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 6, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 5, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 4, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 3, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 2, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 1, dest, true);
assertEquals(0, numBytes);
numBytes = uniqueBank.getChunk(0x1000, 0, dest, true);
assertEquals(0, numBytes);
}
@Test
public void testSimpleOverwrite() {
uniqueBank.setChunk(0x1000, 8, eightTestBytes);
byte[] dest = new byte[8];
int numBytes = uniqueBank.getChunk(0x1000, 8, dest, true);
assertEquals(8, numBytes);
assertTrue(Arrays.equals(dest, eightTestBytes));
uniqueBank.setChunk(0x1000, 8, eightZeroBytes);
numBytes = uniqueBank.getChunk(0x1000, 8, dest, true);
assertEquals(8, numBytes);
assertTrue(Arrays.equals(dest, eightZeroBytes));
}
@Test(expected = LowlevelError.class)
public void testUninitializedReadStop() {
byte[] dest = new byte[16];
uniqueBank.getChunk(0x1000, 0x10, dest, false);
}
@Test
public void testUninitializedReadContinue() {
byte[] dest = new byte[16];
int bytesRead = uniqueBank.getChunk(0x1000, 0x10, dest, true);
assertEquals(0, bytesRead);
}
@SuppressWarnings("unused")
@Test(expected = UnsupportedOperationException.class)
public void testGetPageException() {
MemoryPage page = uniqueBank.getPage(0);
}
@Test(expected = UnsupportedOperationException.class)
public void testSetPageException() {
uniqueBank.setPage(0, new byte[0], 0, 4096, 0);
}
@Test(expected = UnsupportedOperationException.class)
public void testSetPageInitializedException() {
uniqueBank.setPageInitialized(0, true, 0, 4096, 0);
}
//possibly add:
//zero-byte read/write
//try to write more bytes than the array has
//try to read more bytes into the array than it has
}

View file

@ -1,66 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import generic.test.AbstractGenericTest;
import ghidra.pcode.utils.Utils;
import ghidra.util.StringUtilities;
public abstract class AbstractOpBehaviorTest extends AbstractGenericTest {
public AbstractOpBehaviorTest() {
super();
}
protected void assertEquals(BigInteger expected, BigInteger result, int byteSize) {
// discards irrelevant bytes before comparing - ignores overflow bytes
byte[] resultBytes = Utils.bigIntegerToBytes(result, byteSize, true);
byte[] expectedBytes = Utils.bigIntegerToBytes(expected, byteSize, true);
org.junit.Assert.assertEquals(toHexString(expectedBytes), toHexString(resultBytes));
}
protected void assertEquals(long expected, long result, int byteSize) {
// discards irrelevant bytes before comparing - ignores overflow bytes
byte[] resultBytes = Utils.longToBytes(result, byteSize, true);
byte[] expectedBytes = Utils.longToBytes(expected, byteSize, true);
org.junit.Assert.assertEquals(toHexString(expectedBytes), toHexString(resultBytes));
}
private String toHexString(byte[] bytes) {
StringBuilder buf = new StringBuilder("0x");
for (byte b : bytes) {
String valStr = StringUtilities.pad(Integer.toHexString(b & 0xff), '0', 2);
buf.append(valStr);
}
return buf.toString();
}
protected BigInteger getUnsignedBigInt(long val) {
if (val > 0) {
return BigInteger.valueOf(val);
}
return new BigInteger(1, Utils.longToBytes(val, 8, true));
}
protected BigInteger getUnsignedBigInt(long val, int size) {
if (val > 0) {
return BigInteger.valueOf(val);
}
return new BigInteger(1, Utils.longToBytes(val, size, true));
}
}

View file

@ -1,54 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
public class OpBehaviorBoolAndTest extends AbstractOpBehaviorTest {
public OpBehaviorBoolAndTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorBoolOr op = new OpBehaviorBoolOr();
Assert.assertEquals(0, op.evaluateBinary(1, 1, 0, 0));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 0, 1));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 1, 0));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 1, 1));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorBoolOr op = new OpBehaviorBoolOr();
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ONE));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ONE));
}
}

View file

@ -1,46 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
public class OpBehaviorBoolNegateTest extends AbstractOpBehaviorTest {
public OpBehaviorBoolNegateTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorBoolNegate op = new OpBehaviorBoolNegate();
Assert.assertEquals(1, op.evaluateUnary(1, 1, 0));
Assert.assertEquals(0, op.evaluateUnary(1, 1, 1));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorBoolNegate op = new OpBehaviorBoolNegate();
Assert.assertEquals(BigInteger.ONE, op.evaluateUnary(1, 1, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ZERO, op.evaluateUnary(1, 1, BigInteger.ONE));
}
}

View file

@ -1,50 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
public class OpBehaviorBoolOrTest extends AbstractOpBehaviorTest {
public OpBehaviorBoolOrTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorBoolOr op = new OpBehaviorBoolOr();
Assert.assertEquals(0, op.evaluateBinary(1, 1, 0, 0));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 0, 1));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 1, 0));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 1, 1));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorBoolOr op = new OpBehaviorBoolOr();
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ONE));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ONE));
}
}

View file

@ -1,50 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
public class OpBehaviorBoolXorTest extends AbstractOpBehaviorTest {
public OpBehaviorBoolXorTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorBoolXor op = new OpBehaviorBoolXor();
Assert.assertEquals(0, op.evaluateBinary(1, 1, 0, 0));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 0, 1));
Assert.assertEquals(1, op.evaluateBinary(1, 1, 1, 0));
Assert.assertEquals(0, op.evaluateBinary(1, 1, 1, 1));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorBoolXor op = new OpBehaviorBoolXor();
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 1, BigInteger.ZERO, BigInteger.ONE));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ZERO));
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 1, BigInteger.ONE, BigInteger.ONE));
}
}

View file

@ -1,88 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatAbsTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatAbsTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatAbs op = new OpBehaviorFloatAbs();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, ff.opAbs(a));
Assert.assertEquals(2.5, ff.getHostFloat(result), 0);
a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.5, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatAbs op = new OpBehaviorFloatAbs();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
}
}

View file

@ -1,108 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatAddTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatAddTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatAdd op = new OpBehaviorFloatAdd();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
long a = ff.getEncoding(1.234);
long b = ff.getEncoding(1.123);
long result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
Assert.assertEquals(2.357, ff.getHostFloat(result), 0);
a = ff.getEncoding(-1.123);
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
Assert.assertEquals(0d, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0);
b = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0);
b = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NaN);
b = ff.getEncoding(1.123);
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatAdd op = new OpBehaviorFloatAdd();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigInteger a = ff.getEncoding(ff.getBigFloat(1.234d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.123d));
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
Assert.assertEquals(ff.getBigFloat(2.357), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-1.123d));
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigInfinity(false));
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
b = ff.getBigInfinityEncoding(true);
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
b = ff.getEncoding(ff.getBigInfinity(false));
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
a = ff.getBigNaNEncoding(false);
b = ff.getEncoding(ff.getBigFloat(1.123d));
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
}
}

View file

@ -1,88 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatCeilTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatCeilTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatCeil op = new OpBehaviorFloatCeil();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
long a = ff.getEncoding(2.5);
long result = ff.opCeil(a);
Assert.assertEquals(3.0, ff.getHostFloat(result), 0);
a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatCeil op = new OpBehaviorFloatCeil();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
}
}

View file

@ -1,82 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatDivTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatDivTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatDiv op = new OpBehaviorFloatDiv();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
long a = ff.getEncoding(3.75);
long b = ff.getEncoding(1.5);
long result = ff.opDiv(a, b);
Assert.assertEquals(2.5, ff.getHostFloat(result), 0);
b = ff.getEncoding(0);
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(-3.75);
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0);
b = ff.getEncoding(Double.NaN);
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatDiv op = new OpBehaviorFloatDiv();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigInteger a = ff.getEncoding(ff.getBigFloat(3.75d));
BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d));
BigInteger result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
b = ff.getBigZeroEncoding(false);
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-3.75d));
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
b = ff.getBigNaNEncoding(false);
result = op.evaluateBinary(8, 8, a, b);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
}
}

View file

@ -1,81 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.*;
public class OpBehaviorFloatEqualTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatEqualTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
Assert.assertEquals(0,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(Double.POSITIVE_INFINITY)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(Double.NEGATIVE_INFINITY)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
ff.getEncoding(Double.NEGATIVE_INFINITY)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(Double.NaN)));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigFloat a = ff.getBigFloat(1.234d);
BigFloat b = ff.getBigFloat(-1.234d);
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8,
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8,
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(true)));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
ff.getBigInfinityEncoding(true)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getBigNaNEncoding(false)));
}
}

View file

@ -1,90 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatFloat2FloatTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatFloat2FloatTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatFloat2Float op = new OpBehaviorFloatFloat2Float();
FloatFormat ff8 = FloatFormatFactory.getFloatFormat(8);
FloatFormat ff4 = FloatFormatFactory.getFloatFormat(4);
long a = ff4.getEncoding(1.75);
long result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(1.75, ff8.getHostFloat(result), 0);
a = ff4.getEncoding(-1.75);
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(-1.75, ff8.getHostFloat(result), 0);
a = ff4.getEncoding(Float.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff8.getHostFloat(result), 0);
a = ff4.getEncoding(Float.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff8.getHostFloat(result), 0);
a = ff4.getEncoding(Float.NaN);
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(Double.NaN, ff8.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatFloat2Float op = new OpBehaviorFloatFloat2Float();
FloatFormat ff8 = FloatFormatFactory.getFloatFormat(8);
FloatFormat ff4 = FloatFormatFactory.getFloatFormat(4);
BigInteger a = ff4.getEncoding(ff4.getBigFloat(1.75d));
BigInteger result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigFloat(1.75d), ff8.getHostFloat(result));
a = ff4.getEncoding(ff4.getBigFloat(-1.75d));
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigFloat(-1.75d), ff8.getHostFloat(result));
a = ff4.getEncoding(ff4.getBigInfinity(false));
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigInfinity(false), ff8.getHostFloat(result));
a = ff4.getEncoding(ff4.getBigInfinity(true));
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigInfinity(true), ff8.getHostFloat(result));
a = ff4.getEncoding(ff4.getBigNaN(false));
result = op.evaluateUnary(8, 4, a);
Assert.assertEquals(ff8.getBigNaN(false), ff8.getHostFloat(result));
}
}

View file

@ -1,96 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
public class OpBehaviorFloatFloorTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatFloorTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatFloor op = new OpBehaviorFloatFloor();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
long a = ff.getEncoding(2.5);
long result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(2.0, ff.getHostFloat(result), 0);
a = ff.getEncoding(-2.0);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-2.0, ff.getHostFloat(result), 0);
a = ff.getEncoding(-2.5);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(-3.0, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.POSITIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.POSITIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NEGATIVE_INFINITY);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NEGATIVE_INFINITY, ff.getHostFloat(result), 0);
a = ff.getEncoding(Double.NaN);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(Double.NaN, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatFloor op = new OpBehaviorFloatFloor();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
BigInteger result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.0d));
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
a = ff.getEncoding(ff.getBigFloat(-2.5d));
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigFloat(-3.0d), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
a = ff.getBigInfinityEncoding(true);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
a = ff.getBigNaNEncoding(false);
result = op.evaluateUnary(8, 8, a);
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
}
}

View file

@ -1,87 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import static org.junit.Assert.*;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.FloatFormat;
import ghidra.pcode.floatformat.FloatFormatFactory;
import ghidra.pcode.utils.Utils;
public class OpBehaviorFloatInt2FloatTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatInt2FloatTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatInt2Float op = new OpBehaviorFloatInt2Float();
FloatFormat ff = FloatFormatFactory.getFloatFormat(4);
long result = op.evaluateUnary(4, 4, 2);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(2.0d, ff.getHostFloat(result), 0);
result = op.evaluateUnary(4, 4, -2);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(-2.0d, ff.getHostFloat(result), 0);
result = op.evaluateUnary(4, 4, 0);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(0d, ff.getHostFloat(result), 0);
result = op.evaluateUnary(4, 4, 0x0ffffffffL);
Assert.assertEquals(0, result & 0xffffffff00000000L);// verify that only 4-bytes are used
Assert.assertEquals(-1.0d, ff.getHostFloat(result), 0);
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatInt2Float op = new OpBehaviorFloatInt2Float();
FloatFormat ff = FloatFormatFactory.getFloatFormat(4);
BigInteger limit = BigInteger.ONE.shiftLeft(32);
BigInteger result = op.evaluateUnary(4, 4, BigInteger.valueOf(2));
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result));
result = op.evaluateUnary(4, 4, BigInteger.valueOf(-2));
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
result = op.evaluateUnary(4, 4, BigInteger.ZERO);
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result));
BigInteger NEG_ONE = Utils.bytesToBigInteger(
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 4, false, false);
result = op.evaluateUnary(4, 4, NEG_ONE);
Assert.assertEquals(ff.getBigFloat(-1.0d), ff.getHostFloat(result));
}
}

View file

@ -1,108 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.*;
public class OpBehaviorFloatLessEqualTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatLessEqualTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
Assert.assertEquals(0,
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
ff.getEncoding(1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
ff.getEncoding(Double.POSITIVE_INFINITY)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
ff.getEncoding(Double.NEGATIVE_INFINITY)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(Double.POSITIVE_INFINITY)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
ff.getEncoding(Double.POSITIVE_INFINITY)));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigFloat a = ff.getBigFloat(1.234d);
BigFloat b = ff.getBigFloat(-1.234d);
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(false)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(true)));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8,
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
ff.getBigInfinityEncoding(false)));
}
}

View file

@ -1,105 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.pcode.opbehavior;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
import ghidra.pcode.floatformat.*;
public class OpBehaviorFloatLessTest extends AbstractOpBehaviorTest {
public OpBehaviorFloatLessTest() {
super();
}
@Test
public void testEvaluateBinaryLong() {
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
Assert.assertEquals(0,
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
Assert.assertEquals(0,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
Assert.assertEquals(0,
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
Assert.assertEquals(1,
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
ff.getEncoding(1.234)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
ff.getEncoding(Double.POSITIVE_INFINITY)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
ff.getEncoding(Double.NEGATIVE_INFINITY)));
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
ff.getEncoding(Double.POSITIVE_INFINITY)));
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
ff.getEncoding(Double.POSITIVE_INFINITY)));
}
@Test
public void testEvaluateBinaryBigInteger() {
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
BigFloat a = ff.getBigFloat(1.234d);
BigFloat b = ff.getBigFloat(-1.234d);
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(b)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true), ff.getEncoding(a)));
Assert.assertEquals(BigInteger.ONE,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(false)));
Assert.assertEquals(BigInteger.ZERO,
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(true)));
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8,
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
ff.getBigInfinityEncoding(false)));
}
}

Some files were not shown because too many files have changed in this diff Show more