diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/PcodeEmit.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/PcodeEmit.java index c4961e1fe7..2c2dbcf39f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/PcodeEmit.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/PcodeEmit.java @@ -185,6 +185,34 @@ public abstract class PcodeEmit { */ public abstract void resolveRelatives(); + /** + * Now that all pcode has been generated, including special + * overrides and injections, ensure that a fallthrough override + * adds a final branch to prevent dropping out the bottom. This + * addresses both fall-through cases: + * + */ + void resolveFinalFallthrough() { + try { + if (fallOverride == null || fallOverride.equals(getStartAddress().add(fallOffset))) { + return; + } + } + catch (AddressOutOfBoundsException e) { + // ignore + } + + VarnodeData dest = new VarnodeData(); + dest.space = fallOverride.getAddressSpace().getPhysicalSpace(); + dest.offset = fallOverride.getOffset(); + dest.size = dest.space.getPointerSize(); + + dump(startAddress, PcodeOp.BRANCH, new VarnodeData[] { dest }, 1, null); + } + abstract void dump(Address instrAddr, int opcode, VarnodeData[] in, int isize, VarnodeData out); private boolean dumpBranchOverride(OpTpl opt) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighInstructionPrototype.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighInstructionPrototype.java index 0ca05d8c27..5307a6b36e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighInstructionPrototype.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighInstructionPrototype.java @@ -968,6 +968,9 @@ public class SleighInstructionPrototype implements InstructionPrototype { new PcodeEmitObjects(walker, context, fallOffset, override, uniqueFactory); emit.build(walker.getConstructor().getTempl(), -1); emit.resolveRelatives(); + if (!isindelayslot) { + emit.resolveFinalFallthrough(); + } protoContext.setDelaySlotLength(0); return emit.getPcodeOp(); } @@ -1016,6 +1019,9 @@ public class SleighInstructionPrototype implements InstructionPrototype { emit.build(walker.getConstructor().getTempl(), -1); emit.resolveRelatives(); + if (!isindelayslot) { + emit.resolveFinalFallthrough(); + } protoContext.setDelaySlotLength(0); emit.write(PcodeEmitPacked.end_tag); // Terminate the inst_tag return emit.getPackedBytes(); @@ -1048,6 +1054,9 @@ public class SleighInstructionPrototype implements InstructionPrototype { PcodeEmitObjects emit = new PcodeEmitObjects(walker); emit.build(walker.getConstructor().getTempl(), -1); emit.resolveRelatives(); + if (!isindelayslot) { + emit.resolveFinalFallthrough(); + } return emit.getPcodeOp(); } }