diff --git a/GhidraPlugin/bin/main/ghidraplugin/SymbolRenameLoggerPlugin.class b/GhidraPlugin/bin/main/ghidraplugin/SymbolRenameLoggerPlugin.class index 03c5934a..c08cd72a 100644 Binary files a/GhidraPlugin/bin/main/ghidraplugin/SymbolRenameLoggerPlugin.class and b/GhidraPlugin/bin/main/ghidraplugin/SymbolRenameLoggerPlugin.class differ diff --git a/GhidraPlugin/src/main/java/ghidraplugin/SymbolRenameLoggerPlugin.java b/GhidraPlugin/src/main/java/ghidraplugin/SymbolRenameLoggerPlugin.java index 4f0c3cf6..79e0dfbe 100644 --- a/GhidraPlugin/src/main/java/ghidraplugin/SymbolRenameLoggerPlugin.java +++ b/GhidraPlugin/src/main/java/ghidraplugin/SymbolRenameLoggerPlugin.java @@ -11,15 +11,18 @@ import ghidra.program.util.ProgramEvent; import ghidra.util.Msg; import ghidra.framework.model.*; import ghidra.program.model.symbol.*; +import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Function; import ghidra.program.util.*; +import ghidra.framework.cmd.Command; +import ghidra.framework.model.TransactionInfo; @PluginInfo( status = PluginStatus.STABLE, packageName = "SymbolLogger", category = PluginCategoryNames.COMMON, 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 = {}, 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) { ProgramEvent eventType = (ProgramEvent)record.getEventType(); + Msg.info(this, "Event: " + record.toString()); + // Handle symbol rename events if (eventType == ProgramEvent.SYMBOL_RENAMED) { handleSymbolRenamed(record); @@ -102,6 +140,27 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj else if (eventType == ProgramEvent.FUNCTION_CHANGED) { 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) { @@ -111,7 +170,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj String newName = (newValue != null) ? newValue.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())); // Try to get additional information about the symbol @@ -124,14 +183,14 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj for (Symbol symbol : symbols) { if (symbol.getName().equals(newName)) { 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())); // If it's a function, log additional function details if (symbol.getSymbolType() == SymbolType.FUNCTION) { Function function = (Function) symbol.getObject(); if (function != null) { - Msg.info(this, String.format(" Function signature: %s", + logWithContext(String.format(" Function signature: %s", function.getPrototypeString(false, false))); } } @@ -155,7 +214,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj // Check for name changes 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())); } @@ -163,18 +222,18 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj String oldSignature = oldFunc.getPrototypeString(false, false); String newSignature = newFunc.getPrototypeString(false, false); if (!oldSignature.equals(newSignature)) { - Msg.info(this, String.format("FUNCTION SIGNATURE CHANGED at address %s:", newFunc.getEntryPoint())); - Msg.info(this, String.format(" Old: %s", oldSignature)); - Msg.info(this, String.format(" New: %s", newSignature)); + logWithContext(String.format("FUNCTION SIGNATURE CHANGED at address %s:", newFunc.getEntryPoint())); + logWithContext(String.format(" Old: %s", oldSignature)); + logWithContext(String.format(" New: %s", newSignature)); // Log specific changes logFunctionSignatureDetails(oldFunc, newFunc); } } else if (newValue instanceof Function) { 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())); - 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 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) { - Msg.info(this, String.format(" Old type: %s", oldValue.toString())); - Msg.info(this, String.format(" New type: %s", newValue.toString())); + logWithContext(String.format(" Old type: %s", oldValue.toString())); + logWithContext(String.format(" New type: %s", newValue.toString())); } 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 { Program program = getCurrentProgram(); 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) { - Msg.info(this, String.format(" Data label: %s", data.getLabel())); - Msg.info(this, String.format(" Data type: %s", data.getDataType().getName())); + logWithContext(String.format(" Data label: %s", data.getLabel())); + logWithContext(String.format(" Data type: %s", data.getDataType().getName())); } } } catch (Exception e) { @@ -214,18 +273,18 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj private void handleDataTypeAdded(ProgramChangeRecord record) { 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) { - Msg.info(this, String.format(" Type: %s", newValue.toString())); + logWithContext(String.format(" Type: %s", newValue.toString())); } } private void handleDataTypeRemoved(ProgramChangeRecord record) { 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) { - 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 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())); } @@ -244,7 +303,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj try { // Check return type changes 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())); } @@ -252,7 +311,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj int oldParamCount = oldFunc.getParameterCount(); int newParamCount = newFunc.getParameterCount(); if (oldParamCount != newParamCount) { - Msg.info(this, String.format(" Parameter count changed: %d -> %d", + logWithContext(String.format(" Parameter count changed: %d -> %d", oldParamCount, newParamCount)); } @@ -264,28 +323,28 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj ghidra.program.model.listing.Parameter newParam = newFunc.getParameter(i); 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())); } 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())); } } else if (i < newParamCount) { 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())); } else { 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())); } } // Check calling convention changes 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())); } @@ -299,7 +358,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj if (newValue instanceof Symbol) { Symbol symbol = (Symbol) newValue; 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())); } } @@ -309,7 +368,7 @@ public class SymbolRenameLoggerPlugin extends ProgramPlugin implements DomainObj if (oldValue instanceof Symbol) { Symbol symbol = (Symbol) oldValue; 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())); } }