diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java index 61c11be009..b6585a3794 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/SymPcodeExecutor.java @@ -15,6 +15,7 @@ */ package ghidra.app.plugin.core.debug.stack; +import java.io.IOException; import java.util.*; import ghidra.app.decompiler.DecompInterface; @@ -28,8 +29,10 @@ import ghidra.program.model.address.Address; import ghidra.program.model.data.*; import ghidra.program.model.lang.*; import ghidra.program.model.listing.*; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.*; import ghidra.util.exception.InvalidInputException; +import ghidra.util.exception.NotFoundException; import ghidra.util.task.TaskMonitor; /** @@ -68,8 +71,8 @@ class SymPcodeExecutor extends PcodeExecutor { CompilerSpec cSpec = program.getCompilerSpec(); SleighLanguage language = (SleighLanguage) cSpec.getLanguage(); SymPcodeArithmetic arithmetic = new SymPcodeArithmetic(cSpec); - return new SymPcodeExecutor(program, cSpec, language, arithmetic, state, reason, - warnings, monitor); + return new SymPcodeExecutor(program, cSpec, language, arithmetic, state, reason, warnings, + monitor); } private final Program program; @@ -93,8 +96,7 @@ class SymPcodeExecutor extends PcodeExecutor { } @Override - public void executeCallother(PcodeOp op, PcodeFrame frame, - PcodeUseropLibrary library) { + public void executeCallother(PcodeOp op, PcodeFrame frame, PcodeUseropLibrary library) { // Do nothing // TODO: Is there a way to know if a userop affects the stack? } @@ -120,8 +122,7 @@ class SymPcodeExecutor extends PcodeExecutor { } int extrapop = convention.getExtrapop(); if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) { - throw new PcodeExecutionException( - "Cannot get stack change for function " + function); + throw new PcodeExecutionException("Cannot get stack change for function " + function); } if (function.isStackPurgeSizeValid()) { return extrapop + function.getStackPurgeSize(); @@ -151,9 +152,15 @@ class SymPcodeExecutor extends PcodeExecutor { } String fixupName = callee.getCallFixup(); if (fixupName != null && !"".equals(fixupName)) { - PcodeProgram snippet = - PcodeProgram.fromInject(program, fixupName, InjectPayload.CALLFIXUP_TYPE); - execute(snippet, library); + PcodeProgram snippet; + try { + 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; } int change = computeStackChange(callee); diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeProgram.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeProgram.java index 0e7fe1f9d1..398e6aae87 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeProgram.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/pcode/exec/PcodeProgram.java @@ -15,6 +15,7 @@ */ package ghidra.pcode.exec; +import java.io.IOException; import java.util.*; 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.listing.Instruction; import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.PcodeOp; +import ghidra.util.exception.NotFoundException; /** * 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"); } PcodeOp[] pcode = instruction.getPcode(includeOverrides); - return new PcodeProgram((SleighLanguage) language, List.of(pcode), - Map.of()); + return new PcodeProgram((SleighLanguage) language, List.of(pcode), Map.of()); } /** @@ -123,8 +125,14 @@ public class PcodeProgram { * @param name the name of the snippet * @param type the type of the snippet * @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(); InjectContext ctx = library.buildInjectContext(); InjectPayload payload = library.getPayload(type, name); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java index bee638d260..74c4b31200 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java @@ -15,9 +15,8 @@ */ package ghidra.program.util; -import java.util.*; - import java.math.BigInteger; +import java.util.*; import org.apache.commons.collections4.map.LRUMap; @@ -88,7 +87,7 @@ public class SymbolicPropogator { // Cache instructions looked up by containing Map instructionContainingCache = new LRUMap<>(LRU_SIZE); - + // cache for pcode callother injection payloads HashMap injectPayloadCache = new HashMap(); @@ -966,7 +965,7 @@ public class SymbolicPropogator { // for callother, could be an interrupt, need to look at it like a call case PcodeOp.CALLOTHER: PcodeOp[] callOtherPcode = doCallOtherPcodeInjection(instruction, in, out); - + if (callOtherPcode != null) { ops = injectPcode(ops, pcodeIndex, callOtherPcode); pcodeIndex = -1; @@ -1088,7 +1087,8 @@ public class SymbolicPropogator { // if return value is a location, give evaluator a chance to check the value try { val1 = vContext.getValue(in[0], evaluator); - if (evaluator != null && evaluator.evaluateReturn(val1, vContext, instruction)) { + if (evaluator != null && + evaluator.evaluateReturn(val1, vContext, instruction)) { canceled = true; return null; } @@ -1446,9 +1446,9 @@ public class SymbolicPropogator { Varnode vt; if (!context.isExternalSpace(val1.getSpace())) { long lval = vContext.getConstant(val1, evaluator); - vt = vContext.getVarnode(minInstrAddress.getAddressSpace().getSpaceID(), - lval, 0); - } else { + vt = vContext.getVarnode(minInstrAddress.getAddressSpace().getSpaceID(), lval, 0); + } + else { vt = val1; } return vt; @@ -1602,7 +1602,13 @@ public class SymbolicPropogator { con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset()); con.callAddr = func.getEntryPoint(); 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, @@ -1629,7 +1635,13 @@ public class SymbolicPropogator { con.nextAddr = con.baseAddr.add(instr.getDefaultFallThroughOffset()); con.callAddr = target; 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) { @@ -1662,7 +1674,8 @@ public class SymbolicPropogator { * * @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(); PcodeInjectLibrary snippetLibrary = prog.getCompilerSpec().getPcodeInjectLibrary(); @@ -1689,33 +1702,40 @@ public class SymbolicPropogator { con.inputlist = inputs; con.output = new ArrayList(); 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); - + // 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)) { + 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; @@ -1739,12 +1759,12 @@ public class SymbolicPropogator { } PrototypeModel conv = function.getCallingConvention(); - + if (function.isStackPurgeSizeValid()) { int depth = function.getStackPurgeSize(); return getDefaultStackDepthChange(prog, conv, depth); } - + return getDefaultStackDepthChange(prog, conv, Function.UNKNOWN_STACK_DEPTH_CHANGE); } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc index ff775928f5..f688535a6d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/flow.cc @@ -1154,6 +1154,8 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO bool startbasic = op->isBlockStart(); ++iter; // Now points to first op in the injection + if (iter == obank.endDead()) + throw LowlevelError("Empty injection: " + payload->getName()); PcodeOp *firstop = *iter; bool isfallthru = true; PcodeOp *lastop = xrefControlFlow(iter,startbasic,isfallthru,fc); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/inject_ghidra.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/inject_ghidra.cc index 6ecde748c1..1f14d2a55b 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/inject_ghidra.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/inject_ghidra.cc @@ -51,13 +51,13 @@ void InjectPayloadGhidra::inject(InjectContext &con,PcodeEmit &emit) const PackedDecode decoder(ghidra); try { 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) { - throw LowlevelError("Error getting pcode snippet: " + err.explain); + throw LowlevelError("Injection error: " + err.explain); } catch(DecoderError &err) { - throw LowlevelError("Error in pcode snippet xml: "+err.explain); + throw LowlevelError("Error decoding injection: "+err.explain); } uint4 elemId = decoder.openElement(); Address addr = Address::decode(decoder); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java index 7a6729ca12..037afa23ba 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileCallback.java @@ -35,6 +35,7 @@ import ghidra.program.model.pcode.*; import ghidra.program.model.symbol.*; import ghidra.util.Msg; import ghidra.util.UndefinedFunction; +import ghidra.util.exception.NotFoundException; import ghidra.util.exception.UsrException; import ghidra.util.task.TaskMonitor; @@ -139,6 +140,8 @@ public class DecompileCallback { /** * 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 size is the number of bytes to fetch * @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 resultEncoder will contain the generated p-code ops */ @@ -234,7 +239,8 @@ public class DecompileCallback { Msg.error(this, "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 type is the type of payload * @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(); InjectPayload payload = snippetLibrary.getPayload(type, nm); if (payload == null) { - Msg.warn(this, "Decompiling " + funcEntry + ", no pcode inject with name: " + nm); - return; // No fixup associated with this name + throw new NotFoundException("No p-code injection with name: " + nm); } InjectContext con = snippetLibrary.buildInjectContext(); 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) { - Msg.error(this, "Decompiling " + funcEntry + ": " + e.getMessage()); - return; - } - try { - 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 + else { + Instruction instr = getInstruction(con.baseAddr); + if (instr == null) { + Msg.warn(this, "Decompiling " + funcEntry + ", pcode inject error at " + + con.baseAddr + ": instruction not found"); + return; } - 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 - fallThruOffset = instr.getDefaultFallThroughOffset(); - con.nextAddr = con.baseAddr.add(fallThruOffset); + // get next inst addr for inst_next pcode variable + fallThruOffset = instr.getDefaultFallThroughOffset(); + con.nextAddr = con.baseAddr.add(fallThruOffset); - con.refAddr = null; - for (Reference ref : program.getReferenceManager() - .getReferencesFrom(con.baseAddr)) { - if (ref.isPrimary() && ref.getReferenceType().isCall()) { - con.refAddr = ref.getToAddress(); - break; - } + con.refAddr = null; + for (Reference ref : program.getReferenceManager().getReferencesFrom(con.baseAddr)) { + if (ref.isPrimary() && ref.getReferenceType().isCall()) { + con.refAddr = ref.getToAddress(); + break; } } - pcode = payload.getPcode(program, con); - if (pcode == null) { - return; // Return without result, which should let the decompiler exit gracefully - } - encodeInstruction(resultEncoder, con.baseAddr, pcode, fallThruOffset, + } + pcode = payload.getPcode(program, con); + if (pcode == null) { + return; // Return without result, which should let the decompiler exit gracefully + } + 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); - if (debug != null) { - 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); + debug.addInject(con.baseAddr, nm, type, xmlEncode.toString()); } } @@ -429,26 +424,19 @@ public class DecompileCallback { * Return the first symbol name at the given address * @param addr is the given address * @return the symbol or null if no symbol is found + * @throws IOException for errors trying to encode the symbol */ - public String getCodeLabel(Address addr) { - try { - Symbol sym = program.getSymbolTable().getPrimarySymbol(addr); - if (sym == null) { - return null; - } - String res = getSymbolName(sym); - if (debug != null) { - debug.getCodeSymbol(addr, sym.getID(), res, sym.getParentNamespace()); - } + public String getCodeLabel(Address addr) throws IOException { + Symbol sym = program.getSymbolTable().getPrimarySymbol(addr); + if (sym == null) { + return null; + } + String res = getSymbolName(sym); + if (debug != null) { + debug.getCodeSymbol(addr, sym.getID(), res, sym.getParentNamespace()); + } - return res; - } - catch (Exception e) { - Msg.error(this, - "Decompiling " + funcEntry + ", error while accessing symbol: " + e.getMessage(), - e); - } - return null; + return res; } private String getSymbolName(Symbol sym) { @@ -658,100 +646,86 @@ public class DecompileCallback { * * @param addr is the given address * @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) { // Unknown spaces may result from "spacebase" registers defined in cspec return; } - try { - Object obj = lookupSymbol(addr); - if (obj instanceof Function) { - boolean includeDefaults = addr.equals(funcEntry); - 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; + Object obj = lookupSymbol(addr); + if (obj instanceof Function) { + boolean includeDefaults = addr.equals(funcEntry); + encodeFunction(resultEncoder, (Function) obj, addr, includeDefaults); } - catch (Exception e) { - Msg.error(this, "Decompiling " + funcEntry + ", mapped symbol error for " + addr + - ": " + e.getMessage(), e); + 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; } /** * Get a description of an external reference at the given address * @param addr is the given address * @param resultEncoder will contain the resulting description + * @throws IOException for errors encoding the result */ - public void getExternalRef(Address addr, Encoder resultEncoder) { - try { - Function func = null; - if (cachedFunction != null && cachedFunction.getEntryPoint().equals(addr)) { - func = cachedFunction; + public void getExternalRef(Address addr, Encoder resultEncoder) throws IOException { + Function func = null; + if (cachedFunction != null && cachedFunction.getEntryPoint().equals(addr)) { + 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 { - 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 { - func = listing.getFunctionAt(addr); - } + func = listing.getFunctionAt(addr); } - if (func == null) { - // Its conceivable we could have external data, but we aren't currently checking for it - return; - } - - 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); + } + if (func == null) { + // Its conceivable we could have external data, but we aren't currently checking for it return; } - catch (Exception e) { - Msg.error(this, - "Decompiling " + funcEntry + ", error in getExternalRef: " + e.getMessage(), e); + + 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); } /** diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java index 42fed63d10..a9652db81c 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileProcess.java @@ -22,9 +22,12 @@ import java.io.*; import ghidra.program.model.address.Address; import ghidra.program.model.lang.InjectPayload; +import ghidra.program.model.lang.UnknownInstructionException; import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.*; import ghidra.util.Msg; +import ghidra.util.exception.NotFoundException; import ghidra.util.timer.GTimer; import ghidra.util.timer.GTimerMonitor; @@ -705,7 +708,8 @@ public class DecompileProcess { 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(); String name = paramDecoder.readString(ATTRIB_NAME); callback.getPcodeInject(name, paramDecoder, type, resultEncoder); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java index 6d87618af4..f357d90ae5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayload.java @@ -20,8 +20,10 @@ import java.io.IOException; import ghidra.app.plugin.processors.sleigh.PcodeEmit; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.Encoder; import ghidra.program.model.pcode.PcodeOp; +import ghidra.util.exception.NotFoundException; import ghidra.xml.XmlParseException; import ghidra.xml.XmlPullParser; @@ -122,8 +124,13 @@ public interface InjectPayload { * Given a context, send the p-code payload to the emitter * @param context is the context for injection * @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 @@ -131,8 +138,13 @@ public interface InjectPayload { * @param program is the Program for which injection is happening * @param con is the context for injection * @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 diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java index 9b3cbeafdb..3dd86c1b81 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/InjectPayloadSleigh.java @@ -27,7 +27,9 @@ import ghidra.app.plugin.processors.sleigh.template.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressFactory; import ghidra.program.model.listing.Program; +import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.pcode.*; +import ghidra.util.exception.NotFoundException; import ghidra.util.xml.SpecXmlUtils; import ghidra.xml.*; @@ -163,22 +165,19 @@ public class InjectPayloadSleigh implements InjectPayload { } @Override - public void inject(InjectContext context, PcodeEmit emit) { + public void inject(InjectContext context, PcodeEmit emit) throws UnknownInstructionException, + MemoryAccessException, IOException, NotFoundException { ParserWalker walker = emit.getWalker(); - try { - walker.snippetState(); - setupParameters(context, walker); - emit.build(pcodeTemplate, -1); - } - catch (Exception e) { // Should not be happening in a CallFixup - e.printStackTrace(); - return; - } + walker.snippetState(); + setupParameters(context, walker); + emit.build(pcodeTemplate, -1); emit.resolveRelatives(); } @Override - public PcodeOp[] getPcode(Program program, InjectContext con) { + public PcodeOp[] getPcode(Program program, InjectContext con) + throws UnknownInstructionException, MemoryAccessException, IOException, + NotFoundException { SleighParserContext protoContext = new SleighParserContext(con.baseAddr, con.nextAddr, con.refAddr, con.callAddr); 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 * @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(); if (inputlist.length != insize) { - throw new SleighException( - "Input parameters do not match injection specification: " + source); + throw new NotFoundException( + "Input parameters do not match specification " + name + " in\n" + source); } for (int i = 0; i < inputlist.length; ++i) { int sz = inputlist[i].getSize(); if (sz != 0 && sz != con.inputlist.get(i).getSize()) { - throw new SleighException( - "Input parameter size does not match injection specification: " + source); + throw new NotFoundException( + "Input parameter size does not match specification " + name + " in\n" + source); } } int outsize = (con.output == null) ? 0 : con.output.size(); 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) { int sz = output[i].getSize(); if (sz != 0 && sz != con.output.get(i).getSize()) { - throw new SleighException( - "Output size does not match injection specification: " + source); + throw new NotFoundException( + "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 walker is the sleigh parser state object * @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) - throws UnknownInstructionException { + throws UnknownInstructionException, NotFoundException { checkParameterRestrictions(con, walker.getAddr()); for (int i = 0; i < inputlist.length; ++i) { walker.allocateOperand();