Merge remote-tracking branch 'origin/Ghidra_11.4'

This commit is contained in:
ghidra1
2025-06-06 18:50:01 -04:00
183 changed files with 3088 additions and 3278 deletions
@@ -1,13 +1,12 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* 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.
@@ -18,17 +17,16 @@
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.*;
public class AddCommentToProgramScript extends GhidraScript {
@Override
public void run() throws Exception {
Address minAddress = currentProgram.getMinAddress();
Listing listing = currentProgram.getListing();
CodeUnit codeUnit = listing.getCodeUnitAt( minAddress );
codeUnit.setComment( CodeUnit.PLATE_COMMENT, "AddCommentToProgramScript - This is an added comment!" );
}
@Override
public void run() throws Exception {
Address minAddress = currentProgram.getMinAddress();
Listing listing = currentProgram.getListing();
CodeUnit codeUnit = listing.getCodeUnitAt(minAddress);
codeUnit.setComment(CommentType.PLATE,
"AddCommentToProgramScript - This is an added comment!");
}
}
@@ -49,7 +49,6 @@ public class AutoRenameSimpleLabels extends GhidraScript {
@Override
public void run() throws Exception {
String tmpString = "\nScript: AutoRenameSimpleLabels() \n";
//get listing of symbols
SymbolIterator iter = currentProgram.getSymbolTable().getAllSymbols(true);
@@ -147,15 +146,13 @@ public class AutoRenameSimpleLabels extends GhidraScript {
// now also propogate the repeatable comment up as well
String comment = currentProgram.getListing().getComment(CommentType.REPEATABLE,
operand_addr);
if (comment != null) {
if (currentProgram.getListing().getComment(CommentType.REPEATABLE,
startAddr) == null) {
//println("updating comment for " + operand +" is " + comment);
currentProgram.getListing()
.setComment(startAddr, CommentType.REPEATABLE, comment);
}
String comment =
currentProgram.getListing().getComment(CommentType.REPEATABLE, operand_addr);
if (comment != null && currentProgram.getListing()
.getComment(CommentType.REPEATABLE, startAddr) == null) {
//println("updating comment for " + operand +" is " + comment);
currentProgram.getListing()
.setComment(startAddr, CommentType.REPEATABLE, comment);
}
}
}
@@ -24,17 +24,16 @@ import ghidra.program.model.listing.*;
public class DeleteDeadDefaultPlatesScript extends GhidraScript {
private static String DEAD_PLATE = " DEAD";
/* (non-Javadoc)
* @see ghidra.app.script.GhidraScript#run()
*/
@Override
public void run() throws Exception {
public void run() throws Exception {
Listing listing = currentProgram.getListing();
AddressSetView set = currentProgram.getMemory();
if (currentSelection != null && !currentSelection.isEmpty()) {
set = currentSelection;
}
int updateCount=0;
int updateCount = 0;
AddressIterator iter = listing.getCommentAddressIterator(CommentType.PLATE, set, true);
while (iter.hasNext()) {
Address addr = iter.next();
@@ -48,7 +47,7 @@ public class DeleteDeadDefaultPlatesScript extends GhidraScript {
}
}
if (updateCount > 0) {
String cmt = updateCount > 1? "comments" : "comment";
String cmt = updateCount > 1 ? "comments" : "comment";
println("Removed " + updateCount + " default plate " + cmt + ".");
}
else {
@@ -24,17 +24,16 @@ import ghidra.program.model.listing.*;
public class DeleteEmptyPlateCommentsScript extends GhidraScript {
private static String EMPTY_PLATE = "";
/* (non-Javadoc)
* @see ghidra.app.script.GhidraScript#run()
*/
@Override
public void run() throws Exception {
public void run() throws Exception {
Listing listing = currentProgram.getListing();
AddressSetView set = currentProgram.getMemory();
if (currentSelection != null && !currentSelection.isEmpty()) {
set = currentSelection;
}
int updateCount=0;
int updateCount = 0;
AddressIterator iter = listing.getCommentAddressIterator(CommentType.PLATE, set, true);
while (iter.hasNext()) {
Address addr = iter.next();
@@ -48,7 +47,7 @@ public class DeleteEmptyPlateCommentsScript extends GhidraScript {
}
}
if (updateCount > 0) {
String cmt = updateCount > 1? "comments" : "comment";
String cmt = updateCount > 1 ? "comments" : "comment";
println("Removed " + updateCount + " emtpy plate " + cmt + ".");
}
else {
@@ -24,17 +24,16 @@ import ghidra.program.model.listing.*;
public class DeleteExitCommentsScript extends GhidraScript {
private static String EXIT_COMMENT = " Exit **********\r\n ";
/* (non-Javadoc)
* @see ghidra.app.script.GhidraScript#run()
*/
@Override
public void run() throws Exception {
public void run() throws Exception {
Listing listing = currentProgram.getListing();
AddressSetView set = currentProgram.getMemory();
if (currentSelection != null && !currentSelection.isEmpty()) {
set = currentSelection;
}
int updateCount=0;
int updateCount = 0;
AddressIterator iter = listing.getCommentAddressIterator(CommentType.POST, set, true);
while (iter.hasNext()) {
Address addr = iter.next();
@@ -46,7 +45,7 @@ public class DeleteExitCommentsScript extends GhidraScript {
}
}
if (updateCount > 0) {
String cmt = updateCount > 1? "comments" : "comment";
String cmt = updateCount > 1 ? "comments" : "comment";
println("Removed " + updateCount + " exit post " + cmt + ".");
}
else {
@@ -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.
@@ -27,6 +27,7 @@ import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.CommentType;
import ghidra.program.model.mem.Memory;
import ghidra.util.exception.CancelledException;
@@ -72,14 +73,14 @@ public class LocateMemoryAddressesForFileOffset extends GhidraScript {
println("File offset " + Long.toHexString(fileOffset) +
" is associated with memory block:address " + memBlockName + ":" + addr.toString());
CodeUnit myCodeUnit = currentProgram.getListing().getCodeUnitContaining(addr);
String comment = myCodeUnit.getComment(0);
String comment = myCodeUnit.getComment(CommentType.EOL);
if (comment == null) {
myCodeUnit.setComment(0,
myCodeUnit.setComment(CommentType.EOL,
this.getScriptName() + ": File offset: " + Long.toHexString(fileOffset) +
", Memory block:address " + memBlockName + ":" + addr.toString());
}
else {
myCodeUnit.setComment(0,
myCodeUnit.setComment(CommentType.EOL,
comment + ", " + this.getScriptName() + ": File offset: " +
Long.toHexString(fileOffset) + ", Memory block:address " + memBlockName + ":" +
addr.toString());
@@ -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.
@@ -48,8 +48,7 @@ import ghidra.program.model.block.CodeBlock;
import ghidra.program.model.block.PartitionCodeSubModel;
import ghidra.program.model.data.DataType;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.*;
@@ -180,7 +179,8 @@ public class MultiInstructionMemReference extends GhidraScript {
public boolean evaluateReference(VarnodeContext context, Instruction instr, int pcodeop,
Address address, int size, DataType dataType, RefType refType) {
return super.evaluateReference(context, instr, pcodeop, address, size, dataType, refType);
return super.evaluateReference(context, instr, pcodeop, address, size, dataType,
refType);
}
private boolean checkInstructionMatch(final int opIdx, boolean input,
@@ -287,7 +287,7 @@ public class MultiInstructionMemReference extends GhidraScript {
}
Address lastSetLocation = context.getLastSetLocation(singleRegister, null);
String comment = instr.getComment(Instruction.EOL_COMMENT);
String comment = instr.getComment(CommentType.EOL);
if (comment == null) {
comment = "";
}
@@ -300,7 +300,7 @@ public class MultiInstructionMemReference extends GhidraScript {
return false;
}
comment = (comment.trim().length() == 0 ? markup : comment + "\n" + markup);
instr.setComment(Instruction.EOL_COMMENT, comment);
instr.setComment(CommentType.EOL, comment);
return false;
}
@@ -18,168 +18,140 @@
// function's plate comment.
//@category Analysis
import java.util.*;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.*;
public class RegisterTouchesPerFunction extends GhidraScript
{
private final static String DIVIDER = "*************************************************************\r\n";
public class RegisterTouchesPerFunction extends GhidraScript {
@Override
public void run() throws Exception
{
Listing l = this.currentProgram.getListing();
private final static String DIVIDER =
"*************************************************************\r\n";
if (this.askYesNo("Function Analysis - Register Touches",
"Analyze complete listing?"))
{
FunctionIterator fi = l.getFunctions(true);
while (fi.hasNext() && !monitor.isCancelled())
{
doAnalysis(l, fi.next());
}
}
else
{
doAnalysis(l, l.getFunctionContaining(this.currentAddress));
}
}
@Override
public void run() throws Exception {
Listing l = this.currentProgram.getListing();
private void doAnalysis(Listing list, Function func)
{
if (func == null) {
println("No function to analyze.");
return;
}
HashSet<String> affected, accessed;
Vector<String> restored;
Stack<String> pushPops;
boolean reviewRestored = false;
Instruction inst;
InstructionIterator iIter;
monitor.setMessage("Analyzing registers in " + func.getName());
if (this.askYesNo("Function Analysis - Register Touches", "Analyze complete listing?")) {
FunctionIterator fi = l.getFunctions(true);
while (fi.hasNext() && !monitor.isCancelled()) {
doAnalysis(l, fi.next());
}
}
else {
doAnalysis(l, l.getFunctionContaining(this.currentAddress));
}
}
String comment = list.getComment(CommentType.PLATE, func.getBody().getMinAddress());
private void doAnalysis(Listing list, Function func) {
if (func == null) {
println("No function to analyze.");
return;
}
HashSet<String> affected, accessed;
Vector<String> restored;
Stack<String> pushPops;
boolean reviewRestored = false;
Instruction inst;
InstructionIterator iIter;
if (comment != null && comment.indexOf("TOUCHED REGISTER SUMMARY") > -1)
return;
monitor.setMessage("Analyzing registers in " + func.getName());
pushPops = new Stack<String>();
affected = new HashSet<String>();
accessed = new HashSet<String>();
restored = new Vector<String>();
String comment = list.getComment(CommentType.PLATE, func.getBody().getMinAddress());
if (comment != null && comment.indexOf("TOUCHED REGISTER SUMMARY") > -1)
return;
iIter = list.getInstructions(func.getBody(), true);
while (iIter.hasNext() && !monitor.isCancelled())
{
inst = iIter.next();
pushPops = new Stack<String>();
affected = new HashSet<String>();
accessed = new HashSet<String>();
restored = new Vector<String>();
Object o[] = inst.getResultObjects();
for (int i = 0; i < o.length; i++)
{
if (o[i] instanceof Register)
{
String name = ((Register) o[i]).getName();
iIter = list.getInstructions(func.getBody(), true);
if (inst.getMnemonicString().equalsIgnoreCase("pop"))
{
if (!name.equalsIgnoreCase("mult_addr")
&& !name.equalsIgnoreCase("sp"))
{
if (pushPops.size() > 0)
{
restored.add(pushPops.pop() + "->" + name);
}
else
{
reviewRestored = true;
}
}
}
else
{
affected.add(name);
}
}
}
o = inst.getInputObjects();
while (iIter.hasNext() && !monitor.isCancelled()) {
inst = iIter.next();
for (int i = 0; i < o.length; i++)
{
if (o[i] instanceof Register)
{
String name = ((Register) o[i]).getName();
if (inst.getMnemonicString().equalsIgnoreCase("push"))
{
if (!name.equalsIgnoreCase("mult_addr")
&& !name.equalsIgnoreCase("sp"))
{
pushPops.push(name);
}
}
else
{
accessed.add(name);
}
}
}
}
Object o[] = inst.getResultObjects();
for (Object element : o) {
if (element instanceof Register) {
String name = ((Register) element).getName();
StringBuffer buffer = new StringBuffer();
if (comment != null) {
buffer.append(comment);
buffer.append("\r\n");
buffer.append(DIVIDER);
}
buffer.append("TOUCHED REGISTER SUMMARY:\r\n");
buffer.append(DIVIDER);
buffer.append("Register(s) Affected:\r\n");
buffer.append(getString(affected, 8));
buffer.append(DIVIDER);
buffer.append("Register(s) Accessed:\r\n");
buffer.append(getString(accessed, 8));
buffer.append(DIVIDER);
buffer.append("Register(s) Restored:\r\n");
buffer.append(getString(restored, 4));
if (inst.getMnemonicString().equalsIgnoreCase("pop")) {
if (!name.equalsIgnoreCase("mult_addr") && !name.equalsIgnoreCase("sp")) {
if (pushPops.size() > 0) {
restored.add(pushPops.pop() + "->" + name);
}
else {
reviewRestored = true;
}
}
}
else {
affected.add(name);
}
}
}
o = inst.getInputObjects();
if(reviewRestored)
{
buffer.append("##Review - due to branches this list may not be accurate\r\n");
println(func.getName() + " - Review - due to branches this list may not be accurate");
}
buffer.append(DIVIDER);
for (Object element : o) {
if (element instanceof Register) {
String name = ((Register) element).getName();
if (inst.getMnemonicString().equalsIgnoreCase("push")) {
if (!name.equalsIgnoreCase("mult_addr") && !name.equalsIgnoreCase("sp")) {
pushPops.push(name);
}
}
else {
accessed.add(name);
}
}
}
}
if (pushPops.size() > 0)
{
StringBuffer buffer = new StringBuffer();
if (comment != null) {
buffer.append(comment);
buffer.append("\r\n");
buffer.append(DIVIDER);
}
buffer.append("TOUCHED REGISTER SUMMARY:\r\n");
buffer.append(DIVIDER);
buffer.append("Register(s) Affected:\r\n");
buffer.append(getString(affected, 8));
buffer.append(DIVIDER);
buffer.append("Register(s) Accessed:\r\n");
buffer.append(getString(accessed, 8));
buffer.append(DIVIDER);
buffer.append("Register(s) Restored:\r\n");
buffer.append(getString(restored, 4));
buffer.append("Registers Remaining on Stack:\r\n");
buffer.append(" "+getString(pushPops, 8));
}
if (reviewRestored) {
buffer.append("##Review - due to branches this list may not be accurate\r\n");
println(func.getName() + " - Review - due to branches this list may not be accurate");
}
buffer.append(DIVIDER);
if (pushPops.size() > 0) {
buffer.append("Registers Remaining on Stack:\r\n");
buffer.append(" " + getString(pushPops, 8));
}
list.setComment(func.getEntryPoint(), CommentType.PLATE, buffer.toString());
}
}
private String getString(Collection<String> c, int itemsPerLine)
{
TreeSet<Object> ts = new TreeSet<Object>(c);
String temp = ts.toString();
temp = temp.substring(1, temp.length() - 1);
int i = 0;
int commaCount = 0;
while ((i = temp.indexOf(',', i + 1)) >= 0)
{
commaCount++;
if (commaCount % itemsPerLine == 0)
temp = temp.substring(0, i + 1) + "\r\n"
+ temp.substring(i + 1).trim();
}
private String getString(Collection<String> c, int itemsPerLine) {
TreeSet<Object> ts = new TreeSet<Object>(c);
String temp = ts.toString();
temp = temp.substring(1, temp.length() - 1);
int i = 0;
int commaCount = 0;
while ((i = temp.indexOf(',', i + 1)) >= 0) {
commaCount++;
if (commaCount % itemsPerLine == 0)
temp = temp.substring(0, i + 1) + "\r\n" + temp.substring(i + 1).trim();
}
return temp + "\r\n";
}
return temp + "\r\n";
}
}
@@ -60,8 +60,8 @@ public class ZapBCTRScript extends GhidraScript {
}
// first try input as class and search for symbol "<class>::__vtbl"
List<Symbol> symbols = currentProgram.getSymbolTable().getSymbols("__vtbl",
getNamespace(null, classNameOrAddr));
List<Symbol> symbols = currentProgram.getSymbolTable()
.getSymbols("__vtbl", getNamespace(null, classNameOrAddr));
// if symbol found, then vtblAddr is the symbol's address
if (symbols.size() == 1) {
vtblAddr = symbols.get(0).getAddress();
@@ -100,8 +100,8 @@ public class ZapBCTRScript extends GhidraScript {
// insert funcName as EOL comment and
// add a mnemonic ref from instAddr to funcAddr
listing.setComment(instAddr, CommentType.EOL, funcName);
listing.getInstructionAt(instAddr).addMnemonicReference(funcAddr, RefType.COMPUTED_CALL,
SourceType.USER_DEFINED);
listing.getInstructionAt(instAddr)
.addMnemonicReference(funcAddr, RefType.COMPUTED_CALL, SourceType.USER_DEFINED);
/* old code that replaces the 'bctr' with a 'bl'
int code = 0x48000001 | ((int)displacement & 0x3ffffff);