GP-1987 Using injected pcode from segment and all pcode userops during

constant propagation
This commit is contained in:
emteere
2022-05-18 13:49:47 +00:00
parent 49a426eb3f
commit 4034568165

View File

@@ -91,10 +91,14 @@ public class SymbolicPropogator {
// Cache instructions looked up by containing // Cache instructions looked up by containing
Map<Address, Instruction> instructionContainingCache = new LRUMap<>(LRU_SIZE); Map<Address, Instruction> instructionContainingCache = new LRUMap<>(LRU_SIZE);
// cache for pcode callother injection payloads
HashMap<Long, InjectPayload> injectPayloadCache = new HashMap<Long, InjectPayload>();
public SymbolicPropogator(Program program) { public SymbolicPropogator(Program program) {
this.program = program; this.program = program;
Language language = program.getLanguage(); Language language = program.getLanguage();
programContext = new ProgramContextImpl(language); programContext = new ProgramContextImpl(language);
spaceContext = new ProgramContextImpl(language); spaceContext = new ProgramContextImpl(language);
@@ -792,16 +796,17 @@ public class SymbolicPropogator {
mustClearAll = pcodeIndex < mustClearAllUntil_PcodeIndex; mustClearAll = pcodeIndex < mustClearAllUntil_PcodeIndex;
ptype = ops[pcodeIndex].getOpcode(); PcodeOp pcodeOp = ops[pcodeIndex];
Varnode out = ops[pcodeIndex].getOutput(); ptype = pcodeOp.getOpcode();
Varnode[] in = ops[pcodeIndex].getInputs(); Varnode out = pcodeOp.getOutput();
Varnode[] in = pcodeOp.getInputs();
Varnode val1, val2, val3, result; Varnode val1, val2, val3, result;
long lval1, lval2; long lval1, lval2;
long lresult; long lresult;
Varnode vt; Varnode vt;
if (debug) { if (debug) {
Msg.info(this, " " + ops[pcodeIndex]); Msg.info(this, " " + pcodeOp);
} }
try { try {
@@ -974,12 +979,12 @@ public class SymbolicPropogator {
// for callother, could be an interrupt, need to look at it like a call // for callother, could be an interrupt, need to look at it like a call
case PcodeOp.CALLOTHER: case PcodeOp.CALLOTHER:
// HACK ALERT! PcodeOp[] callOtherPcode = doCallOtherPcodeInjection(instruction, in, out);
// if this is a segment op, emulate the segmenting for now.
String opName = this.program.getLanguage() if (callOtherPcode != null) {
.getUserDefinedOpName((int) in[0].getOffset()); ops = injectPcode(ops, pcodeIndex, callOtherPcode);
if (opName.equals("segment") && in.length > 2) { pcodeIndex = -1;
checkSegmented(out, in[1], in[2], mustClearAll); injected = true;
} }
else if (out != null) { else if (out != null) {
// clear out settings for the output from call other. // clear out settings for the output from call other.
@@ -1636,27 +1641,73 @@ public class SymbolicPropogator {
return currentPcode; return currentPcode;
} }
private void checkSegmented(Varnode out, Varnode in1, Varnode in2, boolean mustClearAll) /**
throws NotFoundException { * Check for pcode replacement for a callother pcode op
Varnode vval1 = context.getValue(in1, evaluator); *
Varnode vval2 = context.getValue(in2, evaluator); * @param instr instruction whose pcodeop we might replace
if (vval1.isConstant() && vval2.isConstant()) { * @param ins input varnodes to callother pcodeop, ins[0] is callother nameindex
int bitsize = program.getAddressFactory().getDefaultAddressSpace().getSize(); * @param out output varnode for pcodeop
long segBase; * @return pcode that should replace callother, null otherwise
if (bitsize > 24) { *
segBase = context.getConstant(vval1, evaluator) << 16; * @throws NotFoundException
} */
else if (bitsize == 24) { private PcodeOp[] doCallOtherPcodeInjection(Instruction instr, Varnode ins[], Varnode out) throws NotFoundException {
segBase = context.getConstant(vval1, evaluator) << 8; Program prog = instr.getProgram();
}
else { PcodeInjectLibrary snippetLibrary = prog.getCompilerSpec().getPcodeInjectLibrary();
segBase = context.getConstant(vval1, evaluator) << 4; InjectPayload payload = findPcodeInjection(prog, snippetLibrary, ins[0].getOffset());
} // no injection defined for this call-other pcodeop
vval1 = context.createConstantVarnode(segBase, out.getSize()); if (payload == null) {
vval2 = context.createConstantVarnode(vval2.getOffset(), out.getSize()); return null;
Varnode segmentedValue = context.add(vval1, vval2, evaluator);
context.putValue(out, segmentedValue, mustClearAll);
} }
ArrayList<Varnode> inputs = new ArrayList<Varnode>();
for (int i = 1; i < ins.length; i++) {
Varnode vval = context.getValue(ins[i], evaluator);
if (!vval.isConstant()) {
return null;
}
inputs.add(vval);
}
InjectContext con = snippetLibrary.buildInjectContext();
con.baseAddr = instr.getMinAddress();
con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset());
con.callAddr = null;
con.refAddr = con.callAddr;
con.inputlist = inputs;
con.output = new ArrayList<Varnode>();
con.output.add(out);
return payload.getPcode(prog, con);
}
private InjectPayload findPcodeInjection(Program prog, PcodeInjectLibrary snippetLibrary, long callOtherIndex) {
InjectPayload payload = (InjectPayload) injectPayloadCache.get(callOtherIndex);
// has a payload value for the pcode callother index
if (payload != null) {
return payload;
}
// value null, if contains the key, then already looked up
if (injectPayloadCache.containsKey(callOtherIndex)) {
return null;
}
String opName = prog.getLanguage().getUserDefinedOpName((int) callOtherIndex);
// segment is special named injection
if ("segment".equals(opName)) {
payload =
snippetLibrary.getPayload(InjectPayload.EXECUTABLEPCODE_TYPE, "segment_pcode");
}
else {
payload = snippetLibrary.getPayload(InjectPayload.CALLOTHERFIXUP_TYPE, opName);
}
// save payload in cache for next lookup
injectPayloadCache.put(callOtherIndex, payload);
return payload;
} }
/** /**