GP-1556 - Added support for searching for structure fields by offset

This commit is contained in:
dragonmacher 2022-03-25 09:43:50 -04:00
parent 883f5a687a
commit 812ea4fe1e
45 changed files with 1461 additions and 840 deletions

View file

@ -38,10 +38,10 @@ public interface Data extends CodeUnit, Settings {
/**
* Get the class used to express the value of this data.
*
*
* <p>NOTE: This determination is made based upon data type and settings only and does not
* examine memory bytes which are used to construct the data value object.
*
*
* @return value class or null if a consistent class is not utilized.
*/
public Class<?> getValueClass();
@ -216,7 +216,7 @@ public interface Data extends CodeUnit, Settings {
* Return the first immediate child component that contains the byte at the given offset. It
* is important to note that with certain datatypes there may be more than one component
* containing the specified offset (see {@link #getComponentsContaining(int)}).
*
*
* @param offset the amount to add to this data items address to get the address of the
* requested data item.
* @return first data component containing offset or null
@ -227,10 +227,10 @@ public interface Data extends CodeUnit, Settings {
public Data getComponentAt(int offset);
/**
* RReturn the first immediate child component that contains the byte at the given offset. It
* Return the first immediate child component that contains the byte at the given offset. It
* is important to note that with certain datatypes there may be more than one component
* containing the specified offset (see {@link #getComponentsContaining(int)}).
*
*
* @param offset the amount to add to this data items address to get the
* @return first data component containing offset or null address of the requested data item.
*/

View file

@ -17,13 +17,15 @@
package ghidra.program.util;
import java.util.Objects;
import ghidra.framework.options.SaveState;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
/**
* The <CODE>FieldNameFieldLocation</CODE> class provides specific information
* about the Function Name field within a program location.
* The <CODE>FieldNameFieldLocation</CODE> class provides specific information about the Function
* Name field within a program location.
*/
public class FieldNameFieldLocation extends CodeUnitLocation {
@ -31,11 +33,11 @@ public class FieldNameFieldLocation extends CodeUnitLocation {
/**
* Construct a new FieldNameFieldLocation.
*
*
* @param program the program of the location
* @param addr the address of the codeunit.
* @param componentPath if not null, it is the array of indexes that point
* to a specific data type inside of another data type
* @param addr the address of the code unit
* @param componentPath if not null, it is the array of indexes that point to a specific data
* type inside of another data type
* @param fieldName the field name
* @param charOffset the character position within the field name for this location.
*/
@ -48,14 +50,14 @@ public class FieldNameFieldLocation extends CodeUnitLocation {
}
/**
* Default constructor needed for restoring
* a field name location from XML
* Default constructor needed for restoring a field name location from XML
*/
public FieldNameFieldLocation() {
}
/**
* Returns the field name of this location.
* @return the name.
*/
public String getFieldName() {
return fieldName;
@ -71,19 +73,19 @@ public class FieldNameFieldLocation extends CodeUnitLocation {
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
FieldNameFieldLocation other = (FieldNameFieldLocation) obj;
if (fieldName == null) {
if (other.fieldName != null)
return false;
}
else if (!fieldName.equals(other.fieldName))
if (!super.equals(obj)) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FieldNameFieldLocation other = (FieldNameFieldLocation) obj;
if (!Objects.equals(fieldName, other.fieldName)) {
return false;
}
return true;
}

View file

@ -15,14 +15,16 @@
*/
package ghidra.program.util;
import java.util.Objects;
import ghidra.framework.options.SaveState;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.VariableOffset;
/**
* The <CODE>OperandFieldLocation</CODE> class contains specific location information
* within the OPERAND field of a CodeUnitLocation object.
* The <CODE>OperandFieldLocation</CODE> class contains specific location information within the
* OPERAND field of a CodeUnitLocation object.
*/
public class OperandFieldLocation extends CodeUnitLocation {
@ -32,17 +34,18 @@ public class OperandFieldLocation extends CodeUnitLocation {
/**
* Construct a new OperandFieldLocation object.
*
* @param program the program of the location
* @param addr address of the location; should not be null
* @param componentPath array of indexes for each nested data component; the
* index is the data component's index within its parent; may be null
*
* @param program the program of the location.
* @param addr address of the location; should not be null.
* @param componentPath array of indexes for each nested data component; the index is the data
* component's index within its parent; may be null.
* @param refAddr the reference 'to' address.
* @param rep the String representation of the operand.
* @param opIndex the index of the operand at this location.
* @param characterOffset the character position from the beginning of the operand.
*/
public OperandFieldLocation(Program program, Address addr, int[] componentPath,
Address refAddr, String rep, int opIndex, int characterOffset) {
public OperandFieldLocation(Program program, Address addr, int[] componentPath, Address refAddr,
String rep, int opIndex, int characterOffset) {
super(program, addr, componentPath, refAddr, 0, opIndex, characterOffset);
@ -52,68 +55,63 @@ public class OperandFieldLocation extends CodeUnitLocation {
/**
* Construct a new OperandFieldLocation object.
*
* @param program the program of the location
* @param addr address of the location; should not be null
* @param componentPath array of indexes for each nested data component; the
* index is the data component's index within its parent; may be null
* @param refAddr the "referred to" address if the location is
* over a reference; may be null
*
* @param program the program of the location.
* @param addr address of the location; should not be null.
* @param componentPath array of indexes for each nested data component; the index is the data
* component's index within its parent; may be null .
* @param refAddr the "referred to" address if the location is over a reference; may be null.
* @param rep the String representation of the operand.
* @param opIndex the index indicating the operand the location is on.
* @param subOpIndex the index of the Object within the operand, this can
* be used to call an instructions getOpObjects() method
* @param characterOffset the character position from the beginning of the operand field
* @param subOpIndex the index of the Object within the operand, this can be used to call an
* instructions getOpObjects() method.
* @param characterOffset the character position from the beginning of the operand field.
*/
public OperandFieldLocation(Program program, Address addr, int[] componentPath,
Address refAddr, String rep, int opIndex, int subOpIndex, int characterOffset) {
public OperandFieldLocation(Program program, Address addr, int[] componentPath, Address refAddr,
String rep, int opIndex, int subOpIndex, int characterOffset) {
super(program, addr, componentPath, refAddr, 0, opIndex, characterOffset);
this.rep = rep;
this.subOpIndex = subOpIndex;
}
/**
* Construct a new OperandFieldLocation object for an instruction operand.
*
* @param program the program of the location
* @param addr address of the location; should not be null
* @param variableOffset associated variable offset or null
* @param refAddr the "referred to" address if the location is
* over a reference; may be null
*
* @param program the program of the location.
* @param addr address of the location; should not be null.
* @param variableOffset associated variable offset or null.
* @param refAddr the "referred to" address if the location is over a reference; may be null.
* @param rep the String representation of the operand.
* @param opIndex the index indicating the operand the location is on.
* @param subOpIndex the index of the Object within the operand, this can
* be used to call an instructions getOpObjects() method
* @param characterOffset the character position from the beginning of the operand field
* @param subOpIndex the index of the Object within the operand, this can be used to call an
* instructions getOpObjects() method.
* @param characterOffset the character position from the beginning of the operand field.
*/
public OperandFieldLocation(Program program, Address addr, VariableOffset variableOffset,
Address refAddr, String rep, int opIndex, int subOpIndex, int characterOffset) {
super(program, addr, null, refAddr, 0, opIndex, characterOffset);
this.rep = rep;
this.subOpIndex = subOpIndex;
this.variableOffset = variableOffset;
}
/**
* Default constructor needed for restoring
* an operand field location from XML.
*/
* Default constructor needed for restoring an operand field location from XML.
*/
public OperandFieldLocation() {
}
/**
* Returns VariableOffset object if applicable or null
* Returns VariableOffset object if applicable or null.
* @return the variable offset.
*/
public VariableOffset getVariableOffset() {
return variableOffset;
}
/**
* Returns a string representation of the opernand at this location.
* Returns a string representation of the operand at this location.
* @return the representation.
*/
public String getOperandRepresentation() {
return rep;
@ -121,6 +119,7 @@ public class OperandFieldLocation extends CodeUnitLocation {
/**
* Returns the index of the operand at this location.
* @return the index
*/
public int getOperandIndex() {
return getColumn();
@ -128,18 +127,15 @@ public class OperandFieldLocation extends CodeUnitLocation {
/**
* Returns the sub operand index at this location.
* This index can be used on the instruction.getOpObjects()
* to find the actual object (Address, Register, Scalar) the
* cursor is over.
* <p>
* This index can be used on the instruction.getOpObjects() to find the actual object (Address,
* Register, Scalar) the cursor is over.
* @return 0-n if over a valid OpObject, -1 otherwise
*/
public int getSubOperandIndex() {
return subOpIndex;
}
/**
* Returns a String representation of this location.
*/
@Override
public String toString() {
return super.toString() + ", OpRep = " + rep + ", subOpIndex = " + subOpIndex +
@ -158,27 +154,25 @@ public class OperandFieldLocation extends CodeUnitLocation {
@Override
public boolean equals(Object obj) {
if (this == obj)
if (this == obj) {
return true;
if (!super.equals(obj))
}
if (!super.equals(obj)) {
return false;
if (getClass() != obj.getClass())
}
if (getClass() != obj.getClass()) {
return false;
}
OperandFieldLocation other = (OperandFieldLocation) obj;
if (rep == null) {
if (other.rep != null)
return false;
if (!Objects.equals(rep, other.rep)) {
return false;
}
else if (!rep.equals(other.rep))
if (subOpIndex != other.subOpIndex) {
return false;
if (subOpIndex != other.subOpIndex)
return false;
if (variableOffset == null) {
if (other.variableOffset != null)
return false;
}
else if (!variableOffset.equals(other.variableOffset))
if (!Objects.equals(variableOffset, other.variableOffset)) {
return false;
}
return true;
}

View file

@ -95,7 +95,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
* Construct a new ProgramLocation for the given address. The address will be adjusted to the
* beginning of the {@link CodeUnit code unit} containing that address (if it exists). The
* original address can be retrieved using the {@link #getByteAddress()}" method.
*
*
* @param program the program associated with this program location (also used to obtain a
* code-unit-aligned address)
* @param addr address of the location; cannot be null
@ -118,7 +118,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
* Construct a new ProgramLocation for the given address. The address will be adjusted to the
* beginning of the {@link CodeUnit code unit} containing that address (if it exists). The
* original address can be retrieved using the {@link #getByteAddress()} method.
*
*
* @param program the program associated with this program location (also used to obtain a
* code-unit-aligned address)
* @param addr address for the location
@ -132,7 +132,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
* Construct a new ProgramLocation for the given address. The address will be adjusted to the
* beginning of the {@link CodeUnit code unit} containing that address (if it exists). The
* original address can be retrieved using the {@link #getByteAddress()} method.
*
*
* @param program the program associated with this program location (also used to obtain a
* code-unit-aligned address)
* @param addr address for the location
@ -150,7 +150,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
* Construct a new ProgramLocation for the given address. The address will be adjusted to the
* beginning of the {@link CodeUnit code unit} containing that address (if it exists). The
* original address can be retrieved using the {@link #getByteAddress()} method.
*
*
* @param program the program associated with this program location (also used to obtain a
* code-unit-aligned address)
* @param addr address for the location
@ -170,6 +170,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the componentPath for the {@link CodeUnit code unit}. Null will be returned if the
* object is an {@link Instruction} or a top-level {@link Data} object.
* @return the path.
*/
public int[] getComponentPath() {
return componentPath;
@ -177,6 +178,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the program associated with this location.
* @return the program.
*/
public Program getProgram() {
return program;
@ -184,11 +186,12 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the address associated with this location.
*
*
* <p>
* Note: this may not be the same as the byte address. For example, in a {@link CodeUnit code
* unit} location this may be the minimum address of the code unit that contains the byte
* address.
* @return the address.
*/
public Address getAddress() {
return addr;
@ -196,6 +199,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the byte level address associated with this location.
* @return the byte address.
*/
public Address getByteAddress() {
return byteAddr;
@ -203,6 +207,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the "referred to" address if the location is over an address in some field.
* @return the address.
*/
public Address getRefAddress() {
return refAddr;
@ -210,7 +215,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Save this program location to the given save state object.
*
*
* @param obj the save state object for saving the location
*/
public void saveState(SaveState obj) {
@ -231,7 +236,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Restore this program location using the given program and save state object.
*
*
* @param program1 program to restore from
* @param obj the save state to restore from
*/
@ -254,7 +259,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Get the program location for the given program and save state object.
*
*
* @param program the program for the location
* @param saveState the state to restore
* @return the restored program location
@ -274,7 +279,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
}
// no address, it must be in a removed block; we can't use it
}
catch (RuntimeException e) { // restoreState may not parse the address if it is no longer valid.
catch (RuntimeException e) { // state may not parse the address if it is no longer valid
}
catch (ClassNotFoundException e) {
// not sure why we are ignoring this--if you know, then please let everyone else know
@ -419,7 +424,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
}
CodeUnit cu = p.getListing().getCodeUnitContaining(addr);
// if the codeunit is a data, try and dig down to the lowest subdata containing the address
// if the code unit is data, get the lowest sub-data containing the address
if (cu instanceof Data) {
Data data = (Data) cu;
cu = data.getPrimitiveAt((int) addr.subtract(data.getAddress()));
@ -437,10 +442,10 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
}
/**
* Returns true if this location represents a valid location in the given program
*
* Returns true if this location represents a valid location in the given program.
*
* @param testProgram the program to test if this location is valid.
* @return true if this location represents a valid location in the given program
* @return true if this location represents a valid location in the given program.
*/
public boolean isValid(Program testProgram) {
return addr == null || testProgram.getAddressFactory().isValidAddress(addr);
@ -448,7 +453,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the row within the program location.
*
*
* @return the row within the program location.
*/
public int getRow() {
@ -456,9 +461,9 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
}
/**
* Returns the character offset in the display item at the (row,col)
*
* @return the character offset in the display item at the (row,col)
* Returns the character offset in the display item at the (row,col).
*
* @return the character offset in the display item at the (row,col).
*/
public int getCharOffset() {
return charOffset;
@ -467,6 +472,7 @@ public class ProgramLocation implements Comparable<ProgramLocation> {
/**
* Returns the column index of the display piece represented by this location. For most
* locations, there is only one display item per row, in which case this value will be 0.
* @return the column.
*/
public int getColumn() {
return col;