mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
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:
parent
01c43efb2c
commit
df983e7bba
9 changed files with 1085 additions and 115 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue