WIP Ghidra plugin
This commit is contained in:
parent
b5805d39d4
commit
5638734828
Binary file not shown.
|
@ -11,15 +11,18 @@ import ghidra.program.util.ProgramEvent;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.util.*;
|
import ghidra.program.util.*;
|
||||||
|
import ghidra.framework.cmd.Command;
|
||||||
|
import ghidra.framework.model.TransactionInfo;
|
||||||
|
|
||||||
@PluginInfo(
|
@PluginInfo(
|
||||||
status = PluginStatus.STABLE,
|
status = PluginStatus.STABLE,
|
||||||
packageName = "SymbolLogger",
|
packageName = "SymbolLogger",
|
||||||
category = PluginCategoryNames.COMMON,
|
category = PluginCategoryNames.COMMON,
|
||||||
shortDescription = "Logs symbol and function renames",
|
shortDescription = "Logs symbol and function renames",
|
||||||
description = "A plugin that monitors and logs all symbol and function rename events to the console",
|
description = "A plugin that monitors and logs all symbol and function rename events to the console, including undo/redo context",
|
||||||
servicesRequired = {},
|
servicesRequired = {},
|
||||||
servicesProvided = {}
|
servicesProvided = {}
|
||||||
)
|
)
|
||||||
|
@ -63,9 +66,44 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the context of the current operation (direct action, undo, or redo)
|
||||||
|
*/
|
||||||
|
private String getOperationContext() {
|
||||||
|
try {
|
||||||
|
Program program = getCurrentProgram();
|
||||||
|
if (program != null) {
|
||||||
|
TransactionInfo currentTransaction = program.getCurrentTransactionInfo();
|
||||||
|
if (currentTransaction != null) {
|
||||||
|
String description = currentTransaction.getDescription();
|
||||||
|
if (description != null) {
|
||||||
|
if (description.startsWith("Undo")) {
|
||||||
|
return "[UNDO] ";
|
||||||
|
} else if (description.startsWith("Redo")) {
|
||||||
|
return "[REDO] ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Silently handle any exceptions in context detection
|
||||||
|
}
|
||||||
|
return ""; // Direct user action (no prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enhanced logging method that includes undo/redo context
|
||||||
|
*/
|
||||||
|
private void logWithContext(String message) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
Msg.info(this, context + message);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleProgramChange(ProgramChangeRecord record) {
|
private void handleProgramChange(ProgramChangeRecord record) {
|
||||||
ProgramEvent eventType = (ProgramEvent)record.getEventType();
|
ProgramEvent eventType = (ProgramEvent)record.getEventType();
|
||||||
|
|
||||||
|
Msg.info(this, "Event: " + record.toString());
|
||||||
|
|
||||||
// Handle symbol rename events
|
// Handle symbol rename events
|
||||||
if (eventType == ProgramEvent.SYMBOL_RENAMED) {
|
if (eventType == ProgramEvent.SYMBOL_RENAMED) {
|
||||||
handleSymbolRenamed(record);
|
handleSymbolRenamed(record);
|
||||||
|
@ -102,6 +140,27 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
else if (eventType == ProgramEvent.FUNCTION_CHANGED) {
|
else if (eventType == ProgramEvent.FUNCTION_CHANGED) {
|
||||||
handleFunctionSignatureChanged(record);
|
handleFunctionSignatureChanged(record);
|
||||||
}
|
}
|
||||||
|
// Handle transaction events for better undo/redo tracking
|
||||||
|
// else if (eventType == ProgramEvent..TRANSACTION_STARTED) {
|
||||||
|
// handleTransactionStarted(record);
|
||||||
|
// }
|
||||||
|
// else if (eventType == ProgramEvent.TRANSACTION_ENDED) {
|
||||||
|
// handleTransactionEnded(record);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTransactionStarted(ProgramChangeRecord record) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
if (!context.isEmpty()) {
|
||||||
|
logWithContext("TRANSACTION STARTED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTransactionEnded(ProgramChangeRecord record) {
|
||||||
|
String context = getOperationContext();
|
||||||
|
if (!context.isEmpty()) {
|
||||||
|
logWithContext("TRANSACTION ENDED");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbolRenamed(ProgramChangeRecord record) {
|
private void handleSymbolRenamed(ProgramChangeRecord record) {
|
||||||
|
@ -111,7 +170,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
String newName = (newValue != null) ? newValue.toString() : "null";
|
String newName = (newValue != null) ? newValue.toString() : "null";
|
||||||
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
||||||
|
|
||||||
Msg.info(this, String.format("SYMBOL RENAMED: '%s' -> '%s' at address %s",
|
logWithContext(String.format("SYMBOL RENAMED: '%s' -> '%s' at address %s",
|
||||||
oldName, newName, record.getStart()));
|
oldName, newName, record.getStart()));
|
||||||
|
|
||||||
// Try to get additional information about the symbol
|
// Try to get additional information about the symbol
|
||||||
|
@ -124,14 +183,14 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
for (Symbol symbol : symbols) {
|
for (Symbol symbol : symbols) {
|
||||||
if (symbol.getName().equals(newName)) {
|
if (symbol.getName().equals(newName)) {
|
||||||
String symbolType = getSymbolTypeDescription(symbol);
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
Msg.info(this, String.format(" Symbol type: %s, Namespace: %s",
|
logWithContext(String.format(" Symbol type: %s, Namespace: %s",
|
||||||
symbolType, symbol.getParentNamespace().getName()));
|
symbolType, symbol.getParentNamespace().getName()));
|
||||||
|
|
||||||
// If it's a function, log additional function details
|
// If it's a function, log additional function details
|
||||||
if (symbol.getSymbolType() == SymbolType.FUNCTION) {
|
if (symbol.getSymbolType() == SymbolType.FUNCTION) {
|
||||||
Function function = (Function) symbol.getObject();
|
Function function = (Function) symbol.getObject();
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
Msg.info(this, String.format(" Function signature: %s",
|
logWithContext(String.format(" Function signature: %s",
|
||||||
function.getPrototypeString(false, false)));
|
function.getPrototypeString(false, false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,7 +214,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
|
|
||||||
// Check for name changes
|
// Check for name changes
|
||||||
if (!newFunc.getName().equals(oldFunc.getName())) {
|
if (!newFunc.getName().equals(oldFunc.getName())) {
|
||||||
Msg.info(this, String.format("FUNCTION RENAMED: '%s' -> '%s' at address %s",
|
logWithContext(String.format("FUNCTION RENAMED: '%s' -> '%s' at address %s",
|
||||||
oldFunc.getName(), newFunc.getName(), newFunc.getEntryPoint()));
|
oldFunc.getName(), newFunc.getName(), newFunc.getEntryPoint()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,18 +222,18 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
String oldSignature = oldFunc.getPrototypeString(false, false);
|
String oldSignature = oldFunc.getPrototypeString(false, false);
|
||||||
String newSignature = newFunc.getPrototypeString(false, false);
|
String newSignature = newFunc.getPrototypeString(false, false);
|
||||||
if (!oldSignature.equals(newSignature)) {
|
if (!oldSignature.equals(newSignature)) {
|
||||||
Msg.info(this, String.format("FUNCTION SIGNATURE CHANGED at address %s:", newFunc.getEntryPoint()));
|
logWithContext(String.format("FUNCTION SIGNATURE CHANGED at address %s:", newFunc.getEntryPoint()));
|
||||||
Msg.info(this, String.format(" Old: %s", oldSignature));
|
logWithContext(String.format(" Old: %s", oldSignature));
|
||||||
Msg.info(this, String.format(" New: %s", newSignature));
|
logWithContext(String.format(" New: %s", newSignature));
|
||||||
|
|
||||||
// Log specific changes
|
// Log specific changes
|
||||||
logFunctionSignatureDetails(oldFunc, newFunc);
|
logFunctionSignatureDetails(oldFunc, newFunc);
|
||||||
}
|
}
|
||||||
} else if (newValue instanceof Function) {
|
} else if (newValue instanceof Function) {
|
||||||
Function function = (Function) newValue;
|
Function function = (Function) newValue;
|
||||||
Msg.info(this, String.format("FUNCTION MODIFIED: %s at address %s",
|
logWithContext(String.format("FUNCTION MODIFIED: %s at address %s",
|
||||||
function.getName(), function.getEntryPoint()));
|
function.getName(), function.getEntryPoint()));
|
||||||
Msg.info(this, String.format(" Signature: %s", function.getPrototypeString(false, false)));
|
logWithContext(String.format(" Signature: %s", function.getPrototypeString(false, false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,23 +246,23 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
Object newValue = record.getNewValue();
|
Object newValue = record.getNewValue();
|
||||||
Object oldValue = record.getOldValue();
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
Msg.info(this, String.format("DATA TYPE CHANGED at address %s", record.getStart()));
|
logWithContext(String.format("DATA TYPE CHANGED at address %s", record.getStart()));
|
||||||
|
|
||||||
if (oldValue != null && newValue != null) {
|
if (oldValue != null && newValue != null) {
|
||||||
Msg.info(this, String.format(" Old type: %s", oldValue.toString()));
|
logWithContext(String.format(" Old type: %s", oldValue.toString()));
|
||||||
Msg.info(this, String.format(" New type: %s", newValue.toString()));
|
logWithContext(String.format(" New type: %s", newValue.toString()));
|
||||||
} else if (newValue != null) {
|
} else if (newValue != null) {
|
||||||
Msg.info(this, String.format(" Type set to: %s", newValue.toString()));
|
logWithContext(String.format(" Type set to: %s", newValue.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get more context about the data type change
|
// Try to get more context about the data type change
|
||||||
try {
|
try {
|
||||||
Program program = getCurrentProgram();
|
Program program = getCurrentProgram();
|
||||||
if (program != null && record.getStart() != null) {
|
if (program != null && record.getStart() != null) {
|
||||||
ghidra.program.model.data.Data data = program.getListing().getDataAt(record.getStart());
|
Data data = program.getListing().getDataAt(record.getStart());
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
Msg.info(this, String.format(" Data label: %s", data.getLabel()));
|
logWithContext(String.format(" Data label: %s", data.getLabel()));
|
||||||
Msg.info(this, String.format(" Data type: %s", data.getDataType().getName()));
|
logWithContext(String.format(" Data type: %s", data.getDataType().getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -214,18 +273,18 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
private void handleDataTypeAdded(ProgramChangeRecord record) {
|
private void handleDataTypeAdded(ProgramChangeRecord record) {
|
||||||
Object newValue = record.getNewValue();
|
Object newValue = record.getNewValue();
|
||||||
|
|
||||||
Msg.info(this, String.format("DATA TYPE ADDED at address %s", record.getStart()));
|
logWithContext(String.format("DATA TYPE ADDED at address %s", record.getStart()));
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
Msg.info(this, String.format(" Type: %s", newValue.toString()));
|
logWithContext(String.format(" Type: %s", newValue.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDataTypeRemoved(ProgramChangeRecord record) {
|
private void handleDataTypeRemoved(ProgramChangeRecord record) {
|
||||||
Object oldValue = record.getOldValue();
|
Object oldValue = record.getOldValue();
|
||||||
|
|
||||||
Msg.info(this, String.format("DATA TYPE REMOVED at address %s", record.getStart()));
|
logWithContext(String.format("DATA TYPE REMOVED at address %s", record.getStart()));
|
||||||
if (oldValue != null) {
|
if (oldValue != null) {
|
||||||
Msg.info(this, String.format(" Removed type: %s", oldValue.toString()));
|
logWithContext(String.format(" Removed type: %s", oldValue.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +295,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
String newName = (newValue != null) ? newValue.toString() : "null";
|
String newName = (newValue != null) ? newValue.toString() : "null";
|
||||||
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
String oldName = (oldValue != null) ? oldValue.toString() : "null";
|
||||||
|
|
||||||
Msg.info(this, String.format("DATA TYPE RENAMED: '%s' -> '%s' at address %s",
|
logWithContext(String.format("DATA TYPE RENAMED: '%s' -> '%s' at address %s",
|
||||||
oldName, newName, record.getStart()));
|
oldName, newName, record.getStart()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +303,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
try {
|
try {
|
||||||
// Check return type changes
|
// Check return type changes
|
||||||
if (!oldFunc.getReturnType().equals(newFunc.getReturnType())) {
|
if (!oldFunc.getReturnType().equals(newFunc.getReturnType())) {
|
||||||
Msg.info(this, String.format(" Return type changed: %s -> %s",
|
logWithContext(String.format(" Return type changed: %s -> %s",
|
||||||
oldFunc.getReturnType().getName(), newFunc.getReturnType().getName()));
|
oldFunc.getReturnType().getName(), newFunc.getReturnType().getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +311,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
int oldParamCount = oldFunc.getParameterCount();
|
int oldParamCount = oldFunc.getParameterCount();
|
||||||
int newParamCount = newFunc.getParameterCount();
|
int newParamCount = newFunc.getParameterCount();
|
||||||
if (oldParamCount != newParamCount) {
|
if (oldParamCount != newParamCount) {
|
||||||
Msg.info(this, String.format(" Parameter count changed: %d -> %d",
|
logWithContext(String.format(" Parameter count changed: %d -> %d",
|
||||||
oldParamCount, newParamCount));
|
oldParamCount, newParamCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,28 +323,28 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
||||||
|
|
||||||
if (!oldParam.getDataType().equals(newParam.getDataType())) {
|
if (!oldParam.getDataType().equals(newParam.getDataType())) {
|
||||||
Msg.info(this, String.format(" Parameter %d type changed: %s -> %s",
|
logWithContext(String.format(" Parameter %d type changed: %s -> %s",
|
||||||
i, oldParam.getDataType().getName(), newParam.getDataType().getName()));
|
i, oldParam.getDataType().getName(), newParam.getDataType().getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oldParam.getName().equals(newParam.getName())) {
|
if (!oldParam.getName().equals(newParam.getName())) {
|
||||||
Msg.info(this, String.format(" Parameter %d name changed: %s -> %s",
|
logWithContext(String.format(" Parameter %d name changed: %s -> %s",
|
||||||
i, oldParam.getName(), newParam.getName()));
|
i, oldParam.getName(), newParam.getName()));
|
||||||
}
|
}
|
||||||
} else if (i < newParamCount) {
|
} else if (i < newParamCount) {
|
||||||
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i);
|
||||||
Msg.info(this, String.format(" Parameter %d added: %s %s",
|
logWithContext(String.format(" Parameter %d added: %s %s",
|
||||||
i, newParam.getDataType().getName(), newParam.getName()));
|
i, newParam.getDataType().getName(), newParam.getName()));
|
||||||
} else {
|
} else {
|
||||||
ghidra.program.model.listing.Parameter oldParam = oldFunc.getParameter(i);
|
ghidra.program.model.listing.Parameter oldParam = oldFunc.getParameter(i);
|
||||||
Msg.info(this, String.format(" Parameter %d removed: %s %s",
|
logWithContext(String.format(" Parameter %d removed: %s %s",
|
||||||
i, oldParam.getDataType().getName(), oldParam.getName()));
|
i, oldParam.getDataType().getName(), oldParam.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check calling convention changes
|
// Check calling convention changes
|
||||||
if (!oldFunc.getCallingConventionName().equals(newFunc.getCallingConventionName())) {
|
if (!oldFunc.getCallingConventionName().equals(newFunc.getCallingConventionName())) {
|
||||||
Msg.info(this, String.format(" Calling convention changed: %s -> %s",
|
logWithContext(String.format(" Calling convention changed: %s -> %s",
|
||||||
oldFunc.getCallingConventionName(), newFunc.getCallingConventionName()));
|
oldFunc.getCallingConventionName(), newFunc.getCallingConventionName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +358,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
if (newValue instanceof Symbol) {
|
if (newValue instanceof Symbol) {
|
||||||
Symbol symbol = (Symbol) newValue;
|
Symbol symbol = (Symbol) newValue;
|
||||||
String symbolType = getSymbolTypeDescription(symbol);
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
Msg.info(this, String.format("SYMBOL ADDED: '%s' (%s) at address %s",
|
logWithContext(String.format("SYMBOL ADDED: '%s' (%s) at address %s",
|
||||||
symbol.getName(), symbolType, symbol.getAddress()));
|
symbol.getName(), symbolType, symbol.getAddress()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +368,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj
|
||||||
if (oldValue instanceof Symbol) {
|
if (oldValue instanceof Symbol) {
|
||||||
Symbol symbol = (Symbol) oldValue;
|
Symbol symbol = (Symbol) oldValue;
|
||||||
String symbolType = getSymbolTypeDescription(symbol);
|
String symbolType = getSymbolTypeDescription(symbol);
|
||||||
Msg.info(this, String.format("SYMBOL REMOVED: '%s' (%s) at address %s",
|
logWithContext(String.format("SYMBOL REMOVED: '%s' (%s) at address %s",
|
||||||
symbol.getName(), symbolType, symbol.getAddress()));
|
symbol.getName(), symbolType, symbol.getAddress()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue