Merge remote-tracking branch 'origin/GP-5411_emteere_PPCpltThunk' into patch

This commit is contained in:
Ryan Kurtz 2025-03-05 10:18:52 -05:00
commit 57784ead36
4 changed files with 127 additions and 33 deletions

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.app.cmd.function; package ghidra.app.cmd.function;
import static ghidra.program.model.symbol.RefType.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -732,13 +734,41 @@ public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
FlowType flowType, boolean checkForSideEffects, HashSet<Varnode> setRegisters, FlowType flowType, boolean checkForSideEffects, HashSet<Varnode> setRegisters,
HashSet<Varnode> usedRegisters) { HashSet<Varnode> usedRegisters) {
// conditional jumps can't be thunks. // conditional jumps/call terminators can't be thunks,
// any other flow, not good // unless not checkingForSideEffects and just trying to get possible thunk address.
Address flowingAddr = null;
if ((flowType.isJump() || flowType.equals(RefType.COMPUTED_CALL_TERMINATOR) ||
flowType.equals(RefType.CALL_TERMINATOR)) && !flowType.isConditional()) {
// program counter should be assumed to be used
boolean isJump = flowType.isJump();
boolean isCall = flowType.isCall();
boolean isConditional = flowType.isConditional();
// only jump/call are allowed
if (!(isJump || isCall)) {
return null;
}
// no conditional jumps allowed
if (isJump && isConditional) {
return null;
}
if (isCall) {
// Any conditional call considered as having side-effects
if (isConditional && checkForSideEffects) {
return null;
}
// CALL_TERMINATOR, COMPUTED_CALL_TERMINATOR
else if (!flowType.isTerminal()) {
if (flowType == COMPUTED_CALL ||
flowType == UNCONDITIONAL_CALL) {
// consider any simple call having side-effects
if (checkForSideEffects) {
return null;
}
}
}
}
// program counter should be assumed to be used
// assume PC is used when considering registers that have been set // assume PC is used when considering registers that have been set
Register PC = program.getLanguage().getProgramCounter(); Register PC = program.getLanguage().getProgramCounter();
if (PC != null) { if (PC != null) {
@ -757,11 +787,13 @@ public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
} }
} }
Address flowingAddr = null;
// if not checking for sideEffect registers set, or there are no side-effects // if not checking for sideEffect registers set, or there are no side-effects
if (!checkForSideEffects || setRegisters.size() == 0) { if (!checkForSideEffects || setRegisters.size() == 0) {
flowingAddr = getFlowingAddress(program, instr); flowingAddr = getFlowingAddress(program, instr);
} }
}
return flowingAddr; return flowingAddr;
} }

View file

@ -72,22 +72,30 @@ class EditThunkFunctionAction extends ProgramContextAction {
if (func == null) { if (func == null) {
return; return;
} }
Address funcEntry = func.getEntryPoint();
Function refFunc = func.getThunkedFunction(false); Function refFunc = func.getThunkedFunction(false);
if (refFunc == null) {
// if not already thunked, fill in a possible value from functions instructions
Address thunkAddr = CreateThunkFunctionCmd.getThunkedAddr(program, funcEntry, false);
if (thunkAddr != null) {
refFunc = functionMgr.getFunctionAt(thunkAddr);
}
}
Symbol refSymbol = (refFunc == null ? null : refFunc.getSymbol());
// Prompt for function referenced by thunk // Prompt for function referenced by thunk
ThunkReferenceAddressDialog dialog = new ThunkReferenceAddressDialog(funcPlugin.getTool()); ThunkReferenceAddressDialog dialog = new ThunkReferenceAddressDialog(funcPlugin.getTool());
dialog.showDialog(program, func.getEntryPoint(), dialog.showDialog(program, funcEntry, refSymbol);
refFunc != null ? refFunc.getSymbol() : null);
Symbol referencedSymbol = dialog.getSymbol(); Symbol referencedSymbol = dialog.getSymbol();
Address referencedFunctionAddr = dialog.getAddress(); Address referencedFunctionAddr = dialog.getAddress();
CreateThunkFunctionCmd cmd; CreateThunkFunctionCmd cmd;
if (referencedSymbol != null) { if (referencedSymbol != null) {
cmd = new CreateThunkFunctionCmd(func.getEntryPoint(), null, referencedSymbol); cmd = new CreateThunkFunctionCmd(funcEntry, null, referencedSymbol);
} }
else if (referencedFunctionAddr != null) { else if (referencedFunctionAddr != null) {
cmd = new CreateThunkFunctionCmd(func.getEntryPoint(), null, referencedFunctionAddr); cmd = new CreateThunkFunctionCmd(funcEntry, null, referencedFunctionAddr);
} }
else { else {
return; // cancelled return; // cancelled

View file

@ -36,4 +36,31 @@
<possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here --> <possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here -->
</pattern> </pattern>
<pattern> <!-- .plt entry thunk -->
<data>
0xf8410028 <!-- std r2,0x28(r1) -->
001111.. ...00010 0xff 0xff <!-- subis rX,r2,0x1 -->
0xe9 ........ ........ ........ <!-- ld rX,#(x) -->
0x7d 0x.9 0x03 0xa6 <!-- mtctr rX -->
0xe8 010..... ........ ........ <!-- ld r2,#(x) -->
0x28220000 <!-- cmpldi r2,0 -->
0x4c 1..00010 0x04 0x20 <!-- bnectr+ -->
010010.. ........ ........ ......00 <!-- b X@plt -->
</data>
<funcstart after="defined" thunk="true"/> <!-- must be something define before this -->
</pattern>
<pattern> <!-- .plt entry thunk -->
<data>
0xf8410028 <!-- std r2,0x28(r1) -->
0xe9 ........ ........ ........ <!-- ld rX,#(x) -->
0x7d 0x.9 0x03 0xa6 <!-- mtctr rX -->
0xe8 010..... ........ ........ <!-- ld r2,#(x) -->
0x28220000 <!-- cmpldi r2,0 -->
0x4c 1..00010 0x04 0x20 <!-- bnectr+ -->
010010.. ........ ........ ......00 <!-- b X@plt -->
</data>
<funcstart after="defined" thunk="true"/> <!-- must be something define before this -->
</pattern>
</patternlist> </patternlist>

View file

@ -36,4 +36,31 @@
<possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here --> <possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here -->
</pattern> </pattern>
<pattern> <!-- .plt entry thunk -->
<data>
0x280041f8 <!-- std r2,0x28(r1) -->
0xff 0xff ...00010 001111.. <!-- subis rX,r2,0x1 -->
........ ........ ........ 0xe9 <!-- ld rX,#(x) -->
0xa6 0x03 0x.9 0x7d <!-- mtctr rX -->
........ ........ 010..... 0xe8 <!-- ld r2,#(x) -->
0x00002228 <!-- cmpldi r2,0 -->
0x20 0x04 1..00010 0x4c <!-- bnectr+ -->
......00 ........ ........ 010010.. <!-- b X@plt -->
</data>
<funcstart after="defined" thunk="true"/> <!-- must be something define before this -->
</pattern>
<pattern> <!-- .plt entry thunk -->
<data>
0x280041f8 <!-- std r2,0x28(r1) -->
........ ........ ........ 0xe9 <!-- ld rX,#(x) -->
0xa6 0x03 0x.9 0x7d <!-- mtctr rX -->
........ ........ 010..... 0xe8 <!-- ld r2,#(x) -->
0x00002228 <!-- cmpldi r2,0 -->
0x20 0x04 1..00010 0x4c <!-- bnectr+ -->
......00 ........ ........ 010010.. <!-- b X@plt -->
</data>
<funcstart after="defined" thunk="true"/> <!-- must be something define before this -->
</pattern>
</patternlist> </patternlist>