diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/DecompilerScriptUtils.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/DecompilerScriptUtils.java index 5e32b90823..90db9073c3 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/DecompilerScriptUtils.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/DecompilerScriptUtils.java @@ -20,6 +20,8 @@ import ghidra.app.decompiler.*; import ghidra.app.decompiler.component.DecompilerUtils; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.address.AddressOutOfBoundsException; import ghidra.program.model.data.DataType; import ghidra.program.model.data.ParameterDefinition; import ghidra.program.model.listing.Function; @@ -226,42 +228,32 @@ public class DecompilerScriptUtils { decompInterface.dispose(); } + /** + * Best-effort extraction of an address candidate from decompiler p-code. + * Returns {@code null} if the candidate is invalid or not mapped in program memory. + */ public Address getAssignedAddressFromPcode(Varnode storedValue) { - long addressOffset; if (storedValue.isConstant()) { - addressOffset = storedValue.getOffset(); - Address possibleAddress = toAddr(addressOffset); - if (possibleAddress == null || !program.getMemory().contains(possibleAddress)) { - return null; - } - return possibleAddress; + return tryToAddr(storedValue.getOffset()); } - PcodeOp valuePcodeOp = storedValue.getDef(); - - if (valuePcodeOp == null) { + PcodeOp op = storedValue.getDef(); + if (op == null) { return null; } - if (valuePcodeOp.getOpcode() == PcodeOp.CAST || valuePcodeOp.getOpcode() == PcodeOp.COPY) { - - Varnode constantVarnode = valuePcodeOp.getInput(0); - return getAssignedAddressFromPcode(constantVarnode); - + int opcode = op.getOpcode(); + if (opcode == PcodeOp.CAST || opcode == PcodeOp.COPY) { + return getAssignedAddressFromPcode(op.getInput(0)); } - else if (valuePcodeOp.getOpcode() != PcodeOp.PTRSUB) { + + if (opcode != PcodeOp.PTRSUB) { return null; } - // don't need to check isConst bc always is - Varnode constantVarnode = valuePcodeOp.getInput(1); - addressOffset = constantVarnode.getOffset(); - Address possibleAddress = toAddr(addressOffset); - if (possibleAddress == null || !program.getMemory().contains(possibleAddress)) { - return null; - } - return possibleAddress; + // PTRSUB input(1) is always a constant offset (but may not represent a valid program address) + return tryToAddr(op.getInput(1).getOffset()); } /** @@ -302,4 +294,29 @@ public class DecompilerScriptUtils { return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset); } + /** + * Attempts to convert the given offset to an {@link Address} in the default address space. + *

+ * Decompiler pcode may surface non-pointer constants that heuristics attempt to interpret + * as addresses; this method performs a best-effort conversion and safely ignores + * invalid or unmapped candidates. + *

+ * Unlike {@link #toAddr(long)}, this method returns {@code null} if the resulting address is not + * contained in the program's memory or if the offset is out of bounds. + * + * @param offset the offset to convert + * @return the address for the given offset, or {@code null} if the offset cannot be represented + * as a valid address in the program's memory + */ + public final Address tryToAddr(long offset) { + AddressSpace space = program.getAddressFactory().getDefaultAddressSpace(); + try { + Address addr = space.getAddress(offset); + return program.getMemory().contains(addr) ? addr : null; + } + catch (AddressOutOfBoundsException e) { + return null; + } + } + }