Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2025-07-18 15:21:52 -04:00
commit 9628d10220
7 changed files with 79 additions and 18 deletions

View file

@ -43,6 +43,7 @@ src/decompile/datatests/impliedfield.xml||GHIDRA||||END|
src/decompile/datatests/indproto.xml||GHIDRA||||END|
src/decompile/datatests/injectoverride.xml||GHIDRA||||END|
src/decompile/datatests/inline.xml||GHIDRA||||END|
src/decompile/datatests/inlinetarget.xml||GHIDRA||||END|
src/decompile/datatests/longdouble.xml||GHIDRA||||END|
src/decompile/datatests/loopcomment.xml||GHIDRA||||END|
src/decompile/datatests/lzcount.xml||GHIDRA||||END|

View file

@ -198,6 +198,19 @@ PcodeOp *FlowInfo::branchTarget(PcodeOp *op) const
return target(addr); // Otherwise a normal address target
}
/// Replace any reference to the op being inlined with the first op of the inlined sequence.
/// \param oldOp is the p-code op being inlined
/// \param newOp is the first p-code op in the inlined sequence
void FlowInfo::updateTarget(PcodeOp *oldOp,PcodeOp *newOp)
{
map<Address,VisitStat>::iterator viter = visited.find(oldOp->getAddr());
if (viter != visited.end()) { // Check if -oldOp- is a possible branch target
if ((*viter).second.seqnum == oldOp->getSeqNum()) // (if injection op is the first op for its address)
(*viter).second.seqnum = newOp->getSeqNum(); // change the seqnum to the newOp
}
}
/// Check to see if the new target has been seen before. Otherwise
/// add it to the list of addresses that need to be processed.
/// Also check range bounds and update basic block information.
@ -1189,11 +1202,7 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO
obank.markIncidentalCopy(firstop, lastop);
obank.moveSequenceDead(firstop,lastop,op); // Move the injection to right after the call
map<Address,VisitStat>::iterator viter = visited.find(op->getAddr());
if (viter != visited.end()) { // Check if -op- is a possible branch target
if ((*viter).second.seqnum == op->getSeqNum()) // (if injection op is the first op for its address)
(*viter).second.seqnum = firstop->getSeqNum(); // change the seqnum to the first injected op
}
updateTarget(op,firstop); // Replace -op- with -firstop- in the target map
// Get rid of the original call
data.opDestroyRaw(op);
}

View file

@ -148,6 +148,7 @@ public:
void clearFlags(uint4 val) { flags &= ~val; } ///< Disable a specific option
PcodeOp *target(const Address &addr) const; ///< Return first p-code op for instruction at given address
PcodeOp *branchTarget(PcodeOp *op) const; ///< Find the target referred to by a given BRANCH or CBRANCH
void updateTarget(PcodeOp *oldOp,PcodeOp *newOp); ///< Update the branch target for an inlined p-code op
void generateOps(void); ///< Generate raw control-flow from the function's base address
void generateBlocks(void); ///< Generate basic blocks from the raw control-flow
bool testHardInlineRestrictions(Funcdata *inlinefd,PcodeOp *op,Address &retaddr);

View file

@ -880,8 +880,10 @@ int4 Funcdata::inlineFlow(Funcdata *inlinefd,FlowInfo &flow,PcodeOp *callop)
--oiter;
PcodeOp *lastop = *oiter;
obank.moveSequenceDead(firstop,lastop,callop); // Move cloned sequence to right after callop
if (callop->isBlockStart())
if (callop->isBlockStart()) {
firstop->setFlag(PcodeOp::startbasic); // First op of inline inherits callop's startbasic flag
flow.updateTarget(callop, firstop);
}
else
firstop->clearFlag(PcodeOp::startbasic);
}

View file

@ -0,0 +1,35 @@
<decompilertest>
<binaryimage arch="PowerPC:BE:32:default:default">
<!--
Function with a BRANCH, overridden as a CALL, to an inlined function.
The BRANCH instruction is also a fallthru target.
-->
<bytechunk space="ram" offset="0x100003fc" readonly="true">
3821fff8
95e10000960100044e800020
</bytechunk>
<bytechunk space="ram" offset="0x10000410" readonly="true">
85e1000086010004382100087c0803a6
4e8000207c0802a64bffffd539e00000
2c0f000a4080001c1e0f00047e100214
7e0903a64e80042139ef00014280ffe4
4280ffc0
</bytechunk>
<symbol space="ram" offset="0x100003fc" name="prologue"/>
<symbol space="ram" offset="0x10000410" name="epilogue"/>
</binaryimage>
<script>
<com>option inline prologue</com>
<com>option inline epilogue</com>
<com>map fun r0x10000424 main</com>
<com>override flow r0x10000450 callreturn</com>
<com>lo fu main</com>
<com>decompile</com>
<com>print C</com>
<com>quit</com>
</script>
<stringmatch name="Inline target #1" min="1" max="1">Inlined function: prologue</stringmatch>
<stringmatch name="Inline target #2" min="1" max="1">Inlined function: epilogue</stringmatch>
<stringmatch name="Inline target #3" min="0" max="0">Could not find op at target</stringmatch>
<stringmatch name="Inline target #4" min="1" max="1">for \(iVar1 = 0; iVar1 &lt; 10; iVar1 = iVar1 \+ 1\)</stringmatch>
</decompilertest>

View file

@ -522,6 +522,7 @@ public class PowerPC64_ElfExtension extends ElfExtension {
Function f = elfLoadHelper.createOneByteFunction(name, address, false);
if (f != null && localFunction != null) {
f.setThunkedFunction(localFunction);
elfLoadHelper.setElfSymbolAddress(elfSymbol, address);
return null; // symbol creation handled
}
@ -543,6 +544,11 @@ public class PowerPC64_ElfExtension extends ElfExtension {
if (elf.e_machine() != ElfConstants.EM_PPC64) {
return 0;
}
if (elf.getSection(".opd") != null) {
return 1;
}
// TODO: While the e_flags should indicate the use of function descriptors, this
// may not be set reliably. The presence of the .opd section is another
// indicator but could be missing if sections have been stripped.

View file

@ -215,27 +215,34 @@ public class PowerPC64_ElfRelocationHandler
memory.setInt(relocationAddress, newValue);
break;
case R_PPC64_JMP_SLOT:
// TODO: do we need option to allow function descriptor
// use - or not? The EF_PPC64_ABI in e_flags is not reliable.
Address functionDescriptorAddr = relocationAddress.getNewAddress(symbolValue);
MemoryBlock block = memory.getBlock(functionDescriptorAddr);
MemoryBlock block = memory.getBlock(symbolAddr);
if (block == null) {
throw new MemoryAccessException(
"Function descriptor not found at: " + functionDescriptorAddr);
"Relocation symbol not found in memory: " + symbolAddr);
}
if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) {
// If symbol is in EXTERNAL block, we don't have descriptor entry;
// just fill-in first slot with EXTERNAL address
memory.setLong(relocationAddress, symbolValue);
byteLength = 8;
break;
}
else {
if (PowerPC64_ElfExtension
.getPpc64ABIVersion(elfRelocationContext.getElfHeader()) == 1) {
// ABI ELFv1 (used by big-endian PPC64) expected to copy full function descriptor
// into .got.plt section where symbolAddr refers to function descriptor
// Copy function descriptor data
byte[] bytes = new byte[24]; // TODO: can descriptor size vary ?
memory.getBytes(functionDescriptorAddr, bytes);
byte[] bytes = new byte[24];
memory.getBytes(symbolAddr, bytes);
memory.setBytes(relocationAddress, bytes);
byteLength = bytes.length;
}
else {
memory.setLong(relocationAddress, symbolValue);
byteLength = 8;
}
break;
case R_PPC64_UADDR32:
newValue = (int) (symbolValue + addend);