mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GT-3227-dragonmacher-equate-manager-transactions'
This commit is contained in:
commit
792ad17cdb
6 changed files with 306 additions and 576 deletions
|
@ -15,13 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.equate;
|
package ghidra.app.plugin.core.equate;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
|
import ghidra.program.database.symbol.EquateManager;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.data.Enum;
|
import ghidra.program.model.data.Enum;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.*;
|
||||||
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
import ghidra.program.model.symbol.Equate;
|
||||||
import ghidra.program.model.symbol.EquateTable;
|
import ghidra.program.model.symbol.EquateTable;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class CreateEnumEquateCommand extends BackgroundCommand {
|
public class CreateEnumEquateCommand extends BackgroundCommand {
|
||||||
|
@ -30,6 +37,7 @@ public class CreateEnumEquateCommand extends BackgroundCommand {
|
||||||
private Enum enoom;
|
private Enum enoom;
|
||||||
private Program program;
|
private Program program;
|
||||||
private boolean shouldDoOnSubOps;
|
private boolean shouldDoOnSubOps;
|
||||||
|
private EquateTable equateTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -37,33 +45,123 @@ public class CreateEnumEquateCommand extends BackgroundCommand {
|
||||||
* @param program The program to use
|
* @param program The program to use
|
||||||
* @param addresses The addresses to apply an enum to
|
* @param addresses The addresses to apply an enum to
|
||||||
* @param enoom The enum to apply equates with
|
* @param enoom The enum to apply equates with
|
||||||
* @param shouldIncludeTypes True if the equate name should include the enum name.
|
* @param shouldDoOnSubOps true if the enum should also be applied to the sub-operands.
|
||||||
* @param shouldDoOnSubOps True if the enum should also be applied to the sub-operands.
|
|
||||||
*/
|
*/
|
||||||
public CreateEnumEquateCommand(Program program, AddressSetView addresses, Enum enoom,
|
public CreateEnumEquateCommand(Program program, AddressSetView addresses, Enum enoom,
|
||||||
boolean shouldDoOnSubOps) {
|
boolean shouldDoOnSubOps) {
|
||||||
this.program = program;
|
this.program = Objects.requireNonNull(program);
|
||||||
this.addresses = addresses;
|
this.addresses = Objects.requireNonNull(addresses);
|
||||||
this.enoom = enoom;
|
this.enoom = Objects.requireNonNull(enoom);
|
||||||
this.shouldDoOnSubOps = shouldDoOnSubOps;
|
this.shouldDoOnSubOps = shouldDoOnSubOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
|
||||||
|
|
||||||
EquateTable et = program.getEquateTable();
|
|
||||||
try {
|
|
||||||
et.applyEnum(addresses, enoom, monitor, shouldDoOnSubOps);
|
|
||||||
}
|
|
||||||
catch (CancelledException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Create Enum Equate Command";
|
return "Create Enum Equate Command";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
|
|
||||||
|
equateTable = program.getEquateTable();
|
||||||
|
try {
|
||||||
|
applyEnum(monitor);
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyEnum(TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
InstructionIterator it = listing.getInstructions(addresses, true);
|
||||||
|
monitor.initialize(addresses.getNumAddresses());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
|
||||||
|
monitor.checkCanceled();
|
||||||
|
|
||||||
|
Instruction instruction = it.next();
|
||||||
|
processsEquates(instruction);
|
||||||
|
monitor.incrementProgress(instruction.getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processsEquates(Instruction instruction) {
|
||||||
|
for (int opIndex = 0; opIndex < instruction.getNumOperands(); opIndex++) {
|
||||||
|
|
||||||
|
if (!shouldDoOnSubOps) {
|
||||||
|
// Only apply equates to scalars that are not contained in sub operands.
|
||||||
|
Scalar scalar = instruction.getScalar(opIndex);
|
||||||
|
maybeCreateEquateOnScalar(instruction, opIndex, scalar);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Apply equates to scalars in the sub operands as well.
|
||||||
|
List<?> subOperands = instruction.getDefaultOperandRepresentationList(opIndex);
|
||||||
|
for (Object subOp : subOperands) {
|
||||||
|
maybeCreateEquateOnScalar(instruction, opIndex, subOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeCreateEquateOnScalar(Instruction instruction, int opIndex,
|
||||||
|
Object operandRepresentation) {
|
||||||
|
|
||||||
|
if (!(operandRepresentation instanceof Scalar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scalar scalar = (Scalar) operandRepresentation;
|
||||||
|
|
||||||
|
int enoomLength = enoom.getLength();
|
||||||
|
boolean anyValuesMatch = Arrays.stream(enoom.getValues()).anyMatch(enumValue -> {
|
||||||
|
return scalar.equals(new Scalar(enoomLength * 8, enumValue, scalar.isSigned()));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!anyValuesMatch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program.getDataTypeManager().findDataTypeForID(enoom.getUniversalID()) == null) {
|
||||||
|
enoom = (Enum) program.getDataTypeManager().addDataType(enoom, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Address addr = instruction.getAddress();
|
||||||
|
removeUnusedEquates(opIndex, scalar, addr);
|
||||||
|
|
||||||
|
long value = scalar.getValue();
|
||||||
|
String equateName = EquateManager.formatNameForEquate(enoom.getUniversalID(), value);
|
||||||
|
Equate equate = getOrCreateEquate(equateName, value);
|
||||||
|
equate.addReference(addr, opIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeUnusedEquates(int opIndex, Scalar scalar, Address addr) {
|
||||||
|
Equate existingEquate = equateTable.getEquate(addr, opIndex, scalar.getValue());
|
||||||
|
if (existingEquate != null) {
|
||||||
|
if (existingEquate.getReferenceCount() <= 1) {
|
||||||
|
equateTable.removeEquate(existingEquate.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Equate getOrCreateEquate(String name, long value) {
|
||||||
|
Equate equate = equateTable.getEquate(name);
|
||||||
|
if (equate != null) {
|
||||||
|
return equate;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
equate = equateTable.createEquate(name, value);
|
||||||
|
}
|
||||||
|
catch (DuplicateNameException | InvalidInputException e) {
|
||||||
|
// These should not happen:
|
||||||
|
// Duplicate will not happen since we checked for the existence first; Invalid
|
||||||
|
// can't happen since we built the name ourselves (we are assuming)
|
||||||
|
Msg.error(this, "Unexpected error creating equate", e); // just in case
|
||||||
|
}
|
||||||
|
return equate;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.util.bean.SetEquateDialog;
|
import ghidra.app.util.bean.SetEquateDialog;
|
||||||
import ghidra.app.util.bean.SetEquateDialog.SelectionType;
|
import ghidra.app.util.bean.SetEquateDialog.SelectionType;
|
||||||
import ghidra.app.util.datatype.ApplyEnumDialog;
|
import ghidra.app.util.datatype.ApplyEnumDialog;
|
||||||
import ghidra.app.util.datatype.DataTypeSelectionDialog;
|
|
||||||
import ghidra.framework.cmd.BackgroundCommand;
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
import ghidra.framework.cmd.CompoundBackgroundCommand;
|
import ghidra.framework.cmd.CompoundBackgroundCommand;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
|
@ -74,23 +73,14 @@ public class EquatePlugin extends Plugin {
|
||||||
private SetEquateDialog setEquateDialog;
|
private SetEquateDialog setEquateDialog;
|
||||||
private ApplyEnumDialog applyEnumDialog;
|
private ApplyEnumDialog applyEnumDialog;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param tool
|
|
||||||
*/
|
|
||||||
public EquatePlugin(PluginTool tool) {
|
public EquatePlugin(PluginTool tool) {
|
||||||
super(tool);
|
super(tool);
|
||||||
createActions();
|
createActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns the GUI for the {@link SetEquateDialog}. Note that this function will close
|
* Returns the GUI for the {@link SetEquateDialog}. Note that this function will close
|
||||||
* any instance of the dialog that is currently open and construct a new one.
|
* any instance of the dialog that is currently open and construct a new one.
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param scalar
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
private SetEquateDialog createEquateDialog(ListingActionContext context, Scalar scalar) {
|
private SetEquateDialog createEquateDialog(ListingActionContext context, Scalar scalar) {
|
||||||
if (setEquateDialog != null) {
|
if (setEquateDialog != null) {
|
||||||
|
@ -105,11 +95,9 @@ public class EquatePlugin extends Plugin {
|
||||||
return setEquateDialog;
|
return setEquateDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns the GUI for the {@link DataTypeSelectionDialog}. Note that this function will
|
* Returns the GUI for the {@link DataTypeSelectionDialog}. Note that this function will
|
||||||
* close any instance of the dialog that is currently open and construct a new one.
|
* close any instance of the dialog that is currently open and construct a new one.
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
private ApplyEnumDialog applyEnumDialog(ListingActionContext context) {
|
private ApplyEnumDialog applyEnumDialog(ListingActionContext context) {
|
||||||
DataTypeManager dtm = context.getProgram().getDataTypeManager();
|
DataTypeManager dtm = context.getProgram().getDataTypeManager();
|
||||||
|
@ -122,11 +110,6 @@ public class EquatePlugin extends Plugin {
|
||||||
return applyEnumDialog;
|
return applyEnumDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the {@link SetEquateDialog}.
|
|
||||||
*
|
|
||||||
* @param dialog
|
|
||||||
*/
|
|
||||||
private void dispose(SetEquateDialog dialog) {
|
private void dispose(SetEquateDialog dialog) {
|
||||||
if (setEquateDialog == dialog) {
|
if (setEquateDialog == dialog) {
|
||||||
setEquateDialog.dispose();
|
setEquateDialog.dispose();
|
||||||
|
@ -146,7 +129,7 @@ public class EquatePlugin extends Plugin {
|
||||||
* array or composite (CreateEquateCmd does not currently support such data cases)</li>
|
* array or composite (CreateEquateCmd does not currently support such data cases)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* Currently markup of equates is not supported within composite or array data
|
* Currently markup of equates is not supported within composite or array data
|
||||||
* @param context
|
* @param context the action context
|
||||||
* @return true if current location satisfies the above constraints
|
* @return true if current location satisfies the above constraints
|
||||||
*/
|
*/
|
||||||
protected boolean isEquatePermitted(ListingActionContext context) {
|
protected boolean isEquatePermitted(ListingActionContext context) {
|
||||||
|
@ -182,7 +165,7 @@ public class EquatePlugin extends Plugin {
|
||||||
* ultimately create the background tasks that will create the proper equate(s) for
|
* ultimately create the background tasks that will create the proper equate(s) for
|
||||||
* the selected addresses.
|
* the selected addresses.
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context the action context
|
||||||
*/
|
*/
|
||||||
private void setEquate(ListingActionContext context) {
|
private void setEquate(ListingActionContext context) {
|
||||||
|
|
||||||
|
@ -252,7 +235,7 @@ public class EquatePlugin extends Plugin {
|
||||||
/**
|
/**
|
||||||
* Called in response to the user selecting the Apply Enum action from the popup menu. This
|
* Called in response to the user selecting the Apply Enum action from the popup menu. This
|
||||||
* action will apply enum values to scalars in a selection.
|
* action will apply enum values to scalars in a selection.
|
||||||
* @param context
|
* @param context the action context
|
||||||
*/
|
*/
|
||||||
private void applyEnum(ListingActionContext context) {
|
private void applyEnum(ListingActionContext context) {
|
||||||
applyEnumDialog = applyEnumDialog(context);
|
applyEnumDialog = applyEnumDialog(context);
|
||||||
|
@ -281,7 +264,7 @@ public class EquatePlugin extends Plugin {
|
||||||
/**
|
/**
|
||||||
* Called in response to the user activating rename action from the context menu.
|
* Called in response to the user activating rename action from the context menu.
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context the action context
|
||||||
*/
|
*/
|
||||||
private void renameEquate(ListingActionContext context) {
|
private void renameEquate(ListingActionContext context) {
|
||||||
|
|
||||||
|
@ -348,12 +331,6 @@ public class EquatePlugin extends Plugin {
|
||||||
dispose(setEquateDialog);
|
dispose(setEquateDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the equate for the given context listing.
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Equate getEquate(ListingActionContext context) {
|
private Equate getEquate(ListingActionContext context) {
|
||||||
EquateTable equateTable = context.getProgram().getEquateTable();
|
EquateTable equateTable = context.getProgram().getEquateTable();
|
||||||
Scalar s = getScalar(context);
|
Scalar s = getScalar(context);
|
||||||
|
@ -363,15 +340,6 @@ public class EquatePlugin extends Plugin {
|
||||||
return equateTable.getEquate(context.getAddress(), getOperandIndex(context), s.getValue());
|
return equateTable.getEquate(context.getAddress(), getOperandIndex(context), s.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renames all equates matching the given old equate name, within the address space identified
|
|
||||||
* by the iterator.
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param oldEquate
|
|
||||||
* @param newEquateName
|
|
||||||
* @param iter
|
|
||||||
*/
|
|
||||||
private void renameEquate(ListingActionContext context, Equate oldEquate, String newEquateName,
|
private void renameEquate(ListingActionContext context, Equate oldEquate, String newEquateName,
|
||||||
CodeUnitIterator iter) {
|
CodeUnitIterator iter) {
|
||||||
|
|
||||||
|
@ -476,14 +444,6 @@ public class EquatePlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of operands for the given {@link Instruction} that match the given
|
|
||||||
* {@link Equate}.
|
|
||||||
*
|
|
||||||
* @param instruction
|
|
||||||
* @param equate
|
|
||||||
* @return an array of matches, in the format: [operand][operand-obj]
|
|
||||||
*/
|
|
||||||
private List<Integer> getInstructionMatches(Program program, Instruction instruction,
|
private List<Integer> getInstructionMatches(Program program, Instruction instruction,
|
||||||
Equate equate) {
|
Equate equate) {
|
||||||
|
|
||||||
|
@ -521,15 +481,6 @@ public class EquatePlugin extends Plugin {
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given {@link Data} object is a scalar value that has an equate
|
|
||||||
* that matches the one passed-in.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @param context
|
|
||||||
* @param equate
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean isDataMatch(Data data, ListingActionContext context, Equate equate) {
|
private boolean isDataMatch(Data data, ListingActionContext context, Equate equate) {
|
||||||
|
|
||||||
if (!data.isDefined()) {
|
if (!data.isDefined()) {
|
||||||
|
@ -560,12 +511,10 @@ public class EquatePlugin extends Plugin {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Removes equates within the selected region, or a single equate if there's
|
* Removes equates within the selected region, or a single equate if there's
|
||||||
* no selection. The user will be prompted for confirmation before
|
* no selection. The user will be prompted for confirmation before
|
||||||
* removing multiple equates in a selection.
|
* removing multiple equates in a selection.
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
*/
|
*/
|
||||||
private void removeSelectedEquates(ListingActionContext context) {
|
private void removeSelectedEquates(ListingActionContext context) {
|
||||||
|
|
||||||
|
@ -606,7 +555,8 @@ public class EquatePlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the instruction at the location provided by the ProgramLocationProvider
|
* Get the instruction at the location provided by the context
|
||||||
|
* @param context the action context
|
||||||
* @return code unit containing current location if found (component data unsupported)
|
* @return code unit containing current location if found (component data unsupported)
|
||||||
*/
|
*/
|
||||||
CodeUnit getCodeUnit(ListingActionContext context) {
|
CodeUnit getCodeUnit(ListingActionContext context) {
|
||||||
|
@ -619,7 +569,7 @@ public class EquatePlugin extends Plugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the operand index at the location
|
* Get the operand index at the location
|
||||||
*
|
* @param context the action context
|
||||||
* @return 0-3 for a good operand location, -1 otherwise
|
* @return 0-3 for a good operand location, -1 otherwise
|
||||||
*/
|
*/
|
||||||
int getOperandIndex(ListingActionContext context) {
|
int getOperandIndex(ListingActionContext context) {
|
||||||
|
@ -630,11 +580,6 @@ public class EquatePlugin extends Plugin {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int getSubOperandIndex(ListingActionContext context) {
|
int getSubOperandIndex(ListingActionContext context) {
|
||||||
ProgramLocation location = context.getLocation();
|
ProgramLocation location = context.getLocation();
|
||||||
if (location instanceof OperandFieldLocation) {
|
if (location instanceof OperandFieldLocation) {
|
||||||
|
@ -649,10 +594,6 @@ public class EquatePlugin extends Plugin {
|
||||||
return scalar;
|
return scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
// *** private methods ***
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private Scalar getScalar(CodeUnit cu, ListingActionContext context) {
|
private Scalar getScalar(CodeUnit cu, ListingActionContext context) {
|
||||||
int opIndex = getOperandIndex(context);
|
int opIndex = getOperandIndex(context);
|
||||||
int subOpIndex = getSubOperandIndex(context);
|
int subOpIndex = getSubOperandIndex(context);
|
||||||
|
@ -664,7 +605,7 @@ public class EquatePlugin extends Plugin {
|
||||||
* Get scalar value associated with the specified code unit,
|
* Get scalar value associated with the specified code unit,
|
||||||
* opIndex and subOpindex. NOTE: this method does not support
|
* opIndex and subOpindex. NOTE: this method does not support
|
||||||
* composite or array data (null will always be returned).
|
* composite or array data (null will always be returned).
|
||||||
* @param cu cpde unit
|
* @param cu code unit
|
||||||
* @param opIndex operand index
|
* @param opIndex operand index
|
||||||
* @param subOpIndex sub-operand index
|
* @param subOpIndex sub-operand index
|
||||||
* @return scalar value or null
|
* @return scalar value or null
|
||||||
|
|
|
@ -38,16 +38,13 @@ import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
import ghidra.program.model.data.Enum;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.util.InvalidNameException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the make enum from a selection of enums action
|
* Tests for the 'make enum from a selection' action
|
||||||
*/
|
*/
|
||||||
public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegrationTest {
|
public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private static final String PROGRAM_FILENAME = "notepad";
|
private static final String PROGRAM_FILENAME = "notepad";
|
||||||
private static final int TASK_TIMEOUT = 2000;
|
|
||||||
|
|
||||||
//private Program program;
|
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
private ProgramDB program;
|
private ProgramDB program;
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
|
@ -57,10 +54,6 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
private ArchiveRootNode archiveRootNode;
|
private ArchiveRootNode archiveRootNode;
|
||||||
private ArchiveNode programNode;
|
private ArchiveNode programNode;
|
||||||
|
|
||||||
public CreateEnumFromSelectionTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
env = new TestEnv();
|
env = new TestEnv();
|
||||||
|
@ -93,16 +86,6 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
return builder.getProgram();
|
return builder.getProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected void tearDown() throws Exception {
|
|
||||||
// executeOnSwingWithoutBlocking(new Runnable() {
|
|
||||||
// public void run() {
|
|
||||||
// ProgramManager pm = tool.getService(ProgramManager.class);
|
|
||||||
// pm.closeProgram();
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
|
|
||||||
|
@ -116,8 +99,7 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
});
|
});
|
||||||
|
|
||||||
// this handles the save changes dialog and potential analysis dialogs
|
// this handles the save changes dialog and potential analysis dialogs
|
||||||
closeAllWindowsAndFrames();
|
closeAllWindows();
|
||||||
env.release(program);
|
|
||||||
env.dispose();
|
env.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +156,7 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Window window = waitForWindow(tool.getToolFrame(), "Name new ENUM", TASK_TIMEOUT);
|
Window window = waitForWindow("Name new ENUM");
|
||||||
assertNotNull(window);
|
assertNotNull(window);
|
||||||
|
|
||||||
final JTextField tf = findComponent(window, JTextField.class);
|
final JTextField tf = findComponent(window, JTextField.class);
|
||||||
|
@ -274,7 +256,7 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Window window = waitForWindow(tool.getToolFrame(), "Name new ENUM", TASK_TIMEOUT);
|
Window window = waitForWindow("Name new ENUM");
|
||||||
assertNotNull(window);
|
assertNotNull(window);
|
||||||
|
|
||||||
final JTextField tf = findComponent(window, JTextField.class);
|
final JTextField tf = findComponent(window, JTextField.class);
|
||||||
|
@ -283,7 +265,7 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
tf.setText("myNewEnum");
|
tf.setText("myNewEnum");
|
||||||
pressButtonByText(window, "OK");
|
pressButtonByText(window, "OK");
|
||||||
|
|
||||||
Window window2 = waitForWindow(tool.getToolFrame(), "Duplicate ENUM Name", TASK_TIMEOUT);
|
Window window2 = waitForWindow("Duplicate ENUM Name");
|
||||||
assertNotNull(window2);
|
assertNotNull(window2);
|
||||||
|
|
||||||
final JTextField tf2 = findComponent(window2, JTextField.class);
|
final JTextField tf2 = findComponent(window2, JTextField.class);
|
||||||
|
@ -334,27 +316,6 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataTypeNode createEnum(CategoryNode categoryNode, String newEnumName, int size) {
|
|
||||||
Category category = categoryNode.getCategory();
|
|
||||||
DataTypeManager dataTypeManager = category.getDataTypeManager();
|
|
||||||
int id = dataTypeManager.startTransaction("new category");
|
|
||||||
Enum newEnum = new EnumDataType(newEnumName, size);
|
|
||||||
category.addDataType(newEnum, null);
|
|
||||||
dataTypeManager.endTransaction(id, true);
|
|
||||||
waitForTree();
|
|
||||||
return getDataTypeNode(categoryNode, newEnumName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataTypeNode getDataTypeNode(GTreeNode parent, String dataTypeName) {
|
|
||||||
List<GTreeNode> children = parent.getChildren();
|
|
||||||
for (GTreeNode node : children) {
|
|
||||||
if (node instanceof DataTypeNode && node.getName().equals(dataTypeName)) {
|
|
||||||
return (DataTypeNode) node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expandNode(GTreeNode node) {
|
private void expandNode(GTreeNode node) {
|
||||||
tree.expandPath(node);
|
tree.expandPath(node);
|
||||||
waitForTree();
|
waitForTree();
|
||||||
|
@ -373,37 +334,4 @@ public class CreateEnumFromSelectionTest extends AbstractGhidraHeadedIntegration
|
||||||
private void waitForTree() {
|
private void waitForTree() {
|
||||||
waitForTree(tree);
|
waitForTree(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForProgram() throws Exception {
|
|
||||||
program.flushEvents();
|
|
||||||
waitForTasks();
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
}
|
|
||||||
|
|
||||||
private CategoryNode createCategory(CategoryNode categoryNode, String newCategoryName) {
|
|
||||||
Category category = categoryNode.getCategory();
|
|
||||||
DataTypeManager dataTypeManager = category.getDataTypeManager();
|
|
||||||
int id = dataTypeManager.startTransaction("new category");
|
|
||||||
try {
|
|
||||||
category.createCategory(newCategoryName);
|
|
||||||
}
|
|
||||||
catch (InvalidNameException e) {
|
|
||||||
// shouldn't happen
|
|
||||||
}
|
|
||||||
dataTypeManager.endTransaction(id, true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
CategoryNode node = getCategoryNode(categoryNode, newCategoryName);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CategoryNode getCategoryNode(GTreeNode parent, String categoryName) {
|
|
||||||
List<GTreeNode> children = parent.getChildren();
|
|
||||||
for (GTreeNode node : children) {
|
|
||||||
if (node instanceof CategoryNode && node.getName().equals(categoryName)) {
|
|
||||||
return (CategoryNode) node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,51 +30,34 @@ import ghidra.program.model.symbol.*;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the equate manager for the database implementation.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private ProgramDB program;
|
private ProgramDB program;
|
||||||
private AddressSpace space;
|
private AddressSpace space;
|
||||||
private EquateTable equateTable;
|
private EquateTable equateTable;
|
||||||
private int transactionID;
|
private int transactionID;
|
||||||
|
|
||||||
/**
|
@Before
|
||||||
* Constructor for EquateManagerTest.
|
public void setUp() throws Exception {
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
public EquateManagerTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see TestCase#setUp()
|
|
||||||
*/
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
program = createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
program = createDefaultProgram("Test", ProgramBuilder._TOY, this);
|
||||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
transactionID = program.startTransaction("Test");
|
transactionID = program.startTransaction("Test");
|
||||||
memory.createInitializedBlock("test", addr(0), 5000, (byte) 0,
|
memory.createInitializedBlock("test", addr(0), 5000, (byte) 0, TaskMonitor.DUMMY, false);
|
||||||
TaskMonitorAdapter.DUMMY_MONITOR, false);
|
|
||||||
|
|
||||||
equateTable = program.getEquateTable();
|
equateTable = program.getEquateTable();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
program.endTransaction(transactionID, true);
|
program.endTransaction(transactionID, true);
|
||||||
program.release(this);
|
program.release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateEquate() throws Exception {
|
public void testCreateEquate() throws Exception {
|
||||||
Equate equate = equateTable.createEquate("Test", 100);
|
Equate equate = equateTable.createEquate("Test", 100);
|
||||||
assertNotNull(equate);
|
assertNotNull(equate);
|
||||||
|
|
||||||
|
@ -82,8 +65,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertNotNull(equate);
|
assertNotNull(equate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateEquateDuplicate() throws Exception {
|
public void testCreateEquateDuplicate() throws Exception {
|
||||||
equateTable.createEquate("Test", 100);
|
equateTable.createEquate("Test", 100);
|
||||||
equateTable.createEquate("Test-2", 1000);
|
equateTable.createEquate("Test-2", 1000);
|
||||||
try {
|
try {
|
||||||
|
@ -91,35 +74,38 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Assert.fail("Should have gotten duplicate name exception");
|
Assert.fail("Should have gotten duplicate name exception");
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadNameForCreate() throws Exception {
|
public void testBadNameForCreate() throws Exception {
|
||||||
try {
|
try {
|
||||||
equateTable.createEquate("", 100);
|
equateTable.createEquate("", 100);
|
||||||
Assert.fail("Should have gotten invalid input exception");
|
Assert.fail("Should have gotten invalid input exception");
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
equateTable.createEquate(null, 100);
|
equateTable.createEquate(null, 100);
|
||||||
Assert.fail("Should have gotten invalid input exception");
|
Assert.fail("Should have gotten invalid input exception");
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicEquate() throws Exception {
|
public void testBasicEquate() throws Exception {
|
||||||
Equate equate = equateTable.createEquate("Test", 100);
|
Equate equate = equateTable.createEquate("Test", 100);
|
||||||
assertEquals("Test", equate.getName());
|
assertEquals("Test", equate.getName());
|
||||||
|
|
||||||
assertEquals(100, equate.getValue());
|
assertEquals(100, equate.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddReferenceOnEquate() throws Exception {
|
public void testAddReferenceOnEquate() throws Exception {
|
||||||
Equate eqTest = equateTable.createEquate("Test", 100);
|
Equate eqTest = equateTable.createEquate("Test", 100);
|
||||||
eqTest.addReference(addr(100), 0);
|
eqTest.addReference(addr(100), 0);
|
||||||
EquateReference[] refs = eqTest.getReferences();
|
EquateReference[] refs = eqTest.getReferences();
|
||||||
|
@ -150,8 +136,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
// assertEquals(1, eqTest3.getReferenceCount());
|
// assertEquals(1, eqTest3.getReferenceCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveReference() throws Exception {
|
public void testRemoveReference() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test", 1);
|
Equate eq = equateTable.createEquate("Test", 1);
|
||||||
|
|
||||||
eq.addReference(addr(10), 0);
|
eq.addReference(addr(10), 0);
|
||||||
|
@ -185,8 +171,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(7, refs.length);
|
assertEquals(7, refs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquateIterator() throws Exception {
|
public void testEquateIterator() throws Exception {
|
||||||
|
|
||||||
for (int i = 10; i < 20; i++) {
|
for (int i = 10; i < 20; i++) {
|
||||||
equateTable.createEquate("Test_" + i, i);
|
equateTable.createEquate("Test_" + i, i);
|
||||||
|
@ -203,8 +189,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquateAddressIterator() throws Exception {
|
public void testEquateAddressIterator() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test", 1);
|
Equate eq = equateTable.createEquate("Test", 1);
|
||||||
|
|
||||||
eq.addReference(addr(100), 3);
|
eq.addReference(addr(100), 3);
|
||||||
|
@ -228,8 +214,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(7, count);// should filter out duplicate ref addrs
|
assertEquals(7, count);// should filter out duplicate ref addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquateAddressIteratorStart() throws Exception {
|
public void testEquateAddressIteratorStart() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test", 1);
|
Equate eq = equateTable.createEquate("Test", 1);
|
||||||
|
|
||||||
eq.addReference(addr(100), 3);
|
eq.addReference(addr(100), 3);
|
||||||
|
@ -247,8 +233,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(2, count);// should filter out duplicate ref addrs
|
assertEquals(2, count);// should filter out duplicate ref addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquateAddressIteratorSet() throws Exception {
|
public void testEquateAddressIteratorSet() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test", 1);
|
Equate eq = equateTable.createEquate("Test", 1);
|
||||||
|
|
||||||
eq.addReference(addr(100), 3);
|
eq.addReference(addr(100), 3);
|
||||||
|
@ -287,8 +273,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetEquatesByValue() throws Exception {
|
public void testGetEquatesByValue() throws Exception {
|
||||||
// now create equates with the same value
|
// now create equates with the same value
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
equateTable.createEquate("EQ_0" + i, 500);
|
equateTable.createEquate("EQ_0" + i, 500);
|
||||||
|
@ -299,8 +285,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(12, equates.size());
|
assertEquals(12, equates.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetEquateByName() throws Exception {
|
public void testGetEquateByName() throws Exception {
|
||||||
equateTable.createEquate("Test", 500);
|
equateTable.createEquate("Test", 500);
|
||||||
equateTable.createEquate("Test2", 1500);
|
equateTable.createEquate("Test2", 1500);
|
||||||
|
|
||||||
|
@ -315,8 +301,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertNull(equateTable.getEquate("foo"));
|
assertNull(equateTable.getEquate("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveEquate() throws Exception {
|
public void testRemoveEquate() throws Exception {
|
||||||
equateTable.createEquate("Test", 500);
|
equateTable.createEquate("Test", 500);
|
||||||
equateTable.createEquate("Test2", 1500);
|
equateTable.createEquate("Test2", 1500);
|
||||||
|
|
||||||
|
@ -325,8 +311,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertNotNull(equateTable.getEquate("Test2"));
|
assertNotNull(equateTable.getEquate("Test2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveEquateWithRefs() throws Exception {
|
public void testRemoveEquateWithRefs() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test", 1);
|
Equate eq = equateTable.createEquate("Test", 1);
|
||||||
|
|
||||||
eq.addReference(addr(100), 3);
|
eq.addReference(addr(100), 3);
|
||||||
|
@ -344,8 +330,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertNotNull(equateTable.getEquate("Test2"));
|
assertNotNull(equateTable.getEquate("Test2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveEquatesInRange() throws Exception {
|
public void testRemoveEquatesInRange() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test1", 100);
|
Equate eq = equateTable.createEquate("Test1", 100);
|
||||||
equateTable.createEquate("Test2", 200);
|
equateTable.createEquate("Test2", 200);
|
||||||
equateTable.createEquate("Test3", 200);
|
equateTable.createEquate("Test3", 200);
|
||||||
|
@ -370,7 +356,7 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
assertEquals(6, count);
|
assertEquals(6, count);
|
||||||
|
|
||||||
equateTable.deleteAddressRange(addr(50), addr(500), TaskMonitorAdapter.DUMMY_MONITOR);
|
equateTable.deleteAddressRange(addr(50), addr(500), TaskMonitor.DUMMY);
|
||||||
assertNull(equateTable.getEquate("Test1"));
|
assertNull(equateTable.getEquate("Test1"));
|
||||||
assertNotNull(equateTable.getEquate("Test4"));
|
assertNotNull(equateTable.getEquate("Test4"));
|
||||||
assertEquals(0, equateTable.getEquates(addr(100), 0).size());
|
assertEquals(0, equateTable.getEquates(addr(100), 0).size());
|
||||||
|
@ -386,8 +372,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(5, count);
|
assertEquals(5, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRenameEquate() throws Exception {
|
public void testRenameEquate() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test1", 100);
|
Equate eq = equateTable.createEquate("Test1", 100);
|
||||||
equateTable.createEquate("Test2", 200);
|
equateTable.createEquate("Test2", 200);
|
||||||
equateTable.createEquate("Test3", 200);
|
equateTable.createEquate("Test3", 200);
|
||||||
|
@ -407,8 +393,8 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(eq, temp);
|
assertEquals(eq, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRenameEquateDuplicate() throws Exception {
|
public void testRenameEquateDuplicate() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test1", 100);
|
Equate eq = equateTable.createEquate("Test1", 100);
|
||||||
equateTable.createEquate("Test2", 200);
|
equateTable.createEquate("Test2", 200);
|
||||||
equateTable.createEquate("Test3", 200);
|
equateTable.createEquate("Test3", 200);
|
||||||
|
@ -419,6 +405,7 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Assert.fail("Should have gotten DuplicateNameException");
|
Assert.fail("Should have gotten DuplicateNameException");
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
eq = equateTable.createEquate("foo", 100);
|
eq = equateTable.createEquate("foo", 100);
|
||||||
eq.renameEquate("foo");// nothing should happen
|
eq.renameEquate("foo");// nothing should happen
|
||||||
|
@ -427,23 +414,26 @@ public class EquateManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Assert.fail("Should have gotten DuplicateNameException");
|
Assert.fail("Should have gotten DuplicateNameException");
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRenameEquateBadName() throws Exception {
|
public void testRenameEquateBadName() throws Exception {
|
||||||
Equate eq = equateTable.createEquate("Test1", 100);
|
Equate eq = equateTable.createEquate("Test1", 100);
|
||||||
try {
|
try {
|
||||||
eq.renameEquate("");
|
eq.renameEquate("");
|
||||||
Assert.fail("Empty string should be invalid!");
|
Assert.fail("Empty string should be invalid!");
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
eq.renameEquate(null);
|
eq.renameEquate(null);
|
||||||
Assert.fail("Empty string should be invalid!");
|
Assert.fail("Empty string should be invalid!");
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@ package ghidra.program.database.symbol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import db.*;
|
import db.*;
|
||||||
import db.util.ErrorHandler;
|
import db.util.ErrorHandler;
|
||||||
|
@ -27,22 +24,17 @@ import ghidra.program.database.*;
|
||||||
import ghidra.program.database.map.AddressKeyAddressIterator;
|
import ghidra.program.database.map.AddressKeyAddressIterator;
|
||||||
import ghidra.program.database.map.AddressMap;
|
import ghidra.program.database.map.AddressMap;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
|
||||||
import ghidra.program.model.data.Enum;
|
|
||||||
import ghidra.program.model.listing.*;
|
|
||||||
import ghidra.program.model.scalar.Scalar;
|
|
||||||
import ghidra.program.model.symbol.Equate;
|
import ghidra.program.model.symbol.Equate;
|
||||||
import ghidra.program.model.symbol.EquateTable;
|
import ghidra.program.model.symbol.EquateTable;
|
||||||
import ghidra.program.util.ChangeManager;
|
import ghidra.program.util.ChangeManager;
|
||||||
import ghidra.program.util.EquateInfo;
|
import ghidra.program.util.EquateInfo;
|
||||||
import ghidra.util.*;
|
import ghidra.util.Lock;
|
||||||
|
import ghidra.util.UniversalID;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for the Equate Table.
|
* Implementation of the Equate Table
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
|
|
||||||
|
@ -60,14 +52,12 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param handle database handle
|
* @param handle database handle
|
||||||
* @param addrMap map that converts addresses to longs and longs to
|
* @param addrMap map that converts addresses to longs and longs to addresses
|
||||||
* addresses
|
|
||||||
* @param openMode one of ProgramDB.CREATE, UPDATE, UPGRADE, or READ_ONLY
|
* @param openMode one of ProgramDB.CREATE, UPDATE, UPGRADE, or READ_ONLY
|
||||||
* @param lock the program synchronization lock
|
* @param lock the program synchronization lock
|
||||||
* @param monitor the progress monitor used when upgrading.
|
* @param monitor the progress monitor used when upgrading.
|
||||||
* @throws VersionException if the database version doesn't match the current version.
|
* @throws VersionException if the database version doesn't match the current version.
|
||||||
* @throws IOException if a database error occurs.
|
* @throws IOException if a database error occurs.
|
||||||
* @throws CancelledException if the user cancels the upgrade.
|
|
||||||
*/
|
*/
|
||||||
public EquateManager(DBHandle handle, AddressMap addrMap, int openMode, Lock lock,
|
public EquateManager(DBHandle handle, AddressMap addrMap, int openMode, Lock lock,
|
||||||
TaskMonitor monitor) throws VersionException, IOException {
|
TaskMonitor monitor) throws VersionException, IOException {
|
||||||
|
@ -103,149 +93,22 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.ManagerDB#setProgram(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgram(ProgramDB program) {
|
public void setProgram(ProgramDB program) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.ManagerDB#programReady(int, int, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void programReady(int openMode, int currentRevision, TaskMonitor monitor)
|
public void programReady(int openMode, int currentRevision, TaskMonitor monitor)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see db.util.ErrorHandler#dbError(java.io.IOException)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void dbError(IOException e) {
|
public void dbError(IOException e) {
|
||||||
program.dbError(e);
|
program.dbError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void applyEnum(AddressSetView addresses, Enum enoom, TaskMonitor monitor,
|
|
||||||
boolean shouldDoOnSubOps) throws CancelledException {
|
|
||||||
|
|
||||||
if (addresses == null) {
|
|
||||||
throw new IllegalArgumentException("Can't apply Enum over null addresses");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enoom == null) {
|
|
||||||
throw new IllegalArgumentException("Data Type is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
Consumer<Instruction> applyEquates = instruction -> {
|
|
||||||
|
|
||||||
if (monitor.isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int opIndex = 0; opIndex < instruction.getNumOperands(); opIndex++) {
|
|
||||||
|
|
||||||
if (!shouldDoOnSubOps) {
|
|
||||||
// Only apply equates to scalars that are not contained in sub operands.
|
|
||||||
Scalar scalar = instruction.getScalar(opIndex);
|
|
||||||
maybeCreateEquateOnScalar(enoom, instruction, opIndex, scalar);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Apply equates to scalars in the sub operands as well.
|
|
||||||
List<?> subOperands = instruction.getDefaultOperandRepresentationList(opIndex);
|
|
||||||
for (Object subOp : subOperands) {
|
|
||||||
maybeCreateEquateOnScalar(enoom, instruction, opIndex, subOp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
|
||||||
InstructionIterator it = listing.getInstructions(addresses, true);
|
|
||||||
Stream<Instruction> instructions = StreamSupport.stream(it.spliterator(), false);
|
|
||||||
|
|
||||||
DataTypeManager dtm = program.getDataTypeManager();
|
|
||||||
try {
|
|
||||||
lock.acquire();
|
|
||||||
int id = dtm.startTransaction("Apply Enum");
|
|
||||||
instructions.forEach(applyEquates);
|
|
||||||
dtm.endTransaction(id, true);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
lock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeCreateEquateOnScalar(Enum enoom, Instruction instruction, int opIndex,
|
|
||||||
Object operandRepresentation) {
|
|
||||||
|
|
||||||
if (!(operandRepresentation instanceof Scalar)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scalar scalar = (Scalar) operandRepresentation;
|
|
||||||
|
|
||||||
int enoomLength = enoom.getLength();
|
|
||||||
boolean anyValuesMatch = Arrays.stream(enoom.getValues()).anyMatch(enumValue -> {
|
|
||||||
return scalar.equals(new Scalar(enoomLength * 8, enumValue, scalar.isSigned()));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!anyValuesMatch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (program.getDataTypeManager().findDataTypeForID(enoom.getUniversalID()) == null) {
|
|
||||||
int transactionID = program.startTransaction("Set Equate Dialog");
|
|
||||||
try {
|
|
||||||
enoom = (Enum) program.getDataTypeManager().addDataType(enoom, null);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Address addr = instruction.getAddress();
|
|
||||||
removeUnusedEquates(opIndex, scalar, addr);
|
|
||||||
|
|
||||||
long value = scalar.getValue();
|
|
||||||
String equateName = EquateManager.formatNameForEquate(enoom.getUniversalID(), value);
|
|
||||||
Equate equate = getOrCreateEquate(equateName, value);
|
|
||||||
equate.addReference(addr, opIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeUnusedEquates(int opIndex, Scalar scalar, Address addr) {
|
|
||||||
Equate existingEquate = getEquate(addr, opIndex, scalar.getValue());
|
|
||||||
if (existingEquate != null) {
|
|
||||||
if (existingEquate.getReferenceCount() <= 1) {
|
|
||||||
removeEquate(existingEquate.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Equate getOrCreateEquate(String name, long value) {
|
|
||||||
Equate equate = getEquate(name);
|
|
||||||
if (equate != null) {
|
|
||||||
return equate;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
equate = createEquate(name, value);
|
|
||||||
}
|
|
||||||
catch (DuplicateNameException | InvalidInputException e) {
|
|
||||||
// These should not happen:
|
|
||||||
// Duplicate will not happen since we checked for the existence first; Invalid
|
|
||||||
// can't happen since we built the name ourselves (we are assuming)
|
|
||||||
Msg.error(this, "Unexpected error creating equate", e); // just in case
|
|
||||||
}
|
|
||||||
return equate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#createEquate(java.lang.String, long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Equate createEquate(String name, long value)
|
public Equate createEquate(String name, long value)
|
||||||
throws DuplicateNameException, InvalidInputException {
|
throws DuplicateNameException, InvalidInputException {
|
||||||
|
@ -271,9 +134,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquate(ghidra.program.model.address.Address, int, long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Equate getEquate(Address reference, int opIndex, long scalarValue) {
|
public Equate getEquate(Address reference, int opIndex, long scalarValue) {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
|
@ -302,9 +162,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquates(ghidra.program.model.address.Address, int)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<Equate> getEquates(Address reference, int opIndex) {
|
public List<Equate> getEquates(Address reference, int opIndex) {
|
||||||
List<Equate> ret = new LinkedList<>();
|
List<Equate> ret = new LinkedList<>();
|
||||||
|
@ -331,9 +188,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquates(ghidra.program.model.address.Address)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<Equate> getEquates(Address reference) {
|
public List<Equate> getEquates(Address reference) {
|
||||||
List<Equate> ret = new LinkedList<>();
|
List<Equate> ret = new LinkedList<>();
|
||||||
|
@ -358,9 +212,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquate(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Equate getEquate(String name) {
|
public Equate getEquate(String name) {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
|
@ -369,6 +220,7 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return getEquateDB(equateID);
|
return getEquateDB(equateID);
|
||||||
}
|
}
|
||||||
catch (NotFoundException e) {
|
catch (NotFoundException e) {
|
||||||
|
// just return null below
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
program.dbError(e);
|
program.dbError(e);
|
||||||
|
@ -379,9 +231,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquateAddresses()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AddressIterator getEquateAddresses() {
|
public AddressIterator getEquateAddresses() {
|
||||||
|
|
||||||
|
@ -395,9 +244,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return new EmptyAddressIterator();
|
return new EmptyAddressIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquateAddresses(ghidra.program.model.address.Address)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AddressIterator getEquateAddresses(Address startAddr) {
|
public AddressIterator getEquateAddresses(Address startAddr) {
|
||||||
try {
|
try {
|
||||||
|
@ -421,9 +267,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return new EmptyAddressIterator();
|
return new EmptyAddressIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquateAddresses(ghidra.program.model.address.AddressSetView)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AddressIterator getEquateAddresses(AddressSetView set) {
|
public AddressIterator getEquateAddresses(AddressSetView set) {
|
||||||
try {
|
try {
|
||||||
|
@ -436,9 +279,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return new EmptyAddressIterator();
|
return new EmptyAddressIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquates()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Equate> getEquates() {
|
public Iterator<Equate> getEquates() {
|
||||||
try {
|
try {
|
||||||
|
@ -451,9 +291,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return new EquateIterator(null);
|
return new EquateIterator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#getEquates(long)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public List<Equate> getEquates(long value) {
|
public List<Equate> getEquates(long value) {
|
||||||
ArrayList<Equate> list = new ArrayList<>();
|
ArrayList<Equate> list = new ArrayList<>();
|
||||||
|
@ -473,9 +310,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.ManagerDB#deleteAddressRange(ghidra.program.model.address.Address, ghidra.program.model.address.Address, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
|
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
@ -516,9 +350,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.model.symbol.EquateTable#removeEquate(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeEquate(String name) {
|
public boolean removeEquate(String name) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
|
@ -562,30 +393,18 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the address map.
|
|
||||||
*/
|
|
||||||
AddressMap getAddressMap() {
|
AddressMap getAddressMap() {
|
||||||
return addrMap;
|
return addrMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the database adapter for equate table.
|
|
||||||
*/
|
|
||||||
EquateDBAdapter getEquateDatabaseAdapter() {
|
EquateDBAdapter getEquateDatabaseAdapter() {
|
||||||
return equateAdapter;
|
return equateAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the database adapter for the equate references table.
|
|
||||||
*/
|
|
||||||
EquateRefDBAdapter getRefDatabaseAdapter() {
|
EquateRefDBAdapter getRefDatabaseAdapter() {
|
||||||
return refAdapter;
|
return refAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a reference for an equate at the given operand position.
|
|
||||||
*/
|
|
||||||
void addReference(long equateID, Address address, int opIndex, long dynamicHash)
|
void addReference(long equateID, Address address, int opIndex, long dynamicHash)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
|
@ -622,9 +441,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the references for the given equate ID.
|
|
||||||
*/
|
|
||||||
EquateRefDB[] getReferences(long equateID) throws IOException {
|
EquateRefDB[] getReferences(long equateID) throws IOException {
|
||||||
long[] keys = refAdapter.getRecordKeysForEquateID(equateID);
|
long[] keys = refAdapter.getRecordKeysForEquateID(equateID);
|
||||||
EquateRefDB[] refs = new EquateRefDB[keys.length];
|
EquateRefDB[] refs = new EquateRefDB[keys.length];
|
||||||
|
@ -634,19 +450,10 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of references for the given equate ID.
|
|
||||||
*/
|
|
||||||
int getReferenceCount(long equateID) throws IOException {
|
int getReferenceCount(long equateID) throws IOException {
|
||||||
return getReferences(equateID).length;
|
return getReferences(equateID).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the reference.
|
|
||||||
* @param equateDB equate
|
|
||||||
* @param refAddr ref address to remove
|
|
||||||
* @param opIndex operand index
|
|
||||||
*/
|
|
||||||
void removeReference(EquateDB equateDB, Address refAddr, short opIndex) throws IOException {
|
void removeReference(EquateDB equateDB, Address refAddr, short opIndex) throws IOException {
|
||||||
|
|
||||||
long[] keys = refAdapter.getRecordKeysForEquateID(equateDB.getKey());
|
long[] keys = refAdapter.getRecordKeysForEquateID(equateDB.getKey());
|
||||||
|
@ -659,13 +466,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the reference.
|
|
||||||
* @param equateDB equate
|
|
||||||
* @param dynamicHash hash value
|
|
||||||
* @param refAddr ref address to remove
|
|
||||||
* @param opIndex operand index
|
|
||||||
*/
|
|
||||||
void removeReference(EquateDB equateDB, long dynamicHash, Address refAddr) throws IOException {
|
void removeReference(EquateDB equateDB, long dynamicHash, Address refAddr) throws IOException {
|
||||||
|
|
||||||
long[] keys = refAdapter.getRecordKeysForEquateID(equateDB.getKey());
|
long[] keys = refAdapter.getRecordKeysForEquateID(equateDB.getKey());
|
||||||
|
@ -678,10 +478,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify that the name is not null and not the empty string.
|
|
||||||
* @throws InvalidInputException if the name is null or is empty
|
|
||||||
*/
|
|
||||||
void validateName(String name) throws InvalidInputException {
|
void validateName(String name) throws InvalidInputException {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new InvalidInputException("Name is null");
|
throw new InvalidInputException("Name is null");
|
||||||
|
@ -693,7 +489,7 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send notification that the equate name changed.
|
* Send notification that the equate name changed
|
||||||
* @param oldName old name
|
* @param oldName old name
|
||||||
* @param newName new name
|
* @param newName new name
|
||||||
*/
|
*/
|
||||||
|
@ -784,66 +580,10 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
private class EquateIterator implements Iterator<Equate> {
|
|
||||||
private RecordIterator iter;
|
|
||||||
|
|
||||||
private EquateIterator(RecordIterator iter) {
|
|
||||||
this.iter = iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.util.Iterator#hasNext()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
if (iter != null) {
|
|
||||||
try {
|
|
||||||
return iter.hasNext();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
program.dbError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.util.Iterator#next()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Equate next() {
|
|
||||||
if (iter != null) {
|
|
||||||
try {
|
|
||||||
Record record = iter.next();
|
|
||||||
if (record != null) {
|
|
||||||
return getEquateDB(record.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
program.dbError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see java.util.Iterator#remove()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException("remove is not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Lock getLock() {
|
Lock getLock() {
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.ManagerDB#invalidateCache(boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateCache(boolean all) {
|
public void invalidateCache(boolean all) {
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
|
@ -856,9 +596,6 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.program.database.ManagerDB#moveAddressRange(ghidra.program.model.address.Address, ghidra.program.model.address.Address, long, ghidra.util.task.TaskMonitor)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
@ -879,7 +616,7 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
* Formats a string to the equate format given the enum UUID and the value for the equate. The
|
* Formats a string to the equate format given the enum UUID and the value for the equate. The
|
||||||
* formatted strings are used when setting equates from datatypes so that information can be
|
* formatted strings are used when setting equates from datatypes so that information can be
|
||||||
* stored with an equate to point back to that datatype.
|
* stored with an equate to point back to that datatype.
|
||||||
* @param dtID The enums data type UUID
|
* @param dtID The enum's data type UUID
|
||||||
* @param equateValue The value intended for the equate
|
* @param equateValue The value intended for the equate
|
||||||
* @return The formatted equate name
|
* @return The formatted equate name
|
||||||
*/
|
*/
|
||||||
|
@ -922,4 +659,51 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// Inner Classes
|
||||||
|
//==================================================================================================
|
||||||
|
|
||||||
|
private class EquateIterator implements Iterator<Equate> {
|
||||||
|
private RecordIterator iter;
|
||||||
|
|
||||||
|
private EquateIterator(RecordIterator iter) {
|
||||||
|
this.iter = iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
if (iter != null) {
|
||||||
|
try {
|
||||||
|
return iter.hasNext();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
program.dbError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Equate next() {
|
||||||
|
if (iter != null) {
|
||||||
|
try {
|
||||||
|
Record record = iter.next();
|
||||||
|
if (record != null) {
|
||||||
|
return getEquateDB(record.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
program.dbError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("remove is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.Enum;
|
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EquateTable manages all equates for program. An equate defines a relationship
|
* EquateTable manages all equates for program. An equate defines a relationship
|
||||||
* between a scalar value and a string whereby the scalar may be represented by
|
* between a scalar value and a string whereby the scalar may be represented by
|
||||||
|
@ -32,40 +32,25 @@ import ghidra.util.task.TaskMonitor;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface EquateTable {
|
public interface EquateTable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates equates and/or adds references for scalars
|
* Creates a new equate
|
||||||
* in the given address set using the given data type.
|
* @param name the name to associate with the given value.
|
||||||
* The data type given must be an enumeration data type.
|
* @param value the value to associate with the given name.
|
||||||
* @param addrSet the address set to use.
|
* @return the equate
|
||||||
* @param dataType the data type to use.
|
* @exception DuplicateNameException thrown if name is already in use
|
||||||
* @param monitor task monitor to cancel the remove operation
|
* as an equate.
|
||||||
* @param shouldDoOnSubOps true if the enum should be applied inside sub-operands as well.
|
* @throws InvalidInputException if name contains blank characters,
|
||||||
*
|
* is zero length, or is null
|
||||||
* @throws CancelledException if the operation is cancelled
|
|
||||||
* @throws IllegalArgumentException if the dataType is null or not an enum.
|
|
||||||
*/
|
*/
|
||||||
public void applyEnum(AddressSetView addrSet, Enum dataType, TaskMonitor monitor,
|
public Equate createEquate(String name, long value)
|
||||||
boolean shouldDoOnSubOps) throws CancelledException;
|
throws DuplicateNameException, InvalidInputException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new equate
|
* Removes the equate from the program.
|
||||||
* @param name the name to associate with the given value.
|
* @param name the name of the equate to remove.
|
||||||
* @param value the value to associate with the given name.
|
* @return true if the equate existed, false otherwise.
|
||||||
* @exception DuplicateNameException thrown if name is already in use
|
*/
|
||||||
* as an equate.
|
|
||||||
* @throws InvalidInputException if name contains blank characters,
|
|
||||||
* is zero length, or is null
|
|
||||||
*/
|
|
||||||
public Equate createEquate(String name,long value)
|
|
||||||
throws DuplicateNameException, InvalidInputException;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the equate from the program.
|
|
||||||
* @param name the name of the equate to remove.
|
|
||||||
* @return true if the equate existed, false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean removeEquate(String name);
|
public boolean removeEquate(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,24 +60,25 @@ public interface EquateTable {
|
||||||
* @param monitor task monitor to cancel the remove operation
|
* @param monitor task monitor to cancel the remove operation
|
||||||
* @throws CancelledException if the operation was cancelled.
|
* @throws CancelledException if the operation was cancelled.
|
||||||
*/
|
*/
|
||||||
public void deleteAddressRange(Address start, Address end, TaskMonitor monitor) throws CancelledException;
|
public void deleteAddressRange(Address start, Address end, TaskMonitor monitor)
|
||||||
|
throws CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the equate with the given name, null if no such equate
|
* Returns the equate with the given name, null if no such equate exists
|
||||||
* exists.
|
* @param name the of the equate to be retrieved
|
||||||
* @param name the of the equate to be retrieved.
|
* @return the equate
|
||||||
*/
|
*/
|
||||||
public Equate getEquate(String name);
|
public Equate getEquate(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first equate found that is associated with the given
|
* Returns the first equate found that is associated with the given
|
||||||
* value at the given reference address and operand position;
|
* value at the given reference address and operand position;
|
||||||
* @param reference address where the equate is used.
|
* @param reference address where the equate is used.
|
||||||
* @param opndPosition the operand index of the operand where the equate is used.
|
* @param opndPosition the operand index of the operand where the equate is used.
|
||||||
* @param value the value where the equate is used.
|
* @param value the value where the equate is used.
|
||||||
* @return the equate or null if there is no such equate.
|
* @return the equate or null if there is no such equate.
|
||||||
*/
|
*/
|
||||||
public Equate getEquate(Address reference, int opndPosition, long value);
|
public Equate getEquate(Address reference, int opndPosition, long value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the equates (one for each scalar) at the given reference address
|
* Returns the equates (one for each scalar) at the given reference address
|
||||||
|
@ -102,7 +88,7 @@ public interface EquateTable {
|
||||||
* @return the list of equates or empty list if there is no such equate.
|
* @return the list of equates or empty list if there is no such equate.
|
||||||
*/
|
*/
|
||||||
public List<Equate> getEquates(Address reference, int opndPosition);
|
public List<Equate> getEquates(Address reference, int opndPosition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the equates (one for each scalar and opIndex) at the given reference address.
|
* Returns the equates (one for each scalar and opIndex) at the given reference address.
|
||||||
* For an instruction a given operand can have multiple scalars.
|
* For an instruction a given operand can have multiple scalars.
|
||||||
|
@ -111,39 +97,42 @@ public interface EquateTable {
|
||||||
*/
|
*/
|
||||||
public List<Equate> getEquates(Address reference);
|
public List<Equate> getEquates(Address reference);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an address iterator over all the addresses where
|
* Returns an address iterator over all the addresses where
|
||||||
* equates have been set.
|
* equates have been set.
|
||||||
*/
|
* @return the iterator
|
||||||
public AddressIterator getEquateAddresses();
|
*/
|
||||||
|
public AddressIterator getEquateAddresses();
|
||||||
/**
|
|
||||||
* Returns all equates defined for value.
|
/**
|
||||||
* @param value the value to get all equates for.
|
* Returns all equates defined for value.
|
||||||
*/
|
* @param value the value to get all equates for.
|
||||||
public List<Equate> getEquates(long value);
|
* @return the equates
|
||||||
|
*/
|
||||||
/**
|
public List<Equate> getEquates(long value);
|
||||||
* Returns an iterator over all equates.
|
|
||||||
*/
|
/**
|
||||||
|
* Returns an iterator over all equates.
|
||||||
|
* @return the iterator
|
||||||
|
*/
|
||||||
public Iterator<Equate> getEquates();
|
public Iterator<Equate> getEquates();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an address iterator over each address with an
|
* Return an address iterator over each address with an
|
||||||
* equate reference starting at the start address.
|
* equate reference starting at the start address.
|
||||||
*
|
*
|
||||||
* @param start start address
|
* @param start start address
|
||||||
* @return an AddressIterator over addresses with defined equate references
|
* @return an AddressIterator over addresses with defined equate references
|
||||||
*/
|
*/
|
||||||
public AddressIterator getEquateAddresses(Address start);
|
public AddressIterator getEquateAddresses(Address start);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an address iterator over each address with an
|
* Return an address iterator over each address with an
|
||||||
* equate reference that is in the specified address set.
|
* equate reference that is in the specified address set.
|
||||||
*
|
*
|
||||||
* @param asv the address set
|
* @param asv the address set
|
||||||
* @return AddressIterator over addresses with defined equate references
|
* @return AddressIterator over addresses with defined equate references
|
||||||
*/
|
*/
|
||||||
public AddressIterator getEquateAddresses(AddressSetView asv);
|
public AddressIterator getEquateAddresses(AddressSetView asv);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue