mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-1987 Using injected pcode from segment and all pcode userops during
constant propagation
This commit is contained in:
@@ -90,11 +90,15 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user