diff --git a/Ghidra/Features/Base/ghidra_scripts/AutoRenameLabelsScript.java b/Ghidra/Features/Base/ghidra_scripts/AutoRenameLabelsScript.java
index ab9863e61b..9af7b67f5b 100644
--- a/Ghidra/Features/Base/ghidra_scripts/AutoRenameLabelsScript.java
+++ b/Ghidra/Features/Base/ghidra_scripts/AutoRenameLabelsScript.java
@@ -32,30 +32,25 @@ public class AutoRenameLabelsScript extends GhidraScript {
return;
}
- String base = askString("Auto Rename Labels", "Enter label base name:");
- if (base == null) {
- println("No base value entered.");
+ String baseName = askString("Auto Rename Labels", "Enter label name prefix:");
+ if (baseName == null) {
return;
}
int num = 1;
-
AddressSetView view = currentSelection;
- if ((view == null) || (view.isEmpty()))
+ if ((view == null) || (view.isEmpty())) {
return;
+ }
- // Obtain the symbol table and listing from program
SymbolTable symbolTable = currentProgram.getSymbolTable();
-
- // Get the addresses in the set.
AddressIterator it = view.getAddresses(true);
-
CompoundCmd cmd = new CompoundCmd("Auto Rename Labels");
while (it.hasNext()) {
Address address = it.next();
Symbol primary = symbolTable.getPrimarySymbol(address);
if (primary != null && primary.getSource() == SourceType.DEFAULT) {
- cmd.add(new RenameLabelCmd(address, null, base + num++, SourceType.USER_DEFINED));
+ cmd.add(new RenameLabelCmd(primary, baseName + num++, SourceType.USER_DEFINED));
}
}
if (cmd.size() > 0) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/RenameLabelCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/RenameLabelCmd.java
index 211a3e982d..c1d572571d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/RenameLabelCmd.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/RenameLabelCmd.java
@@ -15,6 +15,12 @@
*/
package ghidra.app.cmd.label;
+import java.util.Objects;
+
+import org.apache.commons.lang3.StringUtils;
+
+import ghidra.app.util.NamespaceUtils;
+import ghidra.app.util.SymbolPath;
import ghidra.framework.cmd.Command;
import ghidra.framework.model.DomainObject;
import ghidra.program.model.address.Address;
@@ -25,92 +31,119 @@ import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
/**
- * Command for renaming labels. Handles converting back and forth between
- * default and named labels as well.
+ * Command for renaming labels. Handles converting back and forth between default and named labels
+ * as well.
*/
public class RenameLabelCmd implements Command {
private Address addr;
private String oldName;
private String newName;
+ private Symbol existingSymbol;
private Namespace currentNamespace;
private Namespace newNamespace;
private SourceType source;
- private String errorMsg = "";
+ private String errorMessage = "";
/**
- * Constructs a new command for renaming a label within a specified namespace.
- * @param addr Address of label to be renamed.
- * @param oldName the current name of the label to be renamed.
- * @param newName the new name for the label. (null for default)
- * @param currentNamespace the symbol's current name space. (The namespace to associate this label with)
+ * Constructs a new command for renaming global labels.
+ *
+ * @param addr Address of label to be renamed
+ * @param oldName the name of the label to be renamed; may be null if the existing label is a
+ * dynamic label
+ * @param newName the new name for the label
* @param source the source of this symbol
*/
- public RenameLabelCmd(Address addr, String oldName, String newName, Namespace currentNamespace,
+ public RenameLabelCmd(Address addr, String oldName, String newName, SourceType source) {
+ this(addr, oldName, newName, null, null, source);
+ }
+
+ /**
+ * Constructor renaming an existing symbol, but not changing its namespace
+ *
+ * @param symbol the existing symbol; may not be null
+ * @param newName the new symbol name
+ * @param source the desired symbol source
+ */
+ public RenameLabelCmd(Symbol symbol, String newName, SourceType source) {
+ this(symbol, newName, symbol.getParentNamespace(), source);
+ }
+
+ /**
+ * Constructor renaming an existing symbol and changing its namespace. If you do not need
+ * to change the namespace, then call {@link #RenameLabelCmd(Symbol, String, SourceType)}.
+ *
+ * @param symbol the existing symbol; may not be null
+ * @param newName the new symbol name
+ * @param newNamespace the new symbol namespace
+ * @param source the desired symbol source
+ */
+ public RenameLabelCmd(Symbol symbol, String newName, Namespace newNamespace,
SourceType source) {
- this.addr = addr;
- this.oldName = oldName;
+
+ this.existingSymbol = Objects.requireNonNull(symbol);
+ this.addr = symbol.getAddress();
+ this.oldName = symbol.getName();
this.newName = newName;
- this.currentNamespace = currentNamespace;
- this.newNamespace = currentNamespace;
+ this.currentNamespace = symbol.getParentNamespace();
+ this.newNamespace = newNamespace;
this.source = source;
}
/**
* Constructs a new command for renaming a label within currentNamespace and changing the
* namespace to newNamespace.
- * @param addr Address of label to be renamed.
- * @param oldName the current name of the label to be renamed.
+ *
+ * @param addr Address of label to be renamed
+ * @param oldName the current name of the label to be renamed
* @param newName the new name for the label. (null for default)
- * @param currentNamespace the symbol's current parent name space (null indicates global namespace)
- * @param newNamespace final namespace (null indicates global namespace)
+ * @param currentNamespace the symbol's current parent name space; null for global namespace
+ * @param newNamespace the desired namespace; null for global namespace
* @param source the source of this symbol
*/
- public RenameLabelCmd(Address addr, String oldName, String newName, Namespace currentNamespace,
+ private RenameLabelCmd(Address addr, String oldName, String newName, Namespace currentNamespace,
Namespace newNamespace, SourceType source) {
- this(addr, oldName, newName, currentNamespace, source);
+ this.addr = addr;
+ this.oldName = oldName;
+ this.newName = newName;
+ this.currentNamespace = currentNamespace;
this.newNamespace = newNamespace;
+ this.source = source;
}
- /**
- * Constructs a new command for renaming global labels.
- * @param addr Address of label to be renamed.
- * @param oldName the name of the label to be renamed; may be null
- * of the existing label is a dynamic label
- * @param newName the new name for the label
- * @param source the source of this symbol
- */
- public RenameLabelCmd(Address addr, String oldName, String newName, SourceType source) {
- this(addr, oldName, newName, null, source);
+ @Override
+ public String getName() {
+ return "Rename Label";
+ }
+
+ @Override
+ public String getStatusMsg() {
+ return errorMessage;
}
- /**
- *
- * @see ghidra.framework.cmd.Command#applyTo(ghidra.framework.model.DomainObject)
- */
@Override
public boolean applyTo(DomainObject obj) {
+
Program program = (Program) obj;
if (currentNamespace == null) {
currentNamespace = program.getGlobalNamespace();
}
-
if (newNamespace == null) {
newNamespace = program.getGlobalNamespace();
}
- SymbolTable st = ((Program) obj).getSymbolTable();
- Symbol s = null;
- if (oldName == null) {
- s = st.getPrimarySymbol(addr);
- }
- else {
- s = st.getSymbol(oldName, addr, currentNamespace);
+ if (!parseNameAndNamespace(program, newNamespace, newName)) {
+ return false; // errorMessage already set
}
+ Symbol s = getSymbol(program);
if (s == null) {
- errorMsg = "Symbol not found: " + oldName;
+ return false; // errorMessage already set
+ }
+
+ if (StringUtils.isBlank(newName) && s.getSource() != SourceType.DEFAULT) {
+ errorMessage = "Cannot set non-default symbol name to \"\"";
return false;
}
@@ -120,45 +153,121 @@ public class RenameLabelCmd implements Command {
}
else {
s.setName(newName, source);
-
- if (newName.length() == 0 && s.getSource() != SourceType.DEFAULT) {
- errorMsg = "Rename failed - cannot set non-default symbol name to \"\"";
- return false;
- }
-
if (!newName.equals(s.getName())) {
- errorMsg = "Rename failed";
+ errorMessage = "Rename failed";
return false;
}
}
return true;
}
catch (DuplicateNameException e) {
- errorMsg = "Symbol already exists: " + newName;
+ errorMessage = "Symbol already exists: " + newName;
}
catch (InvalidInputException e) {
- errorMsg = "Invalid entry: " + e.getMessage();
+ errorMessage = "Invalid entry: " + e.getMessage();
}
catch (CircularDependencyException e) {
- errorMsg = e.getMessage();
+ errorMessage = e.getMessage();
}
return false;
}
- /**
- * @see ghidra.framework.cmd.Command#getName()
- */
- @Override
- public String getName() {
- return "Rename Label";
+ private boolean parseNameAndNamespace(Program program, Namespace rootNamespace, String name) {
+
+ SymbolPath symbolPath = getSymbolPath(name);
+ if (symbolPath == null) {
+ return false; // invalid symbol name
+ }
+
+ // see if the user specified a namespace path
+ Namespace parent = getOrCreateNamespaces(program, symbolPath, rootNamespace);
+ if (parent == null) {
+ return false; // create namespace failed
+ }
+
+ // update the new namespace and symbol name to reflect the parse results
+ newNamespace = parent;
+ newName = symbolPath.getName();
+ return true;
}
- /**
- * @see ghidra.framework.cmd.Command#getStatusMsg()
- */
- @Override
- public String getStatusMsg() {
- return errorMsg;
+ private Symbol getSymbol(Program program) {
+
+ if (existingSymbol != null) {
+ return existingSymbol;
+ }
+
+ SymbolTable st = program.getSymbolTable();
+ Symbol s = null;
+ if (oldName != null) {
+ s = st.getSymbol(oldName, addr, currentNamespace);
+ }
+ else {
+ s = st.getPrimarySymbol(addr);
+ if (s != null && !s.isDynamic()) {
+ // noted by the constructor, a null name can only be used to rename dynamic symbols
+ errorMessage = "Must specify name of symbol to be renamed";
+ return null;
+ }
+ }
+
+ if (s == null) {
+ errorMessage = "Symbol not found: " + oldName;
+ return null;
+ }
+ return s;
}
+ // note: the root namespace will be used as the parent for any namespaces found in 'symbolPath'
+ private Namespace getOrCreateNamespaces(Program program, SymbolPath symbolPath,
+ Namespace rootNamespace) {
+ SymbolPath parentPath = symbolPath.getParent();
+ if (parentPath == null) {
+ return rootNamespace;
+ }
+
+ //
+ // Prefer a non-function namespace. This allows us to put a function inside of a namespace
+ // sharing the same name.
+ //
+ SymbolPath fullPath = new SymbolPath(rootNamespace.getSymbol()).append(parentPath);
+ Namespace nonFunctionNs = NamespaceUtils.getNonFunctionNamespace(program, fullPath);
+ if (nonFunctionNs != null) {
+ return nonFunctionNs;
+ }
+
+ //
+ // At this point we can either reuse an existing function namespace or we have to create
+ // a new non-function namespaces, depending upon the names being used. Only use an
+ // existing function as a namespace if none of namespace path entries match the function
+ // name.
+ //
+ String name = symbolPath.getName();
+ if (!parentPath.containsPathEntry(name)) {
+ Namespace functionNamespace =
+ NamespaceUtils.getFunctionNamespaceContaining(program, parentPath, addr);
+ if (functionNamespace != null) {
+ return functionNamespace;
+ }
+ }
+
+ CreateNamespacesCmd cmd =
+ new CreateNamespacesCmd(parentPath.getPath(), rootNamespace, SourceType.USER_DEFINED);
+ if (cmd.applyTo(program)) {
+ return cmd.getNamespace();
+ }
+
+ errorMessage = cmd.getStatusMsg();
+ return null;
+ }
+
+ private SymbolPath getSymbolPath(String symbolName) {
+
+ if (StringUtils.isBlank(symbolName)) {
+ errorMessage = "Name cannot be blank";
+ return null;
+ }
+
+ return new SymbolPath(symbolName);
+ }
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
index dae9bddd46..45a1d2a1b7 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
@@ -443,11 +443,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier
SymbolTable symbolTable = currentProgram.getSymbolTable();
Symbol symbol = symbolTable.getSymbol(reference);
if ((symbol instanceof CodeSymbol) || (symbol instanceof FunctionSymbol)) {
- String oldName = symbol.getName();
- Namespace namespace = symbol.getParentNamespace();
- Address symbolAddress = symbol.getAddress();
- RenameLabelCmd cmd = new RenameLabelCmd(symbolAddress, oldName, labelName, namespace,
- SourceType.USER_DEFINED);
+ RenameLabelCmd cmd = new RenameLabelCmd(symbol, labelName, SourceType.USER_DEFINED);
return tool.execute(cmd, currentProgram);
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTableModel.java
index 3774b141f3..aaaf5990b6 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTableModel.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTableModel.java
@@ -23,7 +23,6 @@ import ghidra.app.cmd.function.DeleteFunctionCmd;
import ghidra.app.cmd.label.DeleteLabelCmd;
import ghidra.app.cmd.label.RenameLabelCmd;
import ghidra.docking.settings.Settings;
-import ghidra.framework.cmd.Command;
import ghidra.framework.cmd.CompoundCmd;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.ServiceProvider;
@@ -207,17 +206,19 @@ class SymbolTableModel extends AddressBasedTableModel {
return;
}
- if (columnIndex == LABEL_COL) {
- String newName = aValue.toString();
- if (!symbol.getName().equals(newName)) {
- Command renameCmd = new RenameLabelCmd(symbol.getAddress(), symbol.getName(),
- newName, symbol.getParentNamespace(), SourceType.USER_DEFINED);
+ if (columnIndex != LABEL_COL) {
+ return;
+ }
- if (!tool.execute(renameCmd, getProgram())) {
- Msg.showError(getClass(), provider.getComponent(), "Error Renaming Symbol",
- renameCmd.getStatusMsg());
- }
- }
+ String newName = aValue.toString();
+ if (symbol.getName().equals(newName)) {
+ return;
+ }
+
+ RenameLabelCmd renameCmd = new RenameLabelCmd(symbol, newName, SourceType.USER_DEFINED);
+ if (!tool.execute(renameCmd, getProgram())) {
+ Msg.showError(getClass(), provider.getComponent(), "Error Renaming Symbol",
+ renameCmd.getStatusMsg());
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddEditDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddEditDialog.java
index b581b688fd..632f88416a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddEditDialog.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddEditDialog.java
@@ -168,12 +168,16 @@ public class AddEditDialog extends DialogComponentProvider {
cmd.add(new AddLabelCmd(addr, symbolName, parent, SourceType.USER_DEFINED));
}
else {
- cmd.add(new RenameLabelCmd(addr, symbol.getName(), symbolName,
- symbol.getParentNamespace(), parent, SourceType.USER_DEFINED));
+ cmd.add(new RenameLabelCmd(symbol, labelText, namespace, SourceType.USER_DEFINED));
isCurrentlyEntryPoint = symbol.isExternalEntryPoint();
isCurrentlyPinned = symbol.isPinned();
}
+ if (!tool.execute(cmd, program)) {
+ setStatusText(cmd.getStatusMsg());
+ return;
+ }
+
if (primaryCheckBox.isEnabled() && primaryCheckBox.isSelected()) {
cmd.add(new SetLabelPrimaryCmd(addr, symbolName, parent));
}
@@ -185,14 +189,12 @@ public class AddEditDialog extends DialogComponentProvider {
cmd.add(new PinSymbolCmd(addr, symbolName, !isCurrentlyPinned));
}
- if (cmd.size() > 0) {
-
- if (!tool.execute(cmd, program)) {
- setStatusText(cmd.getStatusMsg());
- return;
- }
- updateRecentLabels(symbolName);
+ if (!tool.execute(cmd, program)) {
+ setStatusText(cmd.getStatusMsg());
+ return;
}
+ updateRecentLabels(symbolName);
+
program = null;
close();
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/disassembler/ClearTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/disassembler/ClearTest.java
index 34164585b4..4e492dfc75 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/disassembler/ClearTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/disassembler/ClearTest.java
@@ -430,8 +430,7 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
Symbol[] symbols = program.getSymbolTable().getSymbols(addr("0x10022bf"));
Symbol s = symbols[0];
- RenameLabelCmd cmd = new RenameLabelCmd(s.getAddress(), s.getName(), "Fred",
- s.getParentNamespace(), SourceType.USER_DEFINED);
+ RenameLabelCmd cmd = new RenameLabelCmd(s, "Fred", SourceType.USER_DEFINED);
applyCmd(program, cmd);
makeSelection(tool, program, addr("0x10022bf"), addr("0x10022c4"));
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/LabelActionTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/LabelActionTest.java
index 3c0f8cd153..67994aef4c 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/LabelActionTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/LabelActionTest.java
@@ -136,25 +136,25 @@ public class LabelActionTest extends AbstractGhidraHeadedIntegrationTest
@Test
public void testNotepadLocations() {
ActionContext context = new ActionContext();
- assertEquals(false, addLabel.isEnabledForContext(context));
+ assertFalse(addLabel.isEnabledForContext(context));
- assertEquals(false, editLabel.isEnabledForContext(context));
+ assertFalse(editLabel.isEnabledForContext(context));
- assertEquals(false, removeLabel.isEnabledForContext(context));
+ assertFalse(removeLabel.isEnabledForContext(context));
- assertEquals(false, setLabel.isEnabledForContext(context));
+ assertFalse(setLabel.isEnabledForContext(context));
env.open(program);
cb.updateNow();
context = cb.getProvider().getActionContext(null);
- assertEquals(true, addLabel.isEnabledForContext(context));
+ assertTrue(addLabel.isEnabledForContext(context));
- assertEquals(false, editLabel.isEnabledForContext(context));
+ assertFalse(editLabel.isEnabledForContext(context));
- assertEquals(false, removeLabel.isEnabledForContext(context));
+ assertFalse(removeLabel.isEnabledForContext(context));
- assertEquals(false, setLabel.isEnabledForContext(context));
+ assertFalse(setLabel.isEnabledForContext(context));
SampleLocationGenerator locGen = new SampleLocationGenerator(program);
locGen.toggleOpenComposites(cb);
@@ -162,9 +162,6 @@ public class LabelActionTest extends AbstractGhidraHeadedIntegrationTest
}
- /**
- * @see ghidra.app.LocationCallback#locationGenerated(ghidra.program.singleuser.util.ProgramLocation)
- */
@Override
public void locationGenerated(ProgramLocation loc) {
@@ -184,11 +181,11 @@ public class LabelActionTest extends AbstractGhidraHeadedIntegrationTest
if (loc instanceof LabelFieldLocation) {
Symbol s = labelMgrPlugin.getSymbol((ListingActionContext) context);
- assertEquals(caseName, false, addLabel.isEnabledForContext(context));
- assertEquals(caseName, true, editLabel.isEnabledForContext(context));
- assertEquals(caseName, false, editExternalLocation.isEnabledForContext(context));
+ assertFalse(caseName, addLabel.isEnabledForContext(context));
+ assertTrue(caseName, editLabel.isEnabledForContext(context));
+ assertFalse(caseName, editExternalLocation.isEnabledForContext(context));
assertEquals(caseName, !s.isDynamic(), removeLabel.isEnabledForContext(context));
- assertEquals(caseName, false, setLabel.isEnabledForContext(context));
+ assertFalse(caseName, setLabel.isEnabledForContext(context));
assertEquals(EditLabelAction.EDIT_LABEL,
editLabel.getPopupMenuData().getMenuItemName());
@@ -249,8 +246,8 @@ public class LabelActionTest extends AbstractGhidraHeadedIntegrationTest
assertEquals(caseName, !hasComponentPath, addLabel.isEnabledForContext(context));
assertEquals(caseName, component != null, editLabel.isEnabledForContext(context));
- assertEquals(caseName, false, removeLabel.isEnabledForContext(context));
- assertEquals(caseName, false, setLabel.isEnabledForContext(context));
+ assertFalse(caseName, removeLabel.isEnabledForContext(context));
+ assertFalse(caseName, setLabel.isEnabledForContext(context));
if (component != null) {
assertEquals(EditLabelAction.EDIT_FIELDNAME,
@@ -258,16 +255,16 @@ public class LabelActionTest extends AbstractGhidraHeadedIntegrationTest
}
}
else if (!(loc instanceof FunctionLocation)) {
- assertEquals(caseName, true, addLabel.isEnabledForContext(context));
- assertEquals(caseName, false, editLabel.isEnabledForContext(context));
- assertEquals(caseName, false, removeLabel.isEnabledForContext(context));
- assertEquals(caseName, false, setLabel.isEnabledForContext(context));
+ assertTrue(caseName, addLabel.isEnabledForContext(context));
+ assertFalse(caseName, editLabel.isEnabledForContext(context));
+ assertFalse(caseName, removeLabel.isEnabledForContext(context));
+ assertFalse(caseName, setLabel.isEnabledForContext(context));
}
else {
- assertEquals(caseName, false, addLabel.isEnabledForContext(context));
- assertEquals(caseName, false, editLabel.isEnabledForContext(context));
- assertEquals(caseName, false, removeLabel.isEnabledForContext(context));
- assertEquals(caseName, false, setLabel.isEnabledForContext(context));
+ assertFalse(caseName, addLabel.isEnabledForContext(context));
+ assertFalse(caseName, editLabel.isEnabledForContext(context));
+ assertFalse(caseName, removeLabel.isEnabledForContext(context));
+ assertFalse(caseName, setLabel.isEnabledForContext(context));
}
}
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AutoRenameLabelsScriptTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AutoRenameLabelsScriptTest.java
index e216cae385..918c606f33 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AutoRenameLabelsScriptTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/AutoRenameLabelsScriptTest.java
@@ -25,7 +25,6 @@ import javax.swing.JTextField;
import org.junit.*;
import ghidra.app.cmd.function.CreateFunctionCmd;
-import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.services.ProgramManager;
import ghidra.framework.Application;
@@ -33,7 +32,6 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
-import ghidra.program.util.ProgramSelection;
import ghidra.test.*;
/**
@@ -58,8 +56,9 @@ public class AutoRenameLabelsScriptTest extends AbstractGhidraHeadedIntegrationT
env.showTool();
script =
- Application.getModuleFile("Base", "ghidra_scripts/AutoRenameLabelsScript.java").getFile(
- true);
+ Application.getModuleFile("Base", "ghidra_scripts/AutoRenameLabelsScript.java")
+ .getFile(
+ true);
env.showTool();
}
@@ -88,12 +87,8 @@ public class AutoRenameLabelsScriptTest extends AbstractGhidraHeadedIntegrationT
return builder.getProgram();
}
- /*
- * @see TestCase#tearDown()
- */
@After
public void tearDown() throws Exception {
- env.release(program);
env.dispose();
}
@@ -102,29 +97,23 @@ public class AutoRenameLabelsScriptTest extends AbstractGhidraHeadedIntegrationT
SymbolTable symbolTable = program.getSymbolTable();
Symbol s1 = symbolTable.getPrimarySymbol(addr(0x01003a94));
assertNotNull(s1);
- assertTrue(s1.getSource() == SourceType.DEFAULT);
+ assertEquals(s1.getSource(), SourceType.DEFAULT);
Symbol s2 = symbolTable.getPrimarySymbol(addr(0x01003a97));
assertNotNull(s2);
- assertTrue(s2.getSource() == SourceType.DEFAULT);
+ assertEquals(s2.getSource(), SourceType.DEFAULT);
- ProgramSelection sel = new ProgramSelection(addr(0x01003a94), addr(0x01003a9b));
- tool.firePluginEvent(new ProgramSelectionPluginEvent("test", sel, program));
- waitForPostedSwingRunnables();
+ makeSelection(tool, program, addr(0x01003a94), addr(0x01003a9b));
ScriptTaskListener scriptID = env.runScript(script);
- JDialog dialog = waitForJDialog(tool.getToolFrame(), "Auto Rename Labels", 2000);
- final JTextField tf = findComponent(dialog, JTextField.class);
+ JDialog dialog = waitForJDialog("Auto Rename Labels");
+ JTextField tf = findComponent(dialog, JTextField.class);
runSwing(() -> tf.setText("My_Label"));
pressButtonByText(dialog, "OK");
waitForScriptCompletion(scriptID, 100000);
- program.flushEvents();
- waitForPostedSwingRunnables();
-
- s1 = symbolTable.getPrimarySymbol(addr(0x01003a94));
- s2 = symbolTable.getPrimarySymbol(addr(0x01003a97));
+ waitForProgram(program);
assertEquals("My_Label1", s1.getName());
assertEquals("My_Label2", s2.getName());
@@ -134,39 +123,34 @@ public class AutoRenameLabelsScriptTest extends AbstractGhidraHeadedIntegrationT
public void testNoRenameOnUserDefined() throws Exception {
SymbolTable symbolTable = program.getSymbolTable();
Symbol s1 = symbolTable.getPrimarySymbol(addr(0x010046cc));
- assertTrue(s1.getSource() == SourceType.DEFAULT);
+ assertEquals(s1.getSource(), SourceType.DEFAULT);
// create a function at 10046d0 so we don't have a default label
CreateFunctionCmd cmd =
new CreateFunctionCmd("My_Function1", addr(0x010046d0), null, SourceType.ANALYSIS);
- tool.execute(cmd, program);
- program.flushEvents();
- waitForPostedSwingRunnables();
+ applyCmd(program, cmd);
Symbol s2 = symbolTable.getPrimarySymbol(addr(0x010046d0));
assertNotNull(s2);
- assertTrue(s2.getSource() != SourceType.DEFAULT);
+ assertNotEquals(s2.getSource(), SourceType.DEFAULT);
String s2Name = s2.getName();
- ProgramSelection sel = new ProgramSelection(addr(0x010046cc), addr(0x010046d0));
- tool.firePluginEvent(new ProgramSelectionPluginEvent("test", sel, program));
- waitForPostedSwingRunnables();
+ makeSelection(tool, program, addr(0x010046cc), addr(0x010046d0));
ScriptTaskListener scriptID = env.runScript(script);
- JDialog dialog = waitForJDialog(tool.getToolFrame(), "Auto Rename Labels", 2000);
- final JTextField tf = findComponent(dialog, JTextField.class);
+ JDialog dialog = waitForJDialog("Auto Rename Labels");
+ JTextField tf = findComponent(dialog, JTextField.class);
runSwing(() -> tf.setText("My_Label"));
pressButtonByText(dialog, "OK");
waitForScriptCompletion(scriptID, 100000);
- program.flushEvents();
- waitForPostedSwingRunnables();
- s1 = symbolTable.getPrimarySymbol(addr(0x010046cc));
+ waitForProgram(program);
+
assertEquals("My_Label1", s1.getName());
+
// only dynamic label should get renamed
- s2 = symbolTable.getPrimarySymbol(addr(0x010046d0));
- assertTrue(!s2.getName().equals("My_Label2"));
+ assertFalse(s2.getName().equals("My_Label2"));
assertEquals(s2Name, s2.getName());
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreeNavigationTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreeNavigationTest.java
index 5121f14ea8..9abc09db87 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreeNavigationTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreeNavigationTest.java
@@ -450,21 +450,16 @@ public class SymbolTreeNavigationTest extends AbstractProgramBasedTest {
}
private void rename(Symbol symbol, String newName) {
-
- String oldName = symbol.getName();
- RenameLabelCmd cmd =
- new RenameLabelCmd(symbol.getAddress(), oldName, newName, SourceType.USER_DEFINED);
+ RenameLabelCmd cmd = new RenameLabelCmd(symbol, newName, SourceType.USER_DEFINED);
applyCmd(cmd);
util.waitForTree();
}
private Symbol createGlobalLabel(Address addr) {
-
return createGlobalLabel(addr, "GlobalLabel");
}
private Symbol createGlobalLabel(Address addr, String labelName) {
-
AddLabelCmd cmd = new AddLabelCmd(addr, labelName, SourceType.USER_DEFINED);
applyCmd(cmd);
Symbol symbol = cmd.getSymbol();
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symtable/SymbolTablePluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symtable/SymbolTablePluginTest.java
index 9e8c6f472f..5cd4cb6489 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symtable/SymbolTablePluginTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symtable/SymbolTablePluginTest.java
@@ -28,6 +28,7 @@ import java.util.function.BiConsumer;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableModel;
+import javax.swing.text.JTextComponent;
import org.jdom.Element;
import org.junit.*;
@@ -346,12 +347,47 @@ public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
waitForNotBusy();
- assertTrue(!symbolTable.isEditing());
+ assertFalse(symbolTable.isEditing());
Symbol s = getSymbol(row);
assertEquals("ghidra.Is.Cool", s.getName());
}
+ @Test
+ public void testEditName_AddNamespace() throws Exception {
+ openProgram("sample");
+
+ waitForNotBusy();
+
+ String symbolName = "ghidra";
+ int row = findRow(symbolName);
+
+ doubleClick(symbolTable, row, SymbolTableModel.LABEL_COL);
+ waitForSwing();
+ assertTrue(symbolTable.isEditing());
+
+ Component editor = symbolTable.getEditorComponent();
+ assertNotNull(editor);
+ JTextField textField = (JTextField) editor;
+ String currentText = getText(textField);
+ assertEquals(symbolName, currentText);
+
+ String newNamespaceName = "NS1";
+ JTextComponent textComponent = (JTextComponent) editor;
+ runSwing(() -> textComponent.selectAll());
+ myTypeText(editor, newNamespaceName + Namespace.DELIMITER + symbolName);
+ runSwing(() -> symbolTable.editingStopped(new ChangeEvent(symbolTable)));
+
+ waitForNotBusy();
+
+ assertFalse(symbolTable.isEditing());
+
+ Symbol s = getSymbol(row);
+ assertEquals(symbolName, s.getName());
+ Namespace namespace = s.getParentNamespace();
+ assertEquals(newNamespaceName, namespace.getName());
+ }
+
@Test
public void testQuickLookup() throws Exception {
openProgram("sample");
@@ -400,7 +436,7 @@ public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
openProgram("sample");
int rowCount = symbolTable.getRowCount();
- assertTrue(!deleteAction.isEnabled());
+ assertFalse(deleteAction.isEnabled());
int row = findRow("ghidra");
Rectangle rect = symbolTable.getCellRect(row, 0, true);
@@ -488,7 +524,7 @@ public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
public void testMakeSelection() throws Exception {
openProgram("sample");
- assertTrue(!makeSelectionAction.isEnabled());
+ assertFalse(makeSelectionAction.isEnabled());
int row1 = findRow("ghidra");
int row2 = findRow("KERNEL32.dll_GetProcAddress");
diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java
index 24a9f9c321..f696c755d7 100644
--- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java
+++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java
@@ -508,8 +508,10 @@ public class FillOutStructureCmd extends BackgroundCommand {
if (isThisParam) {
Namespace rootNamespace = currentProgram.getGlobalNamespace();
Namespace newNamespace = createUniqueClassName(rootNamespace);
- RenameLabelCmd command = new RenameLabelCmd(f.getEntryPoint(), f.getName(), f.getName(),
- rootNamespace, newNamespace, SourceType.USER_DEFINED);
+ String name = f.getName();
+ Symbol symbol = f.getSymbol();
+ RenameLabelCmd command =
+ new RenameLabelCmd(symbol, name, newNamespace, SourceType.USER_DEFINED);
if (!command.applyTo(currentProgram)) {
return null;
}
@@ -545,12 +547,10 @@ public class FillOutStructureCmd extends BackgroundCommand {
symbolTable.createClass(rootNamespace, newClassName, SourceType.USER_DEFINED);
}
catch (DuplicateNameException e) {
- // Shouldn't happen
- e.printStackTrace();
+ Msg.error(this, "Error creating class '" + newClassName + "'", e);
}
catch (InvalidInputException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Msg.error(this, "Error creating class '" + newClassName + "'", e);
}
return newClass;
}