diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/InstructionDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/InstructionDB.java index c8e56fe794..aa399b9aaf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/InstructionDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/InstructionDB.java @@ -218,6 +218,7 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio if (alignment < 1) { alignment = 1; } + do { // skip past delay slot instructions try { @@ -228,8 +229,16 @@ public class InstructionDB extends CodeUnitDB implements Instruction, Instructio catch (AddressOverflowException e) { return null; } + // if an instruction is in a delay slot and has references to it, + // consider this the fallfrom instruction + if (instr != null && instr.isInDelaySlot() && instr.hasFallthrough()) { + if (program.getSymbolTable().hasSymbol(instr.getMinAddress())) { + break; + } + } } while (instr != null && instr.isInDelaySlot()); + if (instr == null) { return null; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/block/FollowFlow.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/block/FollowFlow.java index ea4b15d8cb..794aac4e82 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/block/FollowFlow.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/block/FollowFlow.java @@ -348,6 +348,10 @@ public class FollowFlow { nextSymbolAddr = null; } } + + // Delay adding instructions in delay slots to the functions body + // until the end. This allows for branches into the delay slot to be handled correctly. + AddressSet delaySlotSet = new AddressSet(); while (!monitor.isCancelled() && !instructionStack.isEmpty()) { @@ -367,36 +371,25 @@ public class FollowFlow { if (flowAddressSet.contains(currentAddress)) { continue; } - - // If code unit is a delay-slot instruction, backup to delayed instruction + Instruction instr = currentInstr; -// while (instr.isInDelaySlot()) { -// Address fallFrom = instr.getFallFrom(); -// if (fallFrom == null) { -// // assumes delay slot instructions have no flow -// flowAddressSet.addRange(instr.getMinAddress(), -// currentInstr.getMaxAddress()); -// break; -// } -// instr = program.getListing().getInstructionContaining(fallFrom); -// } -// if (instr.isInDelaySlot()) -// continue; // unable to find non-delay-slot instruction -// currentInstr = instr; - // handle instruction - include associated delay slot instructions + // handle instruction with delay slot instructions Address end = instr.getMaxAddress(); int delaySlotDepth = instr.getDelaySlotDepth(); for (int i = 0; i < delaySlotDepth; i++) { instr = instr.getNext(); if (instr == null) break; - end = instr.getMaxAddress(); + delaySlotSet.add(instr.getMinAddress(),instr.getMaxAddress()); } flowAddressSet.addRange(currentInstr.getMinAddress(), end); followInstruction(instructionStack, flowAddressSet, currentInstr); } + + // add in any instructions that were in a delayslot + flowAddressSet.add(delaySlotSet); } // followCode /** diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java index fad690673b..2a5e3008ef 100644 --- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java +++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java @@ -722,7 +722,6 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler { } else { memory.setInt(relocationAddress, (int) symbolValue); - byteLength = 8; } status = Status.APPLIED; break;