mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-0: Fixing some more javadoc
This commit is contained in:
parent
c964163c80
commit
88a35769a2
16 changed files with 592 additions and 427 deletions
|
@ -79,11 +79,11 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Implementation of DomainObjectListener
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||
|
|
|
@ -114,11 +114,11 @@ public final class LanguageProviderPlugin extends Plugin implements ApplicationL
|
|||
tool.addAction(setLanguageAction);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
// //
|
||||
// methods overriding Plugin //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
|
|
@ -55,11 +55,11 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
|
|||
private static final String FILE_OFFSET_ANCHOR_NAME = "GoTo_File_Offset";
|
||||
private static final int DEFAULT_MAX_GOTO_ENTRIES = 10;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
// //
|
||||
// Instance fields //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
private Plugin plugin;
|
||||
private JPanel mainPanel;
|
||||
|
@ -79,11 +79,11 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
|
|||
|
||||
private JCheckBox includeDynamicBox;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
// //
|
||||
// Constructor //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
public GoToAddressLabelDialog(GoToService gotoService, Plugin plugin) {
|
||||
super(DIALOG_TITLE, true, true, true, true);
|
||||
|
@ -268,11 +268,11 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
|
|||
saveState.putBoolean("INCLUDE_DYNAMIC", includeDynamicBox.isSelected());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
// //
|
||||
// Overridden GhidraDialog methods //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public final void okCallback() {
|
||||
|
@ -325,7 +325,7 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
|
|||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
public void maxEntrysChanged() {
|
||||
truncateHistoryAsNeeded();
|
||||
|
@ -347,7 +347,7 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
|
|||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
private void addToHistory(String input) {
|
||||
history.remove(input);
|
||||
|
|
|
@ -22,7 +22,9 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/// Creates an acyclic dependency list of data types.
|
||||
/**
|
||||
* Creates an acyclic dependency list of data types.
|
||||
*/
|
||||
public class DataTypeDependencyOrderer {
|
||||
|
||||
public static class Entry {
|
||||
|
|
|
@ -232,7 +232,7 @@ public class BinaryField extends Field {
|
|||
return hashcode;
|
||||
}
|
||||
|
||||
/// Methods below should not use data field directly
|
||||
// Methods below should not use data field directly
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -18,30 +18,37 @@ package ghidra.app.emulator.memory;
|
|||
import ghidra.pcode.memstate.*;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
|
||||
/// A kind of MemoryBank which retrieves its data from an underlying LoadImage
|
||||
///
|
||||
/// Any bytes requested on the bank which lie in the LoadImage are retrieved from
|
||||
/// the LoadImage. Other addresses in the space are filled in with zero.
|
||||
/// This bank cannot be written to.
|
||||
/**
|
||||
* A kind of MemoryBank which retrieves its data from an underlying LoadImage
|
||||
* <p>
|
||||
* Any bytes requested on the bank which lie in the LoadImage are retrieved from
|
||||
* the LoadImage. Other addresses in the space are filled in with zero.
|
||||
* This bank cannot be written to.
|
||||
*/
|
||||
public class MemoryImage extends MemoryBank {
|
||||
|
||||
private MemoryLoadImage loader; // The underlying LoadImage
|
||||
|
||||
/// A MemoryImage needs everything a basic memory bank needs and is needs to know
|
||||
/// the underlying LoadImage object to forward read requests to.
|
||||
/// \param spc is the address space associated with the memory bank
|
||||
/// \param ws is the number of bytes in the preferred wordsize (must be power of 2)
|
||||
/// \param ps is the number of bytes in a page (must be power of 2)
|
||||
/// \param ld is the underlying LoadImage
|
||||
/**
|
||||
* A MemoryImage needs everything a basic memory bank needs and is needs to know
|
||||
* the underlying LoadImage object to forward read requests to.
|
||||
* @param spc is the address space associated with the memory bank
|
||||
* @param isBigEndian
|
||||
* @param ps is the number of bytes in a page (must be power of 2)
|
||||
* @param ld is the underlying LoadImage
|
||||
* @param faultHandler
|
||||
*/
|
||||
public MemoryImage(AddressSpace spc, boolean isBigEndian, int ps, MemoryLoadImage ld,
|
||||
MemoryFaultHandler faultHandler) {
|
||||
super(spc, isBigEndian, ps, faultHandler);
|
||||
loader = ld;
|
||||
}
|
||||
|
||||
/// Retrieve an aligned page from the bank. First an attempt is made to retrieve the
|
||||
/// page from the LoadImage, which may do its own zero filling. If the attempt fails, the
|
||||
/// page is entirely filled in with zeros.
|
||||
/**
|
||||
* Retrieve an aligned page from the bank. First an attempt is made to retrieve the
|
||||
* page from the LoadImage, which may do its own zero filling. If the attempt fails, the
|
||||
* page is entirely filled in with zeros.
|
||||
*/
|
||||
@Override
|
||||
public MemoryPage getPage(long addr) {
|
||||
MemoryPage page = new MemoryPage(getPageSize());
|
||||
|
|
|
@ -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.
|
||||
|
@ -19,45 +18,53 @@ 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.
|
||||
/**
|
||||
* A breakpoint object
|
||||
* <p>
|
||||
* 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
|
||||
* <ul>
|
||||
* <li>pcodeCallback()</li>
|
||||
* <li>addressCallback()</li>
|
||||
* </ul>
|
||||
*
|
||||
* 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
|
||||
protected Emulate emulate; // The emulator currently associated with this breakpoint
|
||||
|
||||
public BreakCallBack() { ///< Generic breakpoint constructor
|
||||
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
|
||||
/**
|
||||
* 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 true if these actions are intended to replace the action of the entire machine
|
||||
* instruction at this address. Or it returns false if the machine instruction should still be
|
||||
* executed normally.
|
||||
* @param addr is the address where the break has occurred
|
||||
* @return true if the machine instruction should not be executed
|
||||
*/
|
||||
public boolean addressCallback(Address addr) { // Call back method for address 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;
|
||||
}
|
||||
public void setEmulate(Emulate emu) { // Associate a particular emulator with this breakpoint
|
||||
emulate = emu;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,43 +18,51 @@ 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
|
||||
/**
|
||||
* A collection of breakpoints for the emulator
|
||||
* <p>
|
||||
* 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
|
||||
* <ul>
|
||||
* <li>doPcodeOpBreak()</li>
|
||||
* <li>doAddressBreak()</li>
|
||||
* </ul>
|
||||
*
|
||||
* 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);
|
||||
/**
|
||||
* Associate a particular emulator with breakpoints in this table
|
||||
* <p>
|
||||
* 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);
|
||||
/**
|
||||
* Invoke any breakpoints associated with this particular pcodeop
|
||||
* <p>
|
||||
* 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 replace the action of the pcode op, then true is returned.
|
||||
* @param curop is the instance of a pcode op to test for breakpoints
|
||||
* @return 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);
|
||||
/**
|
||||
* Invoke any breakpoints associated with this machine address
|
||||
* <p>
|
||||
* 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 replace
|
||||
* the action of the machine instruction, then true is returned.
|
||||
* @param addr is address to test for breakpoints
|
||||
* @return true is the machine instruction has been replaced by a breakpoint
|
||||
*/
|
||||
public abstract boolean doAddressBreak(Address addr);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,18 @@ 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
|
||||
/**
|
||||
* A basic instantiation of a breakpoint table
|
||||
* <p>
|
||||
* This object allows breakpoints to registered in the table via either
|
||||
* <ul>
|
||||
* <li>registerPcodeCallback()</li>
|
||||
* <li>registerAddressCallback()</li>
|
||||
* </ul>
|
||||
*
|
||||
* 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 = "*";
|
||||
|
@ -42,18 +46,22 @@ public class BreakTableCallBack implements BreakTable {
|
|||
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
|
||||
/**
|
||||
* The break table needs a translator object so user-defined pcode ops can be registered against
|
||||
* by name.
|
||||
* @param language the language
|
||||
*/
|
||||
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
|
||||
/**
|
||||
* 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 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)) {
|
||||
|
@ -77,9 +85,11 @@ public class BreakTableCallBack implements BreakTable {
|
|||
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
|
||||
/**
|
||||
* 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;
|
||||
|
@ -95,11 +105,13 @@ public class BreakTableCallBack implements BreakTable {
|
|||
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
|
||||
/**
|
||||
* 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 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);
|
||||
|
@ -109,8 +121,10 @@ public class BreakTableCallBack implements BreakTable {
|
|||
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
|
||||
/**
|
||||
* 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
|
||||
|
@ -129,10 +143,12 @@ public class BreakTableCallBack implements BreakTable {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/**
|
||||
* 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 true if the breakpoint exists and returns true, otherwise return false
|
||||
*/
|
||||
@Override
|
||||
public boolean doPcodeOpBreak(PcodeOpRaw curop) {
|
||||
long val = curop.getInput(0).getOffset();
|
||||
|
@ -146,10 +162,12 @@ public class BreakTableCallBack implements BreakTable {
|
|||
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
|
||||
/**
|
||||
* 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 true if the breakpoint exists and returns true, otherwise return false
|
||||
*/
|
||||
@Override
|
||||
public boolean doAddressBreak(Address addr) {
|
||||
IteratorSTL<Pair<Address, BreakCallBack>> iter = addressCallback.find(addr);
|
||||
|
|
|
@ -33,27 +33,28 @@ 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.
|
||||
|
||||
/**
|
||||
* A SLEIGH based implementation of the Emulate interface
|
||||
* <p>
|
||||
* 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 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 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;
|
||||
|
@ -62,7 +63,7 @@ public class Emulate {
|
|||
private InstructionBlock lastPseudoInstructionBlock;
|
||||
private Disassembler pseudoDisassembler;
|
||||
private Instruction pseudoInstruction;
|
||||
private PcodeOp[] pcode; ///< The cache of current pcode ops
|
||||
private PcodeOp[] pcode; // The cache of current pcode ops
|
||||
|
||||
private RegisterValue nextContextRegisterValue = null;
|
||||
|
||||
|
@ -70,9 +71,13 @@ public class Emulate {
|
|||
|
||||
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
|
||||
/**
|
||||
* Creates a new {@link Emulate} object
|
||||
*
|
||||
* @param lang is the SLEIGH language
|
||||
* @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;
|
||||
|
@ -134,29 +139,35 @@ public class Emulate {
|
|||
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
|
||||
/**
|
||||
* Since the emulator can single step through individual pcode operations, the machine state
|
||||
* may be halted in the 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 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
|
||||
* {@return the current emulator execution state}
|
||||
*/
|
||||
public EmulateExecutionState getExecutionState() {
|
||||
return executionState;
|
||||
}
|
||||
|
||||
/// \return the currently executing machine address
|
||||
/**
|
||||
* {@return the currently executing machine address}
|
||||
*/
|
||||
public Address getExecuteAddress() {
|
||||
return current_address;
|
||||
}
|
||||
|
||||
/// \return the last address
|
||||
/**
|
||||
* {@return the last address}
|
||||
*/
|
||||
public Address getLastExecuteAddress() {
|
||||
return last_execute_address;
|
||||
}
|
||||
|
@ -291,8 +302,10 @@ public class Emulate {
|
|||
pseudoInstruction = null;
|
||||
}
|
||||
|
||||
/// Update the iterator into the current pcode cache, and if necessary, generate
|
||||
/// the pcode for the fallthru instruction and reset the iterator.
|
||||
/**
|
||||
* 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) {
|
||||
|
@ -318,8 +331,11 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// Since the full instruction is cached, we can do relative branches properly
|
||||
/// \param op is the particular branch op being executed
|
||||
/**
|
||||
* 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()) {
|
||||
|
@ -338,10 +354,14 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/**
|
||||
* 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
|
||||
* @throws UnimplementedCallOtherException
|
||||
*/
|
||||
public void executeCallother(PcodeOpRaw op) throws UnimplementedCallOtherException {
|
||||
if ((instructionStateModifier == null || !instructionStateModifier.executeCallOther(op)) &&
|
||||
!breaktable.doPcodeOpBreak(op)) {
|
||||
|
@ -352,9 +372,12 @@ public class Emulate {
|
|||
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
|
||||
/**
|
||||
* 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;
|
||||
|
@ -370,11 +393,18 @@ public class Emulate {
|
|||
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.
|
||||
/**
|
||||
* 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.
|
||||
* @param stopAtBreakpoint
|
||||
* @param monitor
|
||||
* @throws CancelledException
|
||||
* @throws LowlevelError
|
||||
* @throws InstructionDecodeException
|
||||
*/
|
||||
public void executeInstruction(boolean stopAtBreakpoint, TaskMonitor monitor)
|
||||
throws CancelledException, LowlevelError, InstructionDecodeException {
|
||||
if (monitor == null) {
|
||||
|
@ -428,13 +458,17 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// \return the memory state object which this emulator uses
|
||||
/**
|
||||
* {@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.
|
||||
/**
|
||||
* 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) {
|
||||
|
@ -541,8 +575,10 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// This routine performs a standard pcode \b load operation on the memory state
|
||||
/// \param op is the particular \e load op being executed
|
||||
/**
|
||||
* This routine performs a standard pcode load operation on the memory state
|
||||
* @param op is the particular load op being executed
|
||||
*/
|
||||
public void executeLoad(PcodeOpRaw op) {
|
||||
|
||||
AddressSpace space =
|
||||
|
@ -564,8 +600,10 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// This routine performs a standard pcode \b store operation on the memory state
|
||||
/// \param op is the particular \e store op being executed
|
||||
/**
|
||||
* This routine performs a standard pcode store operation on the memory state
|
||||
* @param op is the particular store op being executed
|
||||
*/
|
||||
public void executeStore(PcodeOpRaw op) {
|
||||
|
||||
AddressSpace space =
|
||||
|
@ -586,36 +624,46 @@ public class Emulate {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/**
|
||||
* This routine performs a standard pcode branch indirect operation on the memory state
|
||||
* @param op is the particular 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
|
||||
/**
|
||||
* This routine performs a standard pcode call operation on the memory state
|
||||
* @param op is the particular 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
|
||||
/**
|
||||
* This routine performs a standard pcode call indirect operation on the memory state
|
||||
* @param op is the particular 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
|
||||
/**
|
||||
* This kind of pcode op should not come up in ordinary emulation, so this routine
|
||||
* throws an exception.
|
||||
* @param op is the particular 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
|
||||
/**
|
||||
* This kind of pcode op should not come up in ordinary emulation, so this routine
|
||||
* throws an exception.
|
||||
* @param op is the particular indirect op being executed
|
||||
*/
|
||||
public void executeIndirect(PcodeOpRaw op) {
|
||||
throw new LowlevelError("INDIRECT appearing in unheritaged code?");
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ 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 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
|
||||
|
||||
|
@ -57,7 +57,7 @@ public abstract class MemoryBank {
|
|||
}
|
||||
|
||||
/**
|
||||
* A MemoryBank is instantiated with a \e natural page size. Requests for large chunks of data
|
||||
* A MemoryBank is instantiated with a 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.
|
||||
*/
|
||||
|
@ -80,55 +80,66 @@ public abstract class MemoryBank {
|
|||
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);
|
||||
// /**
|
||||
// * This routine only retrieves data from a single page in the memory bank. Bytes need not
|
||||
// * be retrieved from the exact start of a page, but all bytes must come from 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 aligned offset of the desired page
|
||||
// * @param res is a pointer to where fetched data should be written
|
||||
// * @param skip is the offset into the 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
|
||||
/**
|
||||
* This routine writes data only to a single 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 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 into the 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
|
||||
/**
|
||||
* This routine marks a range within a single 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 aligned offset of the desired page
|
||||
* @param initialized true if range should be marked as initialized, false if uninitialized
|
||||
* @param skip is the offset into the 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
|
||||
/**
|
||||
* 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;
|
||||
|
@ -156,12 +167,15 @@ public abstract class MemoryBank {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/**
|
||||
* 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;
|
||||
|
@ -188,15 +202,18 @@ public abstract class MemoryBank {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/**
|
||||
* 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 addrOffset 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);
|
||||
|
@ -261,12 +278,16 @@ public abstract class MemoryBank {
|
|||
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
|
||||
/**
|
||||
* 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 offset a fixed offset from {@code ptr} used during decode
|
||||
* @param size is the number of bytes
|
||||
* @param bigendian is 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;
|
||||
|
||||
|
@ -285,12 +306,16 @@ public abstract class MemoryBank {
|
|||
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
|
||||
/**
|
||||
* 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 offset a fixed offset from {@code ptr} to where to write the bytes
|
||||
* @param val is the value to be encoded
|
||||
* @param size is the number of bytes to encode
|
||||
* @param bigendian is true if a big endian encoding is desired
|
||||
*/
|
||||
public static void deconstructValue(byte[] ptr, int offset, long val, int size,
|
||||
boolean bigendian) {
|
||||
if (bigendian) {
|
||||
|
|
|
@ -19,20 +19,25 @@ 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.
|
||||
/**
|
||||
* Memory bank that overlays some other memory bank, using a "copy on write" behavior.
|
||||
* <p>
|
||||
* 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 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
|
||||
/**
|
||||
* 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
|
||||
* @param faultHandler
|
||||
*/
|
||||
public MemoryPageOverlay(AddressSpace spc, MemoryBank ul, MemoryFaultHandler faultHandler) {
|
||||
super(spc,ul.isBigEndian(),ul.getPageSize(),faultHandler);
|
||||
underlie = ul;
|
||||
|
|
|
@ -148,9 +148,10 @@ public abstract class VertexShape {
|
|||
return Objects.equals(name, other.name) && size == other.size;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Vertex Shape Classes
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Vertex Shape Classes
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
static class RectangleVertexShape extends VertexShape {
|
||||
private RectangleVertexShape(int size) {
|
||||
super("Rectangle", size);
|
||||
|
|
|
@ -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.
|
||||
|
@ -20,17 +19,21 @@ import ghidra.pcodeCPort.space.AddrSpace;
|
|||
|
||||
public interface BasicSpaceProvider {
|
||||
|
||||
/// Most processors have a main address bus, on which the bulk
|
||||
/// of the processor's RAM is mapped. Everything referenced
|
||||
/// with this address bus should be modeled in pcode with a
|
||||
/// single address space, referred to as the \e default space.
|
||||
/// \return a pointer to the \e default space
|
||||
/**
|
||||
* Most processors have a main address bus, on which the bulk
|
||||
* of the processor's RAM is mapped. Everything referenced
|
||||
* with this address bus should be modeled in pcode with a
|
||||
* single address space, referred to as the default space.
|
||||
* @return a pointer to the default space
|
||||
*/
|
||||
public AddrSpace getDefaultSpace();
|
||||
|
||||
/// Pcode represents constant values within an operation as
|
||||
/// offsets within a special \e constant address space.
|
||||
/// (See ConstantSpace)
|
||||
/// \return a pointer to the \b constant space
|
||||
/**
|
||||
* Pcode represents constant values within an operation as
|
||||
* offsets within a special constant address space.
|
||||
* (See ConstantSpace)
|
||||
* @return a pointer to the constant space
|
||||
*/
|
||||
public AddrSpace getConstantSpace();
|
||||
|
||||
}
|
||||
|
|
|
@ -48,165 +48,200 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
protected int alignment; // Byte modulo on which instructions are aligned
|
||||
protected int target_endian; // =0 target is little endian =1 target is big
|
||||
|
||||
/// The \e unique address space, for allocating temporary registers,
|
||||
/// is used for both registers needed by the pcode translation
|
||||
/// engine and, later, by the simplification engine. This routine
|
||||
/// sets the boundary of the portion of the space allocated
|
||||
/// for the pcode engine, and sets the base offset where registers
|
||||
/// created by the simplification process can start being allocated.
|
||||
/// \param val is the boundary offset
|
||||
/**
|
||||
* The unique address space, for allocating temporary registers,
|
||||
* is used for both registers needed by the pcode translation
|
||||
* engine and, later, by the simplification engine. This routine
|
||||
* sets the boundary of the portion of the space allocated
|
||||
* for the pcode engine, and sets the base offset where registers
|
||||
* created by the simplification process can start being allocated.
|
||||
* @param val is the boundary offset
|
||||
*/
|
||||
protected void setUniqueBase(long val) {
|
||||
if (val > unique_base) {
|
||||
unique_base = val;
|
||||
}
|
||||
}
|
||||
|
||||
/// Processors can usually be described as using a big endian
|
||||
/// encoding or a little endian encoding. This routine returns
|
||||
/// \b true if the processor globally uses big endian encoding.
|
||||
/// \return \b true if big endian
|
||||
/**
|
||||
* Processors can usually be described as using a big endian
|
||||
* encoding or a little endian encoding. This routine returns
|
||||
* true if the processor globally uses big endian encoding.
|
||||
* @return true if big endian
|
||||
*/
|
||||
public boolean isBigEndian() {
|
||||
return target_endian == 1;
|
||||
}
|
||||
|
||||
/// \deprecated This routine is intended to return a \e global
|
||||
/// address size for the processor. Use getDefaultSize instead.
|
||||
/// \return the size of addresses in bytes
|
||||
/**
|
||||
* This routine is intended to return a global address size for the processor.
|
||||
* @return the size of addresses in bytes
|
||||
* @deprecated use {@link #getDefaultSize()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int getAddrSize() {
|
||||
return defaultspace.getAddrSize();
|
||||
}
|
||||
|
||||
/// Return the size of addresses for the processor's official
|
||||
/// default space. This space is usually the main RAM databus.
|
||||
/// \return the size of an address in bytes
|
||||
/**
|
||||
* Return the size of addresses for the processor's official
|
||||
* default space. This space is usually the main RAM databus.
|
||||
* @return the size of an address in bytes
|
||||
*/
|
||||
public int getDefaultSize() {
|
||||
return defaultspace.getAddrSize();
|
||||
}
|
||||
|
||||
/// If machine instructions need to have a specific alignment
|
||||
/// for this processor, this routine returns it. I.e. a return
|
||||
/// value of 4, means that the address of all instructions
|
||||
/// must be a multiple of 4. If there is no
|
||||
/// specific alignment requirement, this routine returns 1.
|
||||
/// \return the instruction alignment
|
||||
/**
|
||||
* If machine instructions need to have a specific alignment
|
||||
* for this processor, this routine returns it. I.e. a return
|
||||
* value of 4, means that the address of all instructions
|
||||
* must be a multiple of 4. If there is no
|
||||
* specific alignment requirement, this routine returns 1.
|
||||
* @return the instruction alignment
|
||||
*/
|
||||
int getAlignment() {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
/// This routine gets the base offset, within the \e unique
|
||||
/// temporary register space, where new registers can be
|
||||
/// allocated for the simplification process. Locations before
|
||||
/// this offset are reserved registers needed by the pcode
|
||||
/// translation engine.
|
||||
/// \return the first allocatable offset
|
||||
/**
|
||||
* This routine gets the base offset, within the unique
|
||||
* temporary register space, where new registers can be
|
||||
* allocated for the simplification process. Locations before
|
||||
* this offset are reserved registers needed by the pcode
|
||||
* translation engine.
|
||||
* @return the first allocatable offset
|
||||
*/
|
||||
public long getUniqueBase() {
|
||||
return unique_base;
|
||||
}
|
||||
|
||||
/// There is a special address space reserved for encoding pointers
|
||||
/// to pcode operations as addresses. This allows a direct pointer
|
||||
/// to be \e hidden within an operation, when manipulating pcode
|
||||
/// internally. (See IopSpace)
|
||||
/// \return a pointer to the address space
|
||||
/**
|
||||
* There is a special address space reserved for encoding pointers
|
||||
* to pcode operations as addresses. This allows a direct pointer
|
||||
* to be hidden within an operation, when manipulating pcode
|
||||
* internally. (See IopSpace)
|
||||
* @return a pointer to the address space
|
||||
*/
|
||||
public AddrSpace getIopSpace() {
|
||||
return iopspace;
|
||||
}
|
||||
|
||||
/// There is a special address space reserved for encoding pointers
|
||||
/// to the FuncCallSpecs object as addresses. This allows direct
|
||||
/// pointers to be \e hidden within an operation, when manipulating
|
||||
/// pcode internally. (See FspecSpace)
|
||||
/// \return a pointer to the address space
|
||||
/**
|
||||
* There is a special address space reserved for encoding pointers
|
||||
* to the FuncCallSpecs object as addresses. This allows direct
|
||||
* pointers to be hidden within an operation, when manipulating
|
||||
* pcode internally. (See FspecSpace)
|
||||
* @return a pointer to the address space
|
||||
*/
|
||||
public AddrSpace getFspecSpace() {
|
||||
return fspecspace;
|
||||
}
|
||||
|
||||
/// Most processors have registers and instructions that are
|
||||
/// reserved for implementing a stack. In the pcode translation,
|
||||
/// these are translated into locations and operations on a
|
||||
/// dedicated \b stack address space. (See SpacebaseSpace)
|
||||
/// \return a pointer to the \b stack space
|
||||
/**
|
||||
* Most processors have registers and instructions that are
|
||||
* reserved for implementing a stack. In the pcode translation,
|
||||
* these are translated into locations and operations on a
|
||||
* dedicated stack address space. (See SpacebaseSpace)
|
||||
* @return a pointer to the stack space
|
||||
*/
|
||||
public AddrSpace getStackSpace() {
|
||||
return stackspace;
|
||||
}
|
||||
|
||||
/// Both the pcode translation process and the simplification
|
||||
/// process need access to a pool of temporary registers that
|
||||
/// can be used for moving data around without affecting the
|
||||
/// address spaces used to formally model the processor's RAM
|
||||
/// and registers. These temporary locations are all allocated
|
||||
/// from a dedicated address space, referred to as the \b unique
|
||||
/// space. (See UniqueSpace)
|
||||
/// \return a pointer to the \b unique space
|
||||
/**
|
||||
* Both the pcode translation process and the simplification
|
||||
* process need access to a pool of temporary registers that
|
||||
* can be used for moving data around without affecting the
|
||||
* address spaces used to formally model the processor's RAM
|
||||
* and registers. These temporary locations are all allocated
|
||||
* from a dedicated address space, referred to as the unique
|
||||
* space. (See UniqueSpace)
|
||||
* @return a pointer to the unique space
|
||||
*/
|
||||
public AddrSpace getUniqueSpace() {
|
||||
return uniqspace;
|
||||
}
|
||||
|
||||
/// Most processors have a main address bus, on which the bulk
|
||||
/// of the processor's RAM is mapped. Everything referenced
|
||||
/// with this address bus should be modeled in pcode with a
|
||||
/// single address space, referred to as the \e default space.
|
||||
/// \return a pointer to the \e default space
|
||||
/**
|
||||
* Most processors have a main address bus, on which the bulk
|
||||
* of the processor's RAM is mapped. Everything referenced
|
||||
* with this address bus should be modeled in pcode with a
|
||||
* single address space, referred to as the default space.
|
||||
* @return a pointer to the default space
|
||||
*/
|
||||
@Override
|
||||
public AddrSpace getDefaultSpace() {
|
||||
return defaultspace;
|
||||
}
|
||||
|
||||
/// Pcode represents constant values within an operation as
|
||||
/// offsets within a special \e constant address space.
|
||||
/// (See ConstantSpace)
|
||||
/// \return a pointer to the \b constant space
|
||||
/**
|
||||
* Pcode represents constant values within an operation as
|
||||
* offsets within a special constant address space.
|
||||
* (See ConstantSpace)
|
||||
* @return a pointer to the constant space
|
||||
*/
|
||||
@Override
|
||||
public AddrSpace getConstantSpace() {
|
||||
return constantspace;
|
||||
}
|
||||
|
||||
// This routine encodes a specific value as a \e constant
|
||||
/// address. I.e. the address space of the resulting Address
|
||||
/// will be the \b constant space, and the offset will be the
|
||||
/// value.
|
||||
/// \param val is the constant value to encode
|
||||
/// \return the \e constant address
|
||||
/**
|
||||
* This routine encodes a specific value as a constant
|
||||
* address. I.e. the address space of the resulting Address
|
||||
* will be the constant space, and the offset will be the
|
||||
* value.
|
||||
* @param val is the constant value to encode
|
||||
* @return the constant address
|
||||
*/
|
||||
public Address getConstant(long val) {
|
||||
return new Address(constantspace, val);
|
||||
}
|
||||
|
||||
// This routine is used to encode a pointer to an address space
|
||||
// as a \e constant Address, for use in \b LOAD and \b STORE
|
||||
// operations. This is used internally and is slightly more
|
||||
// efficient than storing the formal index of the space
|
||||
// param spc is the space pointer to be encoded
|
||||
// \return the encoded Address
|
||||
/**
|
||||
* This routine is used to encode a pointer to an address space
|
||||
* as a constant Address, for use in LOAD and STORE
|
||||
* operations. This is used internally and is slightly more
|
||||
* efficient than storing the formal index of the space
|
||||
* @param spc is the space pointer to be encoded
|
||||
* @return the encoded Address
|
||||
*/
|
||||
public Address createConstFromSpace(AddrSpace spc) {
|
||||
long id = AddrSpaceToIdSymmetryMap.getID(spc);
|
||||
return new Address(constantspace, id);
|
||||
}
|
||||
|
||||
// This returns the total number of address spaces used by the
|
||||
// processor, including all special spaces, like the \b constant
|
||||
// space and the \b iop space.
|
||||
// \return the number of spaces
|
||||
/**
|
||||
* This returns the total number of address spaces used by the
|
||||
* processor, including all special spaces, like the constant
|
||||
* space and the iop space.
|
||||
* @return the number of spaces
|
||||
*/
|
||||
public int numSpaces() {
|
||||
return baselist.size();
|
||||
}
|
||||
|
||||
// This retrieves a specific address space via its formal index.
|
||||
// All spaces have an index, and in conjunction with the numSpaces
|
||||
// method, this method can be used to iterate over all spaces.
|
||||
// \param i is the index of the address space
|
||||
// \return a pointer to the desired space
|
||||
/**
|
||||
* This retrieves a specific address space via its formal index.
|
||||
* All spaces have an index, and in conjunction with the numSpaces
|
||||
* method, this method can be used to iterate over all spaces.
|
||||
* @param i is the index of the address space
|
||||
* @return a pointer to the desired space
|
||||
*/
|
||||
public AddrSpace getSpace(int i) {
|
||||
return baselist.get(i);
|
||||
}
|
||||
|
||||
// The Translate object keep tracks of address ranges for which
|
||||
// it is effectively impossible to have a pointer into. This is
|
||||
// used for pointer aliasing calculations. This routine returns
|
||||
// \b true if it is \e possible to have pointers into the indicated
|
||||
// range.
|
||||
// \param loc is the starting address of the range
|
||||
// \param size is the size of the range in bytes
|
||||
// \return \b true if pointers are possible
|
||||
/**
|
||||
* The Translate object keep tracks of address ranges for which
|
||||
* it is effectively impossible to have a pointer into. This is
|
||||
* used for pointer aliasing calculations. This routine returns
|
||||
* true if it is possible to have pointers into the indicated
|
||||
* range.
|
||||
* @param loc is the starting address of the range
|
||||
* @param size is the size of the range in bytes
|
||||
* @return true if pointers are possible
|
||||
*/
|
||||
public boolean highPtrPossible(Address loc, int size) {
|
||||
return !nohighptr.inRange(loc, size);
|
||||
}
|
||||
|
@ -251,17 +286,19 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Associate a particular register or memory location with an address space
|
||||
// The canonical example is the \b stack \b pointer and the stack space.
|
||||
// The \b basespace is the so-called stack space, which is really a
|
||||
// virtual space typically contained by ram space. The \b spacebase
|
||||
// register effectively hides the true location of its basespace with
|
||||
// its containing space and facilitates addressing in the virtual space
|
||||
// by providing a base offset into the containing space.
|
||||
// \param basespace is the virtual address space
|
||||
// \param spc is the address space of the register
|
||||
// \param offset is the offset of the register
|
||||
// \param size is the size of the register
|
||||
/**
|
||||
* Associate a particular register or memory location with an address space
|
||||
* The canonical example is the stack pointer and the stack space.
|
||||
* The basespace is the so-called stack space, which is really a
|
||||
* virtual space typically contained by ram space. The spacebase
|
||||
* register effectively hides the true location of its basespace with
|
||||
* its containing space and facilitates addressing in the virtual space
|
||||
* by providing a base offset into the containing space.
|
||||
* @param basespace is the virtual address space
|
||||
* @param spc is the address space of the register
|
||||
* @param offset is the offset of the register
|
||||
* @param size is the size of the register
|
||||
*/
|
||||
public void addSpacebase(AddrSpace basespace, AddrSpace spc, long offset, int size) {
|
||||
int index = basespace.getIndex();
|
||||
while (index >= spacebaselist.size()) {
|
||||
|
@ -275,10 +312,12 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
datalist.back().size = size;
|
||||
}
|
||||
|
||||
// If \b basespace is a virtual space, it has one (or more) registers or memory locations
|
||||
// associated with it that serve as base offsets, anchoring the virtual space in a physical space
|
||||
// \param basespace is the virtual space to check
|
||||
// \return the number of spacebase registers
|
||||
/**
|
||||
* If basespace is a virtual space, it has one (or more) registers or memory locations
|
||||
* associated with it that serve as base offsets, anchoring the virtual space in a physical space
|
||||
* @param basespace is the virtual space to check
|
||||
* @return the number of spacebase registers
|
||||
*/
|
||||
public int numSpacebase(AddrSpace basespace) {
|
||||
int index = basespace.getIndex();
|
||||
if (index >= spacebaselist.size()) {
|
||||
|
@ -287,12 +326,14 @@ public abstract class Translate implements BasicSpaceProvider {
|
|||
return spacebaselist.get(index).size();
|
||||
}
|
||||
|
||||
// Retrieve a particular spacebase register associated with the virtual address space
|
||||
// \b basespace. This register serves as a base offset to anchor \b basespace within
|
||||
// its containing space.
|
||||
// \param basespace is the virtual space to find a spacebase register for
|
||||
// \param i is the index of the particular spacebase register
|
||||
// \return a reference to the spacebase register
|
||||
/**
|
||||
* Retrieve a particular spacebase register associated with the virtual address space
|
||||
* basespace. This register serves as a base offset to anchor basespace within
|
||||
* its containing space.
|
||||
* @param basespace is the virtual space to find a spacebase register for
|
||||
* @param i is the index of the particular spacebase register
|
||||
* @return a reference to the spacebase register
|
||||
*/
|
||||
public VarnodeData getSpacebase(AddrSpace basespace, int i) {
|
||||
int index = basespace.getIndex();
|
||||
if (index < spacebaselist.size()) {
|
||||
|
|
|
@ -610,9 +610,9 @@ public class FunctionManagerDB implements FunctionManager {
|
|||
return getFunctionContaining(addr) != null;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// ManagerDB methods
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue