mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-5411_emteere_PPCpltThunk' into patch
This commit is contained in:
commit
57784ead36
4 changed files with 127 additions and 33 deletions
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.cmd.function;
|
||||
|
||||
import static ghidra.program.model.symbol.RefType.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -732,36 +734,66 @@ public class CreateThunkFunctionCmd extends BackgroundCommand<Program> {
|
|||
FlowType flowType, boolean checkForSideEffects, HashSet<Varnode> setRegisters,
|
||||
HashSet<Varnode> usedRegisters) {
|
||||
|
||||
// conditional jumps can't be thunks.
|
||||
// any other flow, not good
|
||||
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
|
||||
|
||||
// assume PC is used when considering registers that have been set
|
||||
Register PC = program.getLanguage().getProgramCounter();
|
||||
if (PC != null) {
|
||||
usedRegisters.add(new Varnode(PC.getAddress(), PC.getMinimumByteSize()));
|
||||
// conditional jumps/call terminators can't be thunks,
|
||||
// unless not checkingForSideEffects and just trying to get possible thunk address.
|
||||
|
||||
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;
|
||||
}
|
||||
setRegisters.removeAll(usedRegisters);
|
||||
|
||||
// check that the setRegisters are all hidden, meaning don't care.
|
||||
for (Iterator<Varnode> iterator = setRegisters.iterator(); iterator.hasNext();) {
|
||||
Varnode rvnode = iterator.next();
|
||||
Register reg = program.getRegister(rvnode);
|
||||
// the register pcode access could have fallen in the middle of a valid register
|
||||
// thus no register will exist at the varnode
|
||||
if (reg != null && reg.isHidden()) {
|
||||
iterator.remove();
|
||||
// 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
|
||||
Register PC = program.getLanguage().getProgramCounter();
|
||||
if (PC != null) {
|
||||
usedRegisters.add(new Varnode(PC.getAddress(), PC.getMinimumByteSize()));
|
||||
}
|
||||
setRegisters.removeAll(usedRegisters);
|
||||
|
||||
// if not checking for sideEffect registers set, or there are no side-effects
|
||||
if (!checkForSideEffects || setRegisters.size() == 0) {
|
||||
flowingAddr = getFlowingAddress(program, instr);
|
||||
// check that the setRegisters are all hidden, meaning don't care.
|
||||
for (Iterator<Varnode> iterator = setRegisters.iterator(); iterator.hasNext();) {
|
||||
Varnode rvnode = iterator.next();
|
||||
Register reg = program.getRegister(rvnode);
|
||||
// the register pcode access could have fallen in the middle of a valid register
|
||||
// thus no register will exist at the varnode
|
||||
if (reg != null && reg.isHidden()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
Address flowingAddr = null;
|
||||
|
||||
// if not checking for sideEffect registers set, or there are no side-effects
|
||||
if (!checkForSideEffects || setRegisters.size() == 0) {
|
||||
flowingAddr = getFlowingAddress(program, instr);
|
||||
}
|
||||
|
||||
return flowingAddr;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -72,22 +72,30 @@ class EditThunkFunctionAction extends ProgramContextAction {
|
|||
if (func == null) {
|
||||
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
|
||||
ThunkReferenceAddressDialog dialog = new ThunkReferenceAddressDialog(funcPlugin.getTool());
|
||||
dialog.showDialog(program, func.getEntryPoint(),
|
||||
refFunc != null ? refFunc.getSymbol() : null);
|
||||
dialog.showDialog(program, funcEntry, refSymbol);
|
||||
Symbol referencedSymbol = dialog.getSymbol();
|
||||
Address referencedFunctionAddr = dialog.getAddress();
|
||||
|
||||
CreateThunkFunctionCmd cmd;
|
||||
if (referencedSymbol != null) {
|
||||
cmd = new CreateThunkFunctionCmd(func.getEntryPoint(), null, referencedSymbol);
|
||||
cmd = new CreateThunkFunctionCmd(funcEntry, null, referencedSymbol);
|
||||
}
|
||||
else if (referencedFunctionAddr != null) {
|
||||
cmd = new CreateThunkFunctionCmd(func.getEntryPoint(), null, referencedFunctionAddr);
|
||||
cmd = new CreateThunkFunctionCmd(funcEntry, null, referencedFunctionAddr);
|
||||
}
|
||||
else {
|
||||
return; // cancelled
|
||||
|
|
|
@ -36,4 +36,31 @@
|
|||
<possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here -->
|
||||
</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>
|
||||
|
|
|
@ -35,5 +35,32 @@
|
|||
<data>0x21 0x00 0x80 0x4e</data> <!-- blrl -->
|
||||
<possiblefuncstart validcode="function" label="__get_pc_thunk_lr" /> <!-- must be a function here -->
|
||||
</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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue