GP-2586 Exceptions for injection error conditions

This commit is contained in:
caheckman 2022-09-28 17:19:55 -04:00
parent dc927fc7be
commit e996440c77
9 changed files with 240 additions and 206 deletions

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.app.plugin.core.debug.stack; package ghidra.app.plugin.core.debug.stack;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.app.decompiler.DecompInterface; import ghidra.app.decompiler.DecompInterface;
@ -28,8 +29,10 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.exception.InvalidInputException; import ghidra.util.exception.InvalidInputException;
import ghidra.util.exception.NotFoundException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/** /**
@ -68,8 +71,8 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
CompilerSpec cSpec = program.getCompilerSpec(); CompilerSpec cSpec = program.getCompilerSpec();
SleighLanguage language = (SleighLanguage) cSpec.getLanguage(); SleighLanguage language = (SleighLanguage) cSpec.getLanguage();
SymPcodeArithmetic arithmetic = new SymPcodeArithmetic(cSpec); SymPcodeArithmetic arithmetic = new SymPcodeArithmetic(cSpec);
return new SymPcodeExecutor(program, cSpec, language, arithmetic, state, reason, return new SymPcodeExecutor(program, cSpec, language, arithmetic, state, reason, warnings,
warnings, monitor); monitor);
} }
private final Program program; private final Program program;
@ -93,8 +96,7 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
} }
@Override @Override
public void executeCallother(PcodeOp op, PcodeFrame frame, public void executeCallother(PcodeOp op, PcodeFrame frame, PcodeUseropLibrary<Sym> library) {
PcodeUseropLibrary<Sym> library) {
// Do nothing // Do nothing
// TODO: Is there a way to know if a userop affects the stack? // TODO: Is there a way to know if a userop affects the stack?
} }
@ -120,8 +122,7 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
} }
int extrapop = convention.getExtrapop(); int extrapop = convention.getExtrapop();
if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) { if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) {
throw new PcodeExecutionException( throw new PcodeExecutionException("Cannot get stack change for function " + function);
"Cannot get stack change for function " + function);
} }
if (function.isStackPurgeSizeValid()) { if (function.isStackPurgeSizeValid()) {
return extrapop + function.getStackPurgeSize(); return extrapop + function.getStackPurgeSize();
@ -151,9 +152,15 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
} }
String fixupName = callee.getCallFixup(); String fixupName = callee.getCallFixup();
if (fixupName != null && !"".equals(fixupName)) { if (fixupName != null && !"".equals(fixupName)) {
PcodeProgram snippet = PcodeProgram snippet;
PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE); try {
execute(snippet, library); snippet = PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE);
execute(snippet, library);
}
catch (MemoryAccessException | UnknownInstructionException | NotFoundException
| IOException e) {
throw new PcodeExecutionException("Issue executing callee fixup: ", e);
}
return; return;
} }
int change = computeStackChange(callee); int change = computeStackChange(callee);

View file

@ -15,6 +15,7 @@
*/ */
package ghidra.pcode.exec; package ghidra.pcode.exec;
import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
@ -25,7 +26,9 @@ import ghidra.pcodeCPort.slghsymbol.UserOpSymbol;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.NotFoundException;
/** /**
* A p-code program to be executed by a {@link PcodeExecutor} * A p-code program to be executed by a {@link PcodeExecutor}
@ -112,8 +115,7 @@ public class PcodeProgram {
throw new IllegalArgumentException("Instruction must be parsed using Sleigh"); throw new IllegalArgumentException("Instruction must be parsed using Sleigh");
} }
PcodeOp[] pcode = instruction.getPcode(includeOverrides); PcodeOp[] pcode = instruction.getPcode(includeOverrides);
return new PcodeProgram((SleighLanguage) language, List.of(pcode), return new PcodeProgram((SleighLanguage) language, List.of(pcode), Map.of());
Map.of());
} }
/** /**
@ -123,8 +125,14 @@ public class PcodeProgram {
* @param name the name of the snippet * @param name the name of the snippet
* @param type the type of the snippet * @param type the type of the snippet
* @return the p-code program * @return the p-code program
* @throws MemoryAccessException for problems establishing the injection context
* @throws IOException for problems while emitting the injection p-code
* @throws UnknownInstructionException if there is no underlying instruction being injected
* @throws NotFoundException if an expected aspect of the injection is not present in context
*/ */
public static PcodeProgram fromInject(Program program, String name, int type) { public static PcodeProgram fromInject(Program program, String name, int type)
throws MemoryAccessException, UnknownInstructionException, NotFoundException,
IOException {
PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary(); PcodeInjectLibrary library = program.getCompilerSpec().getPcodeInjectLibrary();
InjectContext ctx = library.buildInjectContext(); InjectContext ctx = library.buildInjectContext();
InjectPayload payload = library.getPayload(type, name); InjectPayload payload = library.getPayload(type, name);

View file

@ -15,9 +15,8 @@
*/ */
package ghidra.program.util; package ghidra.program.util;
import java.util.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*;
import org.apache.commons.collections4.map.LRUMap; import org.apache.commons.collections4.map.LRUMap;
@ -1088,7 +1087,8 @@ public class SymbolicPropogator {
// if return value is a location, give evaluator a chance to check the value // if return value is a location, give evaluator a chance to check the value
try { try {
val1 = vContext.getValue(in[0], evaluator); val1 = vContext.getValue(in[0], evaluator);
if (evaluator != null && evaluator.evaluateReturn(val1, vContext, instruction)) { if (evaluator != null &&
evaluator.evaluateReturn(val1, vContext, instruction)) {
canceled = true; canceled = true;
return null; return null;
} }
@ -1446,9 +1446,9 @@ public class SymbolicPropogator {
Varnode vt; Varnode vt;
if (!context.isExternalSpace(val1.getSpace())) { if (!context.isExternalSpace(val1.getSpace())) {
long lval = vContext.getConstant(val1, evaluator); long lval = vContext.getConstant(val1, evaluator);
vt = vContext.getVarnode(minInstrAddress.getAddressSpace().getSpaceID(), vt = vContext.getVarnode(minInstrAddress.getAddressSpace().getSpaceID(), lval, 0);
lval, 0); }
} else { else {
vt = val1; vt = val1;
} }
return vt; return vt;
@ -1602,7 +1602,13 @@ public class SymbolicPropogator {
con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset()); con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset());
con.callAddr = func.getEntryPoint(); con.callAddr = func.getEntryPoint();
con.refAddr = con.callAddr; con.refAddr = con.callAddr;
return payload.getPcode(prog, con); try {
return payload.getPcode(prog, con);
}
catch (Exception e) {
Msg.warn(this, e.getMessage());
}
return null;
} }
private PcodeOp[] checkForUponReturnCallMechanismInjection(Program prog, Function func, private PcodeOp[] checkForUponReturnCallMechanismInjection(Program prog, Function func,
@ -1629,7 +1635,13 @@ public class SymbolicPropogator {
con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset()); con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset());
con.callAddr = target; con.callAddr = target;
con.refAddr = con.callAddr; con.refAddr = con.callAddr;
return payload.getPcode(prog, con); try {
return payload.getPcode(prog, con);
}
catch (Exception e) {
Msg.warn(this, e.getMessage());
}
return null;
} }
private PcodeOp[] injectPcode(PcodeOp[] currentPcode, int pcodeIndex, PcodeOp[] replacePcode) { private PcodeOp[] injectPcode(PcodeOp[] currentPcode, int pcodeIndex, PcodeOp[] replacePcode) {
@ -1662,7 +1674,8 @@ public class SymbolicPropogator {
* *
* @throws NotFoundException * @throws NotFoundException
*/ */
private PcodeOp[] doCallOtherPcodeInjection(Instruction instr, Varnode ins[], Varnode out) throws NotFoundException { private PcodeOp[] doCallOtherPcodeInjection(Instruction instr, Varnode ins[], Varnode out)
throws NotFoundException {
Program prog = instr.getProgram(); Program prog = instr.getProgram();
PcodeInjectLibrary snippetLibrary = prog.getCompilerSpec().getPcodeInjectLibrary(); PcodeInjectLibrary snippetLibrary = prog.getCompilerSpec().getPcodeInjectLibrary();
@ -1689,10 +1702,17 @@ public class SymbolicPropogator {
con.inputlist = inputs; con.inputlist = inputs;
con.output = new ArrayList<Varnode>(); con.output = new ArrayList<Varnode>();
con.output.add(out); con.output.add(out);
return payload.getPcode(prog, con); try {
return payload.getPcode(prog, con);
}
catch (Exception e) {
Msg.warn(this, e.getMessage());
}
return null;
} }
private InjectPayload findPcodeInjection(Program prog, PcodeInjectLibrary snippetLibrary, long callOtherIndex) { private InjectPayload findPcodeInjection(Program prog, PcodeInjectLibrary snippetLibrary,
long callOtherIndex) {
InjectPayload payload = injectPayloadCache.get(callOtherIndex); InjectPayload payload = injectPayloadCache.get(callOtherIndex);
// has a payload value for the pcode callother index // has a payload value for the pcode callother index

View file

@ -1154,6 +1154,8 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO
bool startbasic = op->isBlockStart(); bool startbasic = op->isBlockStart();
++iter; // Now points to first op in the injection ++iter; // Now points to first op in the injection
if (iter == obank.endDead())
throw LowlevelError("Empty injection: " + payload->getName());
PcodeOp *firstop = *iter; PcodeOp *firstop = *iter;
bool isfallthru = true; bool isfallthru = true;
PcodeOp *lastop = xrefControlFlow(iter,startbasic,isfallthru,fc); PcodeOp *lastop = xrefControlFlow(iter,startbasic,isfallthru,fc);

View file

@ -51,13 +51,13 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const
PackedDecode decoder(ghidra); PackedDecode decoder(ghidra);
try { try {
if (!ghidra->getPcodeInject(name,type,con,decoder)) if (!ghidra->getPcodeInject(name,type,con,decoder))
throw LowlevelError("Could not retrieve pcode snippet: "+name); throw LowlevelError("Could not retrieve injection: "+name);
} }
catch(JavaError &err) { catch(JavaError &err) {
throw LowlevelError("Error getting pcode snippet: " + err.explain); throw LowlevelError("Injection error: " + err.explain);
} }
catch(DecoderError &err) { catch(DecoderError &err) {
throw LowlevelError("Error in pcode snippet xml: "+err.explain); throw LowlevelError("Error decoding injection: "+err.explain);
} }
uint4 elemId = decoder.openElement(); uint4 elemId = decoder.openElement();
Address addr = Address::decode(decoder); Address addr = Address::decode(decoder);

View file

@ -35,6 +35,7 @@ import ghidra.program.model.pcode.*;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.UndefinedFunction; import ghidra.util.UndefinedFunction;
import ghidra.util.exception.NotFoundException;
import ghidra.util.exception.UsrException; import ghidra.util.exception.UsrException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -139,6 +140,8 @@ public class DecompileCallback {
/** /**
* Get bytes from the program's memory image. * Get bytes from the program's memory image.
* Any exceptions are caught, resulting in null being returned. The decompiler treats a null
* as a DataUnavailError but will continue to process the function.
* @param addr is the starting address to fetch bytes from * @param addr is the starting address to fetch bytes from
* @param size is the number of bytes to fetch * @param size is the number of bytes to fetch
* @return the bytes matching the query or null if the query can't be met * @return the bytes matching the query or null if the query can't be met
@ -199,7 +202,9 @@ public class DecompileCallback {
} }
/** /**
* Generate p-code ops for the instruction at the given address * Generate p-code ops for the instruction at the given address.
* Any exceptions are caught, resulting in an empty result. The decompiler interprets these
* as a BadDataError, but will continue to process the function.
* @param addr is the given address * @param addr is the given address
* @param resultEncoder will contain the generated p-code ops * @param resultEncoder will contain the generated p-code ops
*/ */
@ -234,7 +239,8 @@ public class DecompileCallback {
Msg.error(this, Msg.error(this,
"Decompiling " + funcEntry + ", pcode error at " + addr + ": " + e.getMessage(), e); "Decompiling " + funcEntry + ", pcode error at " + addr + ": " + e.getMessage(), e);
} }
resultEncoder.clear(); // If we reach here, an exception was thrown
resultEncoder.clear(); // Make sure the result is empty
} }
/** /**
@ -275,73 +281,62 @@ public class DecompileCallback {
* @param paramDecoder contains the context * @param paramDecoder contains the context
* @param type is the type of payload * @param type is the type of payload
* @param resultEncoder will contain the generated p-code ops * @param resultEncoder will contain the generated p-code ops
* @throws DecoderException for problems decoding the injection context
* @throws UnknownInstructionException if there is no instruction at the injection site
* @throws IOException for errors encoding the injection result
* @throws NotFoundException if an expected aspect of the injection is not present in context
* @throws MemoryAccessException for problems establishing the injection context
*/ */
public void getPcodeInject(String nm, Decoder paramDecoder, int type, Encoder resultEncoder) { public void getPcodeInject(String nm, Decoder paramDecoder, int type, Encoder resultEncoder)
throws DecoderException, UnknownInstructionException, IOException,
MemoryAccessException, NotFoundException {
PcodeInjectLibrary snippetLibrary = pcodecompilerspec.getPcodeInjectLibrary(); PcodeInjectLibrary snippetLibrary = pcodecompilerspec.getPcodeInjectLibrary();
InjectPayload payload = snippetLibrary.getPayload(type, nm); InjectPayload payload = snippetLibrary.getPayload(type, nm);
if (payload == null) { if (payload == null) {
Msg.warn(this, "Decompiling " + funcEntry + ", no pcode inject with name: " + nm); throw new NotFoundException("No p-code injection with name: " + nm);
return; // No fixup associated with this name
} }
InjectContext con = snippetLibrary.buildInjectContext(); InjectContext con = snippetLibrary.buildInjectContext();
PcodeOp[] pcode; PcodeOp[] pcode;
try { con.decode(paramDecoder);
con.decode(paramDecoder); int fallThruOffset;
if (payload.getType() == InjectPayload.EXECUTABLEPCODE_TYPE) {
// Executable p-code has no underlying instruction address and
// does (should) not use the inst_start, inst_next symbols that need
// to know about it.
fallThruOffset = 4; // Provide a dummy length
} }
catch (DecoderException e) { else {
Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); Instruction instr = getInstruction(con.baseAddr);
return; if (instr == null) {
} Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " +
try { con.baseAddr + ": instruction not found");
int fallThruOffset; return;
if (payload.getType() == InjectPayload.EXECUTABLEPCODE_TYPE) {
// Executable p-code has no underlying instruction address and
// does (should) not use the inst_start, inst_next symbols that need
// to know about it.
fallThruOffset = 4; // Provide a dummy length
} }
else {
Instruction instr = getInstruction(con.baseAddr);
if (instr == null) {
Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " +
con.baseAddr + ": instruction not found");
return;
}
// get next inst addr for inst_next pcode variable // get next inst addr for inst_next pcode variable
fallThruOffset = instr.getDefaultFallThroughOffset(); fallThruOffset = instr.getDefaultFallThroughOffset();
con.nextAddr = con.baseAddr.add(fallThruOffset); con.nextAddr = con.baseAddr.add(fallThruOffset);
con.refAddr = null; con.refAddr = null;
for (Reference ref : program.getReferenceManager() for (Reference ref : program.getReferenceManager().getReferencesFrom(con.baseAddr)) {
.getReferencesFrom(con.baseAddr)) { if (ref.isPrimary() && ref.getReferenceType().isCall()) {
if (ref.isPrimary() && ref.getReferenceType().isCall()) { con.refAddr = ref.getToAddress();
con.refAddr = ref.getToAddress(); break;
break;
}
} }
} }
pcode = payload.getPcode(program, con); }
if (pcode == null) { pcode = payload.getPcode(program, con);
return; // Return without result, which should let the decompiler exit gracefully if (pcode == null) {
} return; // Return without result, which should let the decompiler exit gracefully
encodeInstruction(resultEncoder, con.baseAddr, pcode, fallThruOffset, }
encodeInstruction(resultEncoder, con.baseAddr, pcode, fallThruOffset,
payload.getParamShift(), addrfactory);
if (debug != null) {
XmlEncode xmlEncode = new XmlEncode();
encodeInstruction(xmlEncode, con.baseAddr, pcode, fallThruOffset,
payload.getParamShift(), addrfactory); payload.getParamShift(), addrfactory);
if (debug != null) { debug.addInject(con.baseAddr, nm, type, xmlEncode.toString());
XmlEncode xmlEncode = new XmlEncode();
encodeInstruction(xmlEncode, con.baseAddr, pcode, fallThruOffset,
payload.getParamShift(), addrfactory);
debug.addInject(con.baseAddr, nm, type, xmlEncode.toString());
}
}
catch (UnknownInstructionException e) {
Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr +
": " + e.getMessage());
}
catch (Exception e) {
Msg.error(this, "Decompiling " + funcEntry + ", pcode inject error at " + con.baseAddr +
": " + e.getMessage(), e);
} }
} }
@ -429,26 +424,19 @@ public class DecompileCallback {
* Return the first symbol name at the given address * Return the first symbol name at the given address
* @param addr is the given address * @param addr is the given address
* @return the symbol or null if no symbol is found * @return the symbol or null if no symbol is found
* @throws IOException for errors trying to encode the symbol
*/ */
public String getCodeLabel(Address addr) { public String getCodeLabel(Address addr) throws IOException {
try { Symbol sym = program.getSymbolTable().getPrimarySymbol(addr);
Symbol sym = program.getSymbolTable().getPrimarySymbol(addr); if (sym == null) {
if (sym == null) { return null;
return null; }
} String res = getSymbolName(sym);
String res = getSymbolName(sym); if (debug != null) {
if (debug != null) { debug.getCodeSymbol(addr, sym.getID(), res, sym.getParentNamespace());
debug.getCodeSymbol(addr, sym.getID(), res, sym.getParentNamespace()); }
}
return res; return res;
}
catch (Exception e) {
Msg.error(this,
"Decompiling " + funcEntry + ", error while accessing symbol: " + e.getMessage(),
e);
}
return null;
} }
private String getSymbolName(Symbol sym) { private String getSymbolName(Symbol sym) {
@ -658,100 +646,86 @@ public class DecompileCallback {
* *
* @param addr is the given address * @param addr is the given address
* @param resultEncoder is where to write encoded description * @param resultEncoder is where to write encoded description
* @throws IOException for errors encoding the result
*/ */
public void getMappedSymbols(Address addr, Encoder resultEncoder) { public void getMappedSymbols(Address addr, Encoder resultEncoder) throws IOException {
if (addr == Address.NO_ADDRESS) { if (addr == Address.NO_ADDRESS) {
// Unknown spaces may result from "spacebase" registers defined in cspec // Unknown spaces may result from "spacebase" registers defined in cspec
return; return;
} }
try { Object obj = lookupSymbol(addr);
Object obj = lookupSymbol(addr); if (obj instanceof Function) {
if (obj instanceof Function) { boolean includeDefaults = addr.equals(funcEntry);
boolean includeDefaults = addr.equals(funcEntry); encodeFunction(resultEncoder, (Function) obj, addr, includeDefaults);
encodeFunction(resultEncoder, (Function) obj, addr, includeDefaults);
}
else if (obj instanceof Data) {
if (!encodeData(resultEncoder, (Data) obj)) {
encodeHole(resultEncoder, addr);
}
}
else if (obj instanceof ExternalReference) {
encodeExternalRef(resultEncoder, addr, (ExternalReference) obj);
}
else if (obj instanceof Symbol) {
encodeLabel(resultEncoder, (Symbol) obj, addr);
}
else {
encodeHole(resultEncoder, addr); // There is a hole, describe the extent of the hole
}
return;
} }
catch (Exception e) { else if (obj instanceof Data) {
Msg.error(this, "Decompiling " + funcEntry + ", mapped symbol error for " + addr + if (!encodeData(resultEncoder, (Data) obj)) {
": " + e.getMessage(), e); encodeHole(resultEncoder, addr);
}
}
else if (obj instanceof ExternalReference) {
encodeExternalRef(resultEncoder, addr, (ExternalReference) obj);
}
else if (obj instanceof Symbol) {
encodeLabel(resultEncoder, (Symbol) obj, addr);
}
else {
encodeHole(resultEncoder, addr); // There is a hole, describe the extent of the hole
} }
return;
} }
/** /**
* Get a description of an external reference at the given address * Get a description of an external reference at the given address
* @param addr is the given address * @param addr is the given address
* @param resultEncoder will contain the resulting description * @param resultEncoder will contain the resulting description
* @throws IOException for errors encoding the result
*/ */
public void getExternalRef(Address addr, Encoder resultEncoder) { public void getExternalRef(Address addr, Encoder resultEncoder) throws IOException {
try { Function func = null;
Function func = null; if (cachedFunction != null && cachedFunction.getEntryPoint().equals(addr)) {
if (cachedFunction != null && cachedFunction.getEntryPoint().equals(addr)) { func = cachedFunction;
func = cachedFunction; }
else {
ExternalReference extRef = getExternalReference(addr);
if (extRef != null) {
func = listing.getFunctionAt(extRef.getToAddress());
if (func == null) {
Symbol symbol = extRef.getExternalLocation().getSymbol();
long extId;
if (symbol != null) {
extId = symbol.getID();
}
else {
extId = program.getSymbolTable().getDynamicSymbolID(addr);
}
HighSymbol shellSymbol =
new HighFunctionShellSymbol(extId, extRef.getLabel(), addr, dtmanage);
encodeResult(resultEncoder, shellSymbol, null);
return;
}
} }
else { else {
ExternalReference extRef = getExternalReference(addr); func = listing.getFunctionAt(addr);
if (extRef != null) {
func = listing.getFunctionAt(extRef.getToAddress());
if (func == null) {
Symbol symbol = extRef.getExternalLocation().getSymbol();
long extId;
if (symbol != null) {
extId = symbol.getID();
}
else {
extId = program.getSymbolTable().getDynamicSymbolID(addr);
}
HighSymbol shellSymbol =
new HighFunctionShellSymbol(extId, extRef.getLabel(), addr, dtmanage);
encodeResult(resultEncoder, shellSymbol, null);
return;
}
}
else {
func = listing.getFunctionAt(addr);
}
} }
if (func == null) { }
// Its conceivable we could have external data, but we aren't currently checking for it if (func == null) {
return; // Its conceivable we could have external data, but we aren't currently checking for it
}
HighFunction hfunc = new HighFunction(func, pcodelanguage, pcodecompilerspec, dtmanage);
int extrapop = getExtraPopOverride(func, addr);
hfunc.grabFromFunction(extrapop, false, (extrapop != default_extrapop));
HighSymbol funcSymbol = new HighFunctionSymbol(addr, 2, hfunc);
Namespace namespc = funcSymbol.getNamespace();
if (debug != null) {
debug.getFNTypes(hfunc);
debug.addPossiblePrototypeExtension(func);
}
encodeResult(resultEncoder, funcSymbol, namespc);
return; return;
} }
catch (Exception e) {
Msg.error(this, HighFunction hfunc = new HighFunction(func, pcodelanguage, pcodecompilerspec, dtmanage);
"Decompiling " + funcEntry + ", error in getExternalRef: " + e.getMessage(), e);
int extrapop = getExtraPopOverride(func, addr);
hfunc.grabFromFunction(extrapop, false, (extrapop != default_extrapop));
HighSymbol funcSymbol = new HighFunctionSymbol(addr, 2, hfunc);
Namespace namespc = funcSymbol.getNamespace();
if (debug != null) {
debug.getFNTypes(hfunc);
debug.addPossiblePrototypeExtension(func);
} }
encodeResult(resultEncoder, funcSymbol, namespc);
} }
/** /**

View file

@ -22,9 +22,12 @@ import java.io.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.lang.InjectPayload; import ghidra.program.model.lang.InjectPayload;
import ghidra.program.model.lang.UnknownInstructionException;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.NotFoundException;
import ghidra.util.timer.GTimer; import ghidra.util.timer.GTimer;
import ghidra.util.timer.GTimerMonitor; import ghidra.util.timer.GTimerMonitor;
@ -705,7 +708,8 @@ public class DecompileProcess {
write(query_response_end); write(query_response_end);
} }
private void getPcodeInject(int type) throws IOException, DecoderException { private void getPcodeInject(int type) throws IOException, DecoderException,
UnknownInstructionException, MemoryAccessException, NotFoundException {
resultEncoder.clear(); resultEncoder.clear();
String name = paramDecoder.readString(ATTRIB_NAME); String name = paramDecoder.readString(ATTRIB_NAME);
callback.getPcodeInject(name, paramDecoder, type, resultEncoder); callback.getPcodeInject(name, paramDecoder, type, resultEncoder);

View file

@ -20,8 +20,10 @@ import java.io.IOException;
import ghidra.app.plugin.processors.sleigh.PcodeEmit; import ghidra.app.plugin.processors.sleigh.PcodeEmit;
import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.Encoder; import ghidra.program.model.pcode.Encoder;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.exception.NotFoundException;
import ghidra.xml.XmlParseException; import ghidra.xml.XmlParseException;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -122,8 +124,13 @@ public interface InjectPayload {
* Given a context, send the p-code payload to the emitter * Given a context, send the p-code payload to the emitter
* @param context is the context for injection * @param context is the context for injection
* @param emit is the object accumulating the final p-code * @param emit is the object accumulating the final p-code
* @throws MemoryAccessException for problems establishing the injection context
* @throws IOException for problems while emitting the injection p-code
* @throws UnknownInstructionException if there is no underlying instruction being injected
* @throws NotFoundException if an expected aspect of the injection is not present in context
*/ */
public void inject(InjectContext context, PcodeEmit emit); public void inject(InjectContext context, PcodeEmit emit) throws MemoryAccessException,
IOException, UnknownInstructionException, NotFoundException;
/** /**
* A convenience function wrapping the inject method, to produce the final set * A convenience function wrapping the inject method, to produce the final set
@ -131,8 +138,13 @@ public interface InjectPayload {
* @param program is the Program for which injection is happening * @param program is the Program for which injection is happening
* @param con is the context for injection * @param con is the context for injection
* @return the array of PcodeOps * @return the array of PcodeOps
* @throws MemoryAccessException for problems establishing the injection context
* @throws IOException for problems while emitting the injection p-code
* @throws UnknownInstructionException if there is no underlying instruction being injected
* @throws NotFoundException if an expected aspect of the injection is not present in context
*/ */
public PcodeOp[] getPcode(Program program, InjectContext con); public PcodeOp[] getPcode(Program program, InjectContext con) throws MemoryAccessException,
IOException, UnknownInstructionException, NotFoundException;
/** /**
* @return true if the injected p-code falls thru * @return true if the injected p-code falls thru

View file

@ -27,7 +27,9 @@ import ghidra.app.plugin.processors.sleigh.template.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory; import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.pcode.*; import ghidra.program.model.pcode.*;
import ghidra.util.exception.NotFoundException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*; import ghidra.xml.*;
@ -163,22 +165,19 @@ public class InjectPayloadSleigh implements InjectPayload {
} }
@Override @Override
public void inject(InjectContext context, PcodeEmit emit) { public void inject(InjectContext context, PcodeEmit emit) throws UnknownInstructionException,
MemoryAccessException, IOException, NotFoundException {
ParserWalker walker = emit.getWalker(); ParserWalker walker = emit.getWalker();
try { walker.snippetState();
walker.snippetState(); setupParameters(context, walker);
setupParameters(context, walker); emit.build(pcodeTemplate, -1);
emit.build(pcodeTemplate, -1);
}
catch (Exception e) { // Should not be happening in a CallFixup
e.printStackTrace();
return;
}
emit.resolveRelatives(); emit.resolveRelatives();
} }
@Override @Override
public PcodeOp[] getPcode(Program program, InjectContext con) { public PcodeOp[] getPcode(Program program, InjectContext con)
throws UnknownInstructionException, MemoryAccessException, IOException,
NotFoundException {
SleighParserContext protoContext = SleighParserContext protoContext =
new SleighParserContext(con.baseAddr, con.nextAddr, con.refAddr, con.callAddr); new SleighParserContext(con.baseAddr, con.nextAddr, con.refAddr, con.callAddr);
ParserWalker walker = new ParserWalker(protoContext); ParserWalker walker = new ParserWalker(protoContext);
@ -333,29 +332,36 @@ public class InjectPayloadSleigh implements InjectPayload {
/** /**
* Verify that the storage locations passed -con- match the restrictions for this payload * Verify that the storage locations passed -con- match the restrictions for this payload
* @param con is InjectContext containing parameter storage locations * @param con is InjectContext containing parameter storage locations
* @throws NotFoundException for expected aspects of the context that are not present
*/ */
private void checkParameterRestrictions(InjectContext con, Address addr) { private void checkParameterRestrictions(InjectContext con, Address addr)
throws NotFoundException {
int insize = (con.inputlist == null) ? 0 : con.inputlist.size(); int insize = (con.inputlist == null) ? 0 : con.inputlist.size();
if (inputlist.length != insize) { if (inputlist.length != insize) {
throw new SleighException( throw new NotFoundException(
"Input parameters do not match injection specification: " + source); "Input parameters do not match specification " + name + " in\n" + source);
} }
for (int i = 0; i < inputlist.length; ++i) { for (int i = 0; i < inputlist.length; ++i) {
int sz = inputlist[i].getSize(); int sz = inputlist[i].getSize();
if (sz != 0 && sz != con.inputlist.get(i).getSize()) { if (sz != 0 && sz != con.inputlist.get(i).getSize()) {
throw new SleighException( throw new NotFoundException(
"Input parameter size does not match injection specification: " + source); "Input parameter size does not match specification " + name + " in\n" + source);
} }
} }
int outsize = (con.output == null) ? 0 : con.output.size(); int outsize = (con.output == null) ? 0 : con.output.size();
if (output.length != outsize) { if (output.length != outsize) {
throw new SleighException("Output does not match injection specification: " + source); if (outsize == 0) {
throw new NotFoundException(
"Output expected by specification " + name + " in\n" + source);
}
throw new NotFoundException(
"Output not expected by specification " + name + " in\n" + source);
} }
for (int i = 0; i < output.length; ++i) { for (int i = 0; i < output.length; ++i) {
int sz = output[i].getSize(); int sz = output[i].getSize();
if (sz != 0 && sz != con.output.get(i).getSize()) { if (sz != 0 && sz != con.output.get(i).getSize()) {
throw new SleighException( throw new NotFoundException(
"Output size does not match injection specification: " + source); "Output size does not match specification " + name + " in\n" + source);
} }
} }
} }
@ -365,9 +371,10 @@ public class InjectPayloadSleigh implements InjectPayload {
* @param con is the InjectContext containing storage locations * @param con is the InjectContext containing storage locations
* @param walker is the sleigh parser state object * @param walker is the sleigh parser state object
* @throws UnknownInstructionException if there are too many parameters for the parser * @throws UnknownInstructionException if there are too many parameters for the parser
* @throws NotFoundException for expected aspects of the context that are not present
*/ */
private void setupParameters(InjectContext con, ParserWalker walker) private void setupParameters(InjectContext con, ParserWalker walker)
throws UnknownInstructionException { throws UnknownInstructionException, NotFoundException {
checkParameterRestrictions(con, walker.getAddr()); checkParameterRestrictions(con, walker.getAddr());
for (int i = 0; i < inputlist.length; ++i) { for (int i = 0; i < inputlist.length; ++i) {
walker.allocateOperand(); walker.allocateOperand();