GT-2885 cleaned up and extended call/jump overrides

GT-2885: addressing code review
GT-2885 improved auto comments for overriding refs
GT-2885 more code review changes
James_GT-2885 more code review changes
GT-2885: reference cacheing and other code review changes
GT-2885 more code review changes, added tests
GT-2885 more code review changes
This commit is contained in:
James 2019-05-17 14:52:44 -04:00
parent 01c43efb2c
commit df983e7bba
9 changed files with 1085 additions and 115 deletions

View file

@ -29,6 +29,7 @@ import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.PcodeOverride;
import ghidra.program.model.symbol.RefType;
import ghidra.util.exception.NotYetImplementedException;
/**
@ -738,42 +739,119 @@ public abstract class PcodeEmit {
return opcode;
}
//If there is an overriding reference on an indirect call, change the indirect
//call to a direct call
if (opcode == PcodeOp.CALLIND) {
Address callRef = override.getOverridingCallReference();
//If there is an overriding call reference on an indirect call, change it to
//to a direct call, unless a call override has already been applied at this instruction
if (opcode == PcodeOp.CALLIND && !override.isCallOverrideRefApplied()) {
Address callRef = override.getOverridingReference(RefType.CALL_OVERRIDE_UNCONDITIONAL);
if (callRef != null) {
VarnodeData dest = in[0];
dest.space = callRef.getAddressSpace();
dest.offset = callRef.getOffset();
dest.size = dest.space.getPointerSize();
override.setCallOverrideRefApplied();
return PcodeOp.CALL;
}
}
// Simple call reference override - use primary call reference as destination
//CALLOTHER ops can be overridden with RefType.CALLOTHER_OVERRIDE_CALL
//or RefType.CALLOTHER_OVERRIDE_JUMP
//Call overrides take precedence over jump overrides
//override at most one callother pcode op per native instruction
boolean callOtherOverrideApplied = override.isCallOtherCallOverrideRefApplied() ||
override.isCallOtherJumpOverrideApplied();
if (opcode == PcodeOp.CALLOTHER && !callOtherOverrideApplied) {
Address overrideRef = override.getOverridingReference(RefType.CALLOTHER_OVERRIDE_CALL);
VarnodeData dest = in[0];
if (overrideRef != null) {
dest.space = overrideRef.getAddressSpace();
dest.offset = overrideRef.getOffset();
dest.size = dest.space.getPointerSize();
override.setCallOtherCallOverrideRefApplied();
return PcodeOp.CALL;
}
overrideRef = override.getOverridingReference(RefType.CALLOTHER_OVERRIDE_JUMP);
if (overrideRef != null) {
dest.space = overrideRef.getAddressSpace();
dest.offset = overrideRef.getOffset();
dest.size = dest.space.getPointerSize();
override.setCallOtherJumpOverrideRefApplied();
return PcodeOp.BRANCH;
}
}
// Simple call reference override - grab destination from appropriate reference
// Only perform reference override if destination function does not have a call-fixup
if (opcode == PcodeOp.CALL &&
if (opcode == PcodeOp.CALL && !override.isCallOverrideRefApplied() &&
!override.hasCallFixup(in[0].space.getAddress(in[0].offset))) {
// Check for call reference (not supported if call-fixup exists for the instruction)
Address callRef = override.getOverridingCallReference();
if (callRef != null) {
VarnodeData dest = in[0];
VarnodeData dest = in[0];
//call to override.getPrimaryCallReference kept for backward compatibility with
//old call override mechanism
//old mechanism has precedence over new
Address callRef = override.getPrimaryCallReference();
boolean overridingRef = false;
if (callRef == null) {
callRef = override.getOverridingReference(RefType.CALL_OVERRIDE_UNCONDITIONAL);
overridingRef = true;
}
//every call instruction automatically has a call-type reference to the call target
//we don't want these references to count as overrides - only count as an override
//via explicitly changing the destination or using a CALL_OVERRIDE_UNCONDITIONAL reference
if (callRef != null && (overridingRef || actualOverride(dest, callRef))) {
dest.space = callRef.getAddressSpace();
dest.offset = callRef.getOffset();
dest.size = dest.space.getPointerSize();
override.setCallOverrideRefApplied();
return PcodeOp.CALL;
}
}
// Fall-through override - alter branch to next instruction
if (fallOverride != null && (opcode == PcodeOp.CBRANCH || opcode == PcodeOp.BRANCH)) {
//don't apply fallthrough overrides into the constant space
if (in[0].space.getType() == AddressSpace.TYPE_CONSTANT) {
return opcode;
}
VarnodeData dest = in[0];
if (defaultFallAddress.getOffset() == dest.offset) {
dest.space = fallOverride.getAddressSpace();
dest.offset = fallOverride.getOffset();
dest.size = dest.space.getPointerSize();
}
return opcode;
}
//if there is an overriding jump reference, change a conditional jump to an
//unconditional jump with the target given by the reference
if ((opcode == PcodeOp.BRANCH || opcode == PcodeOp.CBRANCH) &&
!override.isJumpOverrideRefApplied()) {
//if the destination varnode is in the const space, it's a pcode-relative branch.
//these should not be overridden
if (in[0].space.getType() == AddressSpace.TYPE_CONSTANT) {
return opcode;
}
Address overrideRef =
override.getOverridingReference(RefType.JUMP_OVERRIDE_UNCONDITIONAL);
if (overrideRef != null) {
VarnodeData dest = in[0];
dest.space = overrideRef.getAddressSpace();
dest.offset = overrideRef.getOffset();
dest.size = dest.space.getPointerSize();
override.setJumpOverrideRefApplied();
return PcodeOp.BRANCH;
}
}
return opcode;
}
// Used to check whether the address from a potentially overriding reference
// actually changes the call destination
private boolean actualOverride(VarnodeData data, Address addr) {
if (!data.space.equals(addr.getAddressSpace())) {
return true;
}
if (data.offset != addr.getOffset()) {
return true;
}
return false;
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +15,8 @@
*/
package ghidra.program.model.listing;
import java.util.List;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.UniqueAddressFactory;
import ghidra.program.model.lang.*;
@ -23,8 +24,6 @@ import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.symbol.FlowType;
import ghidra.program.model.symbol.RefType;
import java.util.List;
/**
* Interface to define an instruction for a processor.
*/

View file

@ -15,19 +15,49 @@
*/
package ghidra.program.model.listing;
import java.util.ArrayList;
import java.util.List;
import ghidra.app.plugin.processors.sleigh.PcodeEmit;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.pcode.PcodeOverride;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.SourceType;
import ghidra.util.Msg;
public class InstructionPcodeOverride implements PcodeOverride {
protected Instruction instr;
private boolean callOverrideApplied = false;
private boolean jumpOverrideApplied = false;
private boolean callOtherCallOverrideApplied = false;
private boolean callOtherJumpOverrideApplied = false;
private Address primaryCallAddress = null;
private List<Reference> primaryOverridingReferences;
/**
* This constructor caches the primary and overriding "from" references of {@code instr}.
* This cache is never updated; the assumption is that this object is short-lived
* (duration of {@link PcodeEmit})
* @param instr the instruction
*/
public InstructionPcodeOverride(Instruction instr) {
this.instr = instr;
primaryOverridingReferences = new ArrayList<>();
for (Reference ref : instr.getReferencesFrom()) {
if (!ref.isPrimary()) {
continue;
}
RefType type = ref.getReferenceType();
if (type.isOverride()) {
primaryOverridingReferences.add(ref);
}
else if (type.isCall() && primaryCallAddress == null) {
primaryCallAddress = ref.getToAddress();
}
}
}
@Override
@ -51,14 +81,27 @@ public class InstructionPcodeOverride implements PcodeOverride {
}
@Override
public Address getOverridingCallReference() {
for (Reference ref : instr.getReferencesFrom()) {
if (ref.getSource().equals(SourceType.USER_DEFINED) && ref.isPrimary() &&
ref.getReferenceType().isCall()) {
return ref.getToAddress();
public Address getOverridingReference(RefType type) {
if (!type.isOverride()) {
return null;
}
Address overrideAddress = null;
for (Reference ref : primaryOverridingReferences) {
if (ref.getReferenceType().equals(type)) {
if (overrideAddress == null) {
overrideAddress = ref.getToAddress();
}
else {
return null; //only allow one primary reference of each type
}
}
}
return null;
return overrideAddress;
}
@Override
public Address getPrimaryCallReference() {
return primaryCallAddress;
}
@Override
@ -89,4 +132,52 @@ public class InstructionPcodeOverride implements PcodeOverride {
}
return fixup;
}
@Override
public void setCallOverrideRefApplied() {
callOverrideApplied = true;
}
@Override
public boolean isCallOverrideRefApplied() {
return callOverrideApplied;
}
@Override
public void setJumpOverrideRefApplied() {
jumpOverrideApplied = true;
}
@Override
public boolean isJumpOverrideRefApplied() {
return jumpOverrideApplied;
}
@Override
public void setCallOtherCallOverrideRefApplied() {
callOtherCallOverrideApplied = true;
}
@Override
public boolean isCallOtherCallOverrideRefApplied() {
return callOtherCallOverrideApplied;
}
@Override
public void setCallOtherJumpOverrideRefApplied() {
callOtherJumpOverrideApplied = true;
}
@Override
public boolean isCallOtherJumpOverrideApplied() {
return callOtherJumpOverrideApplied;
}
@Override
public boolean hasPotentialOverride() {
return !primaryOverridingReferences.isEmpty();
}
}

View file

@ -18,7 +18,7 @@ package ghidra.program.model.pcode;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.RefType;
public interface PcodeOverride {
@ -35,11 +35,12 @@ public interface PcodeOverride {
FlowOverride getFlowOverride();
/**
* Get the primary call reference address (whose {@link SourceType} must be {@link SourceType#USER_DEFINED})
* from the current instruction
* Get the primary overriding reference address of {@link RefType} {@code type} from
* the current instruction
* @param type type of reference
* @return call reference address or null
*/
Address getOverridingCallReference();
Address getOverridingReference(RefType type);
/**
* Get the fall-through override address which may have been
@ -66,4 +67,65 @@ public interface PcodeOverride {
*/
InjectPayload getCallFixup(Address callDestAddr);
/**
* Register that a call override has been applied at the current instruction.
*/
void setCallOverrideRefApplied();
/**
* Returns a boolean indicating whether a call override has been applied at the current instruction
* @return has call override been applied
*/
boolean isCallOverrideRefApplied();
/**
* Register that a jump override has been applied at the current instruction
*/
void setJumpOverrideRefApplied();
/**
* Returns a boolean indicating whether a jump override has been applied at the current instruction
* @return has jump override been applied
*/
boolean isJumpOverrideRefApplied();
/**
* Register that a callother call override has been applied at the current instruction
*/
void setCallOtherCallOverrideRefApplied();
/**
* Returns a boolean indicating whether a callother call override has been applied at the current
* instruction
* @return has callother call override been applied
*/
boolean isCallOtherCallOverrideRefApplied();
/**
* Register that a callother jump override has been applied at the current instruction
*/
void setCallOtherJumpOverrideRefApplied();
/**
* Returns a boolean indicating whether a callother jump override has been applied at the current
* instruction
* @return has callother jump override been applied
*/
boolean isCallOtherJumpOverrideApplied();
/**
* Returns a boolean indicating whether there are any primary overriding references at the current
* instruction
* @return are there primary overriding references
*/
boolean hasPotentialOverride();
/**
*
* Get the primary call reference address from the current instruction
* @return call reference address or null
*/
@Deprecated
Address getPrimaryCallReference();
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,23 +20,82 @@ package ghidra.program.model.symbol;
* flows from one instruction to the next)
*/
public final class FlowType extends RefType {
private final boolean hasFall;
private final boolean hasFall;
private final boolean isCall;
private final boolean isJump;
private final boolean isTeminal;
private final boolean isTerminal;
private final boolean isConditional;
private final boolean isComputed;
private final boolean isOverride;
protected FlowType(byte type, String name, boolean hasFall, boolean isCall, boolean isJump, boolean isTeminal, boolean isComputed, boolean isConditional) {
super(type, name);
this.hasFall = hasFall;
this.isCall = isCall;
this.isJump = isJump;
this.isTeminal = isTeminal;
this.isComputed = isComputed;
this.isConditional = isConditional;
}
protected static class Builder {
private byte type;
private String name;
private boolean hasFall = false;
private boolean isCall = false;
private boolean isJump = false;
private boolean isTerminal = false;
private boolean isComputed = false;
private boolean isConditional = false;
private boolean isOverride = false;
protected Builder(byte type, String name) {
this.type = type;
this.name = name;
}
protected Builder setHasFall() {
this.hasFall = true;
return this;
}
protected Builder setIsCall() {
this.isCall = true;
return this;
}
protected Builder setIsJump() {
this.isJump = true;
return this;
}
protected Builder setIsTerminal() {
this.isTerminal = true;
return this;
}
protected Builder setIsComputed() {
this.isComputed = true;
return this;
}
protected Builder setIsConditional() {
this.isConditional = true;
return this;
}
protected Builder setIsOverride() {
this.isOverride = true;
return this;
}
protected FlowType build() {
return new FlowType(this);
}
}
private FlowType(Builder builder) {
super(builder.type, builder.name);
this.hasFall = builder.hasFall;
this.isCall = builder.isCall;
this.isJump = builder.isJump;
this.isTerminal = builder.isTerminal;
this.isComputed = builder.isComputed;
this.isConditional = builder.isConditional;
this.isOverride = builder.isOverride;
}
@Override
public boolean hasFallthrough() {
@ -71,7 +129,7 @@ public final class FlowType extends RefType {
@Override
public boolean isTerminal() {
return isTeminal;
return isTerminal;
}
@Override
@ -79,4 +137,9 @@ public final class FlowType extends RefType {
return !isConditional;
}
@Override
public boolean isOverride() {
return isOverride;
}
}

View file

@ -53,6 +53,12 @@ public abstract class RefType {
static final byte __CONDITIONAL_CALL_TERMINATOR = 14;
static final byte __COMPUTED_CALL_TERMINATOR = 15;
static final byte __CALL_OVERRIDE_UNCONDITIONAL = 16;
static final byte __JUMP_OVERRIDE_UNCONDITIONAL = 17;
static final byte __CALLOTHER_OVERRIDE_CALL = 18;
static final byte __CALLOTHER_OVERRIDE_JUMP = 19;
// DATA REFERENCE TYPES
static final byte __UNKNOWNDATA = 100;
static final byte __READ = 101;
@ -72,44 +78,58 @@ public abstract class RefType {
static final byte __DYNAMICDATA = 127;
public static final FlowType INVALID =
new FlowType(__INVALID, "INVALID", true, false, false, false, false, false);
new FlowType.Builder(__INVALID, "INVALID").setHasFall().build();
public static final FlowType FLOW =
new FlowType(__UNKNOWNFLOW, "FLOW", true, false, false, false, false, false);
new FlowType.Builder(__UNKNOWNFLOW, "FLOW").setHasFall().build();
public static final FlowType FALL_THROUGH =
new FlowType(__FALL_THROUGH, "FALL_THROUGH", true, false, false, false, false, false);
public static final FlowType UNCONDITIONAL_JUMP = new FlowType(__UNCONDITIONAL_JUMP,
"UNCONDITIONAL_JUMP", false, false, true, false, false, false);
public static final FlowType CONDITIONAL_JUMP =
new FlowType(__CONDITIONAL_JUMP, "CONDITIONAL_JUMP", true, false, true, false, false, true);
public static final FlowType UNCONDITIONAL_CALL = new FlowType(__UNCONDITIONAL_CALL,
"UNCONDITIONAL_CALL", true, true, false, false, false, false);
public static final FlowType CONDITIONAL_CALL =
new FlowType(__CONDITIONAL_CALL, "CONDITIONAL_CALL", true, true, false, false, false, true);
new FlowType.Builder(__FALL_THROUGH, "FALL_THROUGH").setHasFall().build();
public static final FlowType UNCONDITIONAL_JUMP =
new FlowType.Builder(__UNCONDITIONAL_JUMP, "UNCONDITIONAL_JUMP").setIsJump().build();
public static final FlowType CONDITIONAL_JUMP = new FlowType.Builder(__CONDITIONAL_JUMP,
"CONDITIONAL_JUMP").setHasFall().setIsJump().setIsConditional().build();
public static final FlowType UNCONDITIONAL_CALL = new FlowType.Builder(__UNCONDITIONAL_CALL,
"UNCONDITIONAL_CALL").setHasFall().setIsCall().build();
public static final FlowType CONDITIONAL_CALL = new FlowType.Builder(__CONDITIONAL_CALL,
"CONDITIONAL CALL").setHasFall().setIsCall().setIsConditional().build();
public static final FlowType TERMINATOR =
new FlowType(__TERMINATOR, "TERMINATOR", false, false, false, true, false, false);
new FlowType.Builder(__TERMINATOR, "TERMINATOR").setIsTerminal().build();
public static final FlowType COMPUTED_JUMP =
new FlowType(__COMPUTED_JUMP, "COMPUTED_JUMP", false, false, true, false, true, false);
public static final FlowType CONDITIONAL_TERMINATOR = new FlowType(__CONDITIONAL_TERMINATOR,
"CONDITIONAL_TERMINATOR", true, false, false, true, false, true);
public static final FlowType COMPUTED_CALL =
new FlowType(__COMPUTED_CALL, "COMPUTED_CALL", true, true, false, false, true, false);
public static final FlowType CALL_TERMINATOR =
new FlowType(__CALL_TERMINATOR, "CALL_TERMINATOR", false, true, false, true, false, false);
public static final FlowType COMPUTED_CALL_TERMINATOR = new FlowType(__COMPUTED_CALL_TERMINATOR,
"COMPUTED_CALL_TERMINATOR", false, true, false, true, true, false);
new FlowType.Builder(__COMPUTED_JUMP, "COMPUTED_JUMP").setIsJump().setIsComputed().build();
public static final FlowType CONDITIONAL_TERMINATOR =
new FlowType.Builder(__CONDITIONAL_TERMINATOR,
"CONDITIONAL_TERMINATOR").setHasFall().setIsTerminal().setIsConditional().build();
public static final FlowType COMPUTED_CALL = new FlowType.Builder(__COMPUTED_CALL,
"COMPUTED_CALL").setHasFall().setIsCall().setIsComputed().build();
public static final FlowType CALL_TERMINATOR = new FlowType.Builder(__CALL_TERMINATOR,
"CALL_TERMINATOR").setIsCall().setIsTerminal().build();
public static final FlowType COMPUTED_CALL_TERMINATOR =
new FlowType.Builder(__COMPUTED_CALL_TERMINATOR,
"COMPUTED_CALL_TERMINATOR").setIsCall().setIsTerminal().setIsComputed().build();
public static final FlowType CONDITIONAL_CALL_TERMINATOR =
new FlowType(__CONDITIONAL_CALL_TERMINATOR, "CONDITIONAL_CALL_TERMINATOR", false, true,
false, true, false, true);
public static final FlowType CONDITIONAL_COMPUTED_CALL =
new FlowType(__CONDITIONAL_COMPUTED_CALL, "CONDITIONAL_COMPUTED_CALL", true, true, false,
false, true, true);
public static final FlowType CONDITIONAL_COMPUTED_JUMP =
new FlowType(__CONDITIONAL_COMPUTED_JUMP, "CONDITIONAL_COMPUTED_JUMP", true, false, true,
false, true, true);
public static final FlowType JUMP_TERMINATOR =
new FlowType(__JUMP_TERMINATOR, "JUMP TERMINATOR", false, false, true, true, false, false);
new FlowType.Builder(__CONDITIONAL_CALL_TERMINATOR,
"CONDITIONAL_CALL_TERMINATOR").setIsCall().setIsTerminal().setIsConditional().build();
public static final FlowType CONDITIONAL_COMPUTED_CALL = new FlowType.Builder(
__CONDITIONAL_COMPUTED_CALL,
"CONDITIONAL_COMPUTED_CALL").setHasFall().setIsCall().setIsComputed().setIsConditional().build();
public static final FlowType CONDITIONAL_COMPUTED_JUMP = new FlowType.Builder(
__CONDITIONAL_COMPUTED_JUMP,
"CONDITIONAL_COMPUTED_JUMP").setHasFall().setIsJump().setIsComputed().setIsConditional().build();
public static final FlowType JUMP_TERMINATOR = new FlowType.Builder(__JUMP_TERMINATOR,
"JUMP_TERMINATOR").setIsJump().setIsTerminal().build();
public static final FlowType INDIRECTION =
new FlowType(__INDIRECTION, "INDIRECTION", false, false, false, false, false, false);
new FlowType.Builder(__INDIRECTION, "INDIRECTION").build();
public static final FlowType CALL_OVERRIDE_UNCONDITIONAL =
new FlowType.Builder(__CALL_OVERRIDE_UNCONDITIONAL,
"CALL_OVERRIDE_UNCONDITIONAL").setHasFall().setIsCall().setIsOverride().build();
public static final FlowType JUMP_OVERRIDE_UNCONDITIONAL =
new FlowType.Builder(__JUMP_OVERRIDE_UNCONDITIONAL,
"JUMP_OVERRIDE_UNCONDITIONAL").setIsJump().setIsOverride().build();
public static final FlowType CALLOTHER_OVERRIDE_CALL =
new FlowType.Builder(__CALLOTHER_OVERRIDE_CALL,
"CALLOTHER_OVERRIDE_CALL").setHasFall().setIsCall().setIsOverride().build();
public static final FlowType CALLOTHER_OVERRIDE_JUMP =
new FlowType.Builder(__CALLOTHER_OVERRIDE_JUMP,
"CALLOTHER_OVERRIDE_JUMP").setIsJump().setIsOverride().build();
/**
* Reference type is unknown.
@ -272,7 +292,7 @@ public abstract class RefType {
}
/**
* Returns true if the flow is a conditiona call or jump.
* Returns true if the flow is a conditional call or jump.
*/
public boolean isConditional() {
return false;
@ -292,6 +312,14 @@ public abstract class RefType {
return false;
}
/**
*
* @return true precisely when the reference is an overriding reference
*/
public boolean isOverride() {
return false;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/

View file

@ -77,6 +77,14 @@ public class RefTypeFactory {
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.STACK_READ.getValue(), RefType.STACK_READ);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.STACK_WRITE.getValue(), RefType.STACK_WRITE);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.EXTERNAL_REF.getValue(), RefType.EXTERNAL_REF);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.__CALL_OVERRIDE_UNCONDITIONAL,
RefType.CALL_OVERRIDE_UNCONDITIONAL);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.__JUMP_OVERRIDE_UNCONDITIONAL,
RefType.JUMP_OVERRIDE_UNCONDITIONAL);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.__CALLOTHER_OVERRIDE_CALL,
RefType.CALLOTHER_OVERRIDE_CALL);
REFTYPE_LOOKUP_BY_TYPE_MAP.put(RefType.__CALLOTHER_OVERRIDE_JUMP,
RefType.CALLOTHER_OVERRIDE_JUMP);
}
private static RefType[] memoryRefTypes = new RefType[] { RefType.INDIRECTION,
@ -84,7 +92,9 @@ public class RefTypeFactory {
RefType.CONDITIONAL_JUMP, RefType.UNCONDITIONAL_CALL, RefType.UNCONDITIONAL_JUMP,
RefType.CONDITIONAL_COMPUTED_CALL, RefType.CONDITIONAL_COMPUTED_JUMP, RefType.PARAM,
RefType.DATA, RefType.DATA_IND, RefType.READ, RefType.READ_IND, RefType.WRITE,
RefType.WRITE_IND, RefType.READ_WRITE, RefType.READ_WRITE_IND };
RefType.WRITE_IND, RefType.READ_WRITE, RefType.READ_WRITE_IND,
RefType.CALL_OVERRIDE_UNCONDITIONAL, RefType.JUMP_OVERRIDE_UNCONDITIONAL,
RefType.CALLOTHER_OVERRIDE_CALL, RefType.CALLOTHER_OVERRIDE_JUMP };
private static HashSet<RefType> validMemRefTypes = new HashSet<>();
static {
@ -99,13 +109,13 @@ public class RefTypeFactory {
private static RefType[] dataRefTypes = new RefType[] { RefType.DATA, RefType.PARAM,
RefType.READ, RefType.WRITE, RefType.READ_WRITE, };
private static RefType[] extRefTypes = new RefType[] {
// TODO: RefType.EXTERNAL_REF should be deprecated and RefType.DATA taking its place
RefType.COMPUTED_CALL, RefType.COMPUTED_JUMP, RefType.CONDITIONAL_CALL,
RefType.CONDITIONAL_JUMP, RefType.UNCONDITIONAL_CALL, RefType.UNCONDITIONAL_JUMP,
RefType.CONDITIONAL_COMPUTED_CALL, RefType.CONDITIONAL_COMPUTED_JUMP, RefType.DATA,
RefType.DATA_IND, RefType.READ, RefType.READ_IND, RefType.WRITE, RefType.WRITE_IND,
RefType.READ_WRITE, RefType.READ_WRITE_IND };
private static RefType[] extRefTypes =
new RefType[] { RefType.COMPUTED_CALL, RefType.COMPUTED_JUMP, RefType.CONDITIONAL_CALL,
RefType.CONDITIONAL_JUMP, RefType.UNCONDITIONAL_CALL, RefType.UNCONDITIONAL_JUMP,
RefType.CONDITIONAL_COMPUTED_CALL, RefType.CONDITIONAL_COMPUTED_JUMP, RefType.DATA,
RefType.DATA_IND, RefType.READ, RefType.READ_IND, RefType.WRITE, RefType.WRITE_IND,
RefType.READ_WRITE, RefType.READ_WRITE_IND, RefType.CALL_OVERRIDE_UNCONDITIONAL,
RefType.CALLOTHER_OVERRIDE_CALL, RefType.CALLOTHER_OVERRIDE_JUMP };
public static RefType[] getMemoryRefTypes() {
return memoryRefTypes;