diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/CreateNamespacesCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/CreateNamespacesCmd.java
index 73e973f703..8aa1a8a83e 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/CreateNamespacesCmd.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/CreateNamespacesCmd.java
@@ -31,7 +31,7 @@ import ghidra.util.exception.InvalidInputException;
*
* Example strings:
*
- * - global{@link Namespace#NAMESPACE_DELIMITER ::}child1{@link Namespace#NAMESPACE_DELIMITER ::}child2
+ *
- global{@link Namespace#DELIMITER ::}child1{@link Namespace#DELIMITER ::}child2
*
- child1
*
*
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/ThunkReferenceAddressDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/ThunkReferenceAddressDialog.java
index f636f73dce..30c674c790 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/ThunkReferenceAddressDialog.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/ThunkReferenceAddressDialog.java
@@ -243,14 +243,14 @@ public class ThunkReferenceAddressDialog extends DialogComponentProvider {
return null;
}
- List namespaces = NamespaceUtils.getNamespaces(parentNs, null, program);
+ List namespaces = NamespaceUtils.getNamespaceByPath(program, null, parentNs);
if (namespaces.isEmpty()) {
SymbolTable symbolTable = program.getSymbolTable();
for (String libraryName : program.getExternalManager().getExternalLibraryNames()) {
Symbol librarySymbol = symbolTable.getLibrarySymbol(libraryName);
- namespaces = NamespaceUtils.getNamespaces(parentNs,
- (Library) librarySymbol.getObject(), program);
+ namespaces = NamespaceUtils.getNamespaceByPath(program,
+ (Library) librarySymbol.getObject(), parentNs);
if (!namespaces.isEmpty()) {
break; // use first library containing namespace
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java
index 7a0d13ab4d..eafa0d4e37 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/gotoquery/GoToHelper.java
@@ -394,7 +394,7 @@ public class GoToHelper {
StringBuilder buf = new StringBuilder();
while (!nameStack.isEmpty()) {
buf.append(nameStack.pop());
- buf.append(Namespace.NAMESPACE_DELIMITER);
+ buf.append(Namespace.DELIMITER);
}
buf.append(externalLoc.getLabel());
return buf.toString();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchSymbol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchSymbol.java
index 03248faad5..5b909fa8b0 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchSymbol.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchSymbol.java
@@ -117,7 +117,7 @@ public class MatchSymbol {
SymbolPath namespacePath = aSymbolPath.getParent();
if (!aSymbolIdentifier.isExternalSymbol() && namespacePath != null &&
!aSymbolPath.equals(bSymbolIdentifier.symbolPath) &&
- NamespaceUtils.getNamespace(bProgram, namespacePath, null) != null) {
+ NamespaceUtils.getNonFunctionNamespace(bProgram, namespacePath) != null) {
// skip match with namespace mismatch when source namespace exists in destination
continue;
}
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 f42980ba6c..1d4cbdd4fe 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
@@ -172,24 +172,39 @@ public class AddEditDialog extends DialogComponentProvider {
if (parentPath == null) {
return rootNamespace;
}
- String relativeParentPath = parentPath.getPath();
- SymbolPath absoluteParentPath =
- new SymbolPath(rootNamespace.getSymbol()).append(parentPath);
- Namespace parentNamespace = NamespaceUtils.getNamespace(program, absoluteParentPath, addr);
- if (parentNamespace != null) {
- return parentNamespace;
+ //
+ // 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;
}
- // run the create namespaces command
- CreateNamespacesCmd command =
- new CreateNamespacesCmd(relativeParentPath, rootNamespace, SourceType.USER_DEFINED);
-
- if (tool.execute(command, program)) {
- return command.getNamespace();
+ //
+ // 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;
+ }
}
- setStatusText(command.getStatusMsg());
+ CreateNamespacesCmd cmd =
+ new CreateNamespacesCmd(parentPath.getPath(), rootNamespace, SourceType.USER_DEFINED);
+ if (tool.execute(cmd, program)) {
+ return cmd.getNamespace();
+ }
+
+ setStatusText(cmd.getStatusMsg());
return null;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/NamespacePath.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/NamespacePath.java
index 624c42856c..614b790db3 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/NamespacePath.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/next/NamespacePath.java
@@ -192,7 +192,7 @@ public class NamespacePath implements Comparable {
public String asNamespaceString() {
StringBuilder sb = new StringBuilder();
doInOrderTraversal(
- nsp -> sb.append(sb.length() != 0 ? Namespace.NAMESPACE_DELIMITER : "").append(
+ nsp -> sb.append(sb.length() != 0 ? Namespace.DELIMITER : "").append(
nsp.isRoot() ? "ROOT" : nsp.name));
return sb.toString();
}
@@ -207,7 +207,7 @@ public class NamespacePath implements Comparable {
doInOrderTraversal(nsp -> {
if (!nsp.isRoot()) {
- sb.append(sb.length() != 0 ? Namespace.NAMESPACE_DELIMITER : "").append(nsp.name);
+ sb.append(sb.length() != 0 ? Namespace.DELIMITER : "").append(nsp.name);
}
});
@@ -219,7 +219,7 @@ public class NamespacePath implements Comparable {
public String toString() {
StringBuilder sb = new StringBuilder();
doInOrderTraversal(
- nsp -> sb.append(sb.length() != 0 ? Namespace.NAMESPACE_DELIMITER : "").append(
+ nsp -> sb.append(sb.length() != 0 ? Namespace.DELIMITER : "").append(
nsp.isRoot() ? "ROOT" : nsp.name).append(
"(" + (nsp.getType() != null ? nsp.getType() : "unknown type") + ")"));
return sb.toString();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java
index aae834ea12..c0a2e8ca89 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java
@@ -39,7 +39,7 @@ public abstract class DemangledObject {
protected static final String SPACE = " ";
protected static final Pattern SPACE_PATTERN = Pattern.compile(SPACE);
- protected static final String NAMESPACE_SEPARATOR = Namespace.NAMESPACE_DELIMITER;
+ protected static final String NAMESPACE_SEPARATOR = Namespace.DELIMITER;
protected static final String EMPTY_STRING = "";
protected String originalMangled;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java
index 389eb05262..4f627fbd4d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java
@@ -193,7 +193,7 @@ public class DemangledType {
return "";
}
- buffer.append(Namespace.NAMESPACE_DELIMITER);
+ buffer.append(Namespace.DELIMITER);
return buffer.toString();
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java
index 00143d4758..628bfa2892 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java
@@ -75,12 +75,12 @@ class FunctionsXmlMgr {
* <!ELEMENT FUNCTION (RETURN_TYPE?, ADDRESS_RANGE*, REGULAR_CMT?, REPEATABLE_CMT?, TYPEINFO_CMT?, STACK_FRAME?, REGISTER_VAR*)>
*
*
- * @param parser
- * @param overwriteConflicts
- * @param ignoreStackFrames
- * @param monitor
- * @throws AddressFormatException
- * @throws CancelledException
+ * @param parser the parser
+ * @param overwriteConflicts true to overwrite any conflicts
+ * @param ignoreStackFrames true to ignore stack frames
+ * @param monitor the task monitor
+ * @throws AddressFormatException if any address is not parsable
+ * @throws CancelledException if the operation is cancelled through the monitor
*/
void read(XmlPullParser parser, boolean overwriteConflicts, boolean ignoreStackFrames,
TaskMonitor monitor) throws AddressFormatException, CancelledException {
@@ -94,9 +94,7 @@ class FunctionsXmlMgr {
dtParser = new DtParser(dataManager);
while (parser.peek().isStart()) {
- if (monitor.isCancelled()) {
- throw new CancelledException();
- }
+ monitor.checkCanceled();
final XmlElement functionElement = parser.start("FUNCTION");
@@ -155,7 +153,8 @@ class FunctionsXmlMgr {
try {
Symbol symbol = func.getSymbol();
Namespace namespace =
- NamespaceUtils.getNamespace(program, namespacePath, entryPoint);
+ NamespaceUtils.getFunctionNamespaceAt(program, namespacePath,
+ entryPoint);
if (namespace == null) {
namespace = program.getGlobalNamespace();
}
@@ -258,13 +257,6 @@ class FunctionsXmlMgr {
}
}
- /**
- * Add local vars to a function.
- *
- * @param function
- * @param variables
- * @throws InvalidInputException
- */
private void addLocalVars(Function function, List variables,
boolean overwriteConflicts) throws InvalidInputException {
for (Variable v : variables) {
@@ -275,8 +267,9 @@ class FunctionsXmlMgr {
try {
String name = v.getName();
boolean isDefaultVariableName = (name == null) ||
- SymbolUtilities.getDefaultLocalName(program, v.getStackOffset(), 0).equals(
- name);
+ SymbolUtilities.getDefaultLocalName(program, v.getStackOffset(), 0)
+ .equals(
+ name);
SourceType sourceType =
isDefaultVariableName ? SourceType.DEFAULT : SourceType.USER_DEFINED;
@@ -305,13 +298,9 @@ class FunctionsXmlMgr {
return dtParser.parseDataType(dtName, cp, size);
}
- /**
+ /*
* Returns the text embedded in an optional xml element. If the next element in the stream is not
- * the "expectedElementName", the xml parser stream is unchanged.
- *
- * @param parser
- * @param expectedElementName
- * @return
+ * the "expectedElementName", the xml parser stream is unchanged
*/
private String getElementText(XmlPullParser parser, String expectedElementName) {
String result = null;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java
index 28dd1f4c2a..acee54c937 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java
@@ -1065,7 +1065,7 @@ public class ProgramBuilder {
ExternalManager extMgr = program.getExternalManager();
Namespace namespace = extMgr.addExternalLibraryName(libraryName, sourceType);
- if (externalLabel != null && externalLabel.indexOf(Namespace.NAMESPACE_DELIMITER) > 0) {
+ if (externalLabel != null && externalLabel.indexOf(Namespace.DELIMITER) > 0) {
// External manager API does not yet support creation of namespaces within
// library so we handle that here
SymbolPath symPath = new SymbolPath(externalLabel);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java
index a091bb3d66..1d23a6e51d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/model/listing/CodeUnitFormat.java
@@ -1293,8 +1293,8 @@ public class CodeUnitFormat {
namespaceName = parentNamespace.getName(true);
}
}
- if (namespaceName.length() != 0 && !namespaceName.endsWith(Namespace.NAMESPACE_DELIMITER)) {
- namespaceName += Namespace.NAMESPACE_DELIMITER;
+ if (namespaceName.length() != 0 && !namespaceName.endsWith(Namespace.DELIMITER)) {
+ namespaceName += Namespace.DELIMITER;
}
return namespaceName + name;
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/AddEditDialoglTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/AddEditDialoglTest.java
index d39862997f..5a097d98db 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/AddEditDialoglTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/label/AddEditDialoglTest.java
@@ -27,6 +27,7 @@ import org.junit.*;
import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.cmd.label.AddLabelCmd;
+import ghidra.app.cmd.label.CreateNamespacesCmd;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
import ghidra.app.util.AddEditDialog;
@@ -93,6 +94,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
@After
public void tearDown() throws Exception {
+ dialog.close();
env.dispose();
}
@@ -107,14 +109,14 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(globalScope, scope);
assertTrue(primaryCheckBox.isSelected());
assertTrue(!primaryCheckBox.isEnabled());
- dialogCancel();
+ pressCancel();
}
@Test
public void testLabelChangeOne() {
addLabel(addr(0x0100642a));
setText("printf");
- dialogOK();
+ pressOk();
Symbol s = getUniqueSymbol(program, "printf", null);
assertNotNull(s);
@@ -126,14 +128,14 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
public void testDuplicateLabelForAdd() {
addLabel(addr(0x0100642a));
setText("printf");
- dialogOK();
+ pressOk();
addLabel(addr(0x0100642c));
setText("printf");
assertEquals(" ", dialog.getStatusText());
- dialogOK();
+ pressOk();
assertTrue(dialog.getStatusText().length() > 0);
- dialogCancel();
+ pressCancel();
}
@Test
@@ -141,7 +143,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
addLabel(addr(0x0100642a));
setText("printf");
setCheckbox(entryCheckBox, true);
- dialogOK();
+ pressOk();
assertTrue(!dialog.isVisible());
Symbol s = getUniqueSymbol(program, "printf", null);
assertNotNull(s);
@@ -153,7 +155,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
addLabel(addr(0x0100642a));
setText("printf");
setCheckbox(pinnedCheckBox, true);
- dialogOK();
+ pressOk();
assertTrue(!dialog.isVisible());
Symbol s = getUniqueSymbol(program, "printf", null);
assertNotNull(s);
@@ -161,7 +163,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
editLabel(s);
setCheckbox(pinnedCheckBox, false);
- dialogOK();
+ pressOk();
assertTrue(!s.isPinned());
}
@@ -169,7 +171,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEmptyLabel() {
addLabel(addr(0x0100642a));
- dialogOK();
+ pressOk();
assertTrue(dialog.isVisible());
assertTrue(dialog.getStatusText().length() > 0);
@@ -239,7 +241,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
setText("printf");
Namespace scope = st.getNamespace(a);
setScope(scope);
- dialogOK();
+ pressOk();
s = getUniqueSymbol(program, "printf", scope);
assertNotNull(s);
assertTrue(!s.isGlobal());
@@ -259,7 +261,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
setText("printf");
setCheckbox(primaryCheckBox, true);
- dialogOK();
+ pressOk();
s = getUniqueSymbol(program, "entry", null);
assertTrue(!s.isPrimary());
s = getUniqueSymbol(program, "printf", null);
@@ -286,7 +288,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
addLabel(addr(0x100642a));
setText("aaaa");
assertEquals(0, recentLabels.size());
- dialogOK();
+ pressOk();
assertEquals(1, recentLabels.size());
assertEquals("aaaa", recentLabels.get(0));
@@ -295,7 +297,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("", getText());
//assertEquals("aaaa", getText());
setText("bbbb");
- dialogOK();
+ pressOk();
assertEquals(2, recentLabels.size());
assertEquals("bbbb", recentLabels.get(0));
@@ -308,7 +310,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < 12; i++) {
addLabel(addr(0x100642a));
setText("l" + i);
- dialogOK();
+ pressOk();
}
assertEquals(10, recentLabels.size());
@@ -328,7 +330,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(entryCheckBox.isSelected());
assertTrue(primaryCheckBox.isSelected());
assertTrue(!primaryCheckBox.isEnabled());
- dialogCancel();
+ pressCancel();
}
@@ -352,7 +354,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
editLabel(s);
assertEquals("entry", getText());
setText("bob");
- dialogOK();
+ pressOk();
program.flushEvents();
waitForSwing();
assertEquals("bob", function.getName());
@@ -378,7 +380,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
editLabel(fredSymbol);
setCheckbox(primaryCheckBox, true);
- dialogOK();
+ pressOk();
program.flushEvents();
waitForSwing();
assertEquals("fred", function.getName());
@@ -400,7 +402,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
Object selectedItem = namespacesComboBox.getSelectedItem();
assertEquals(ns, ((AddEditDialog.NamespaceWrapper) selectedItem).getNamespace());
- dialogCancel();
+ pressCancel();
}
@@ -414,7 +416,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(primaryCheckBox.isSelected());
assertTrue(!primaryCheckBox.isEnabled());
setText("aaaa");
- dialogOK();
+ pressOk();
s = st.getPrimarySymbol(refAddr);
assertEquals("aaaa", s.getName());
}
@@ -426,7 +428,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
editLabel(s);
setText("fred");
- dialogOK();
+ pressOk();
assertEquals("fred", s.getName());
s = st.getPrimarySymbol(a);
@@ -438,17 +440,17 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
public void testDuplicateLabelForEdit() {
addLabel(addr(0x100642a));
setText("printf");
- dialogOK();
+ pressOk();
addLabel(addr(0x100642a));
setText("fred");
- dialogOK();
+ pressOk();
Symbol s = getUniqueSymbol(program, "printf", null);
editLabel(s);
setText("fred");
- dialogOK();
+ pressOk();
assertTrue(dialog.isVisible());
assertTrue(dialog.getStatusText().length() > 0);
@@ -459,18 +461,18 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
Address a = addr(0x100642a);
addLabel(a);
setText("aaaa");
- dialogOK();
+ pressOk();
addLabel(a);
setText("bbbb");
- dialogOK();
+ pressOk();
addLabel(a);
setText("cccc");
- dialogOK();
+ pressOk();
Symbol s = getUniqueSymbol(program, "bbbb", null);
editLabel(s);
setText("zzzz");
- dialogOK();
+ pressOk();
assertNotNull(getUniqueSymbol(program, "aaaa", null));
assertNotNull(getUniqueSymbol(program, "zzzz", null));
assertNotNull(getUniqueSymbol(program, "cccc", null));
@@ -491,7 +493,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(!primaryCheckBox.isSelected());
assertTrue(primaryCheckBox.isEnabled());
setText("foo");
- dialogOK();
+ pressOk();
s = st.getPrimarySymbol(a);
assertNotNull(s);
@@ -509,16 +511,16 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
addLabel(s.getAddress());
setText("aaaa");
- dialogOK();
+ pressOk();
s = getUniqueSymbol(program, "aaaa", null);
editLabel(s);
setText("zzzz");
- dialogOK();
+ pressOk();
editLabel(s);
setText("bbbb");
- dialogOK();
+ pressOk();
assertEquals(3, recentLabels.size());
assertEquals("bbbb", recentLabels.get(0));
@@ -532,13 +534,13 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
addLabel(s.getAddress());
setScope(s.getParentNamespace());
setText("foo");
- dialogOK();
+ pressOk();
s = getUniqueSymbol(program, "foo", null);
editLabel(s);
assertTrue(primaryCheckBox.isEnabled());
assertTrue(!primaryCheckBox.isSelected());
- dialogOK();
+ pressOk();
}
@Test
@@ -579,7 +581,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
Address entryAddress = s.getAddress();
addLabel(entryAddress);
setText("label_1");
- dialogOK();
+ pressOk();
assertTrue("Encountered a problem adding a label to the Global " + "namespace",
!dialog.isVisible());
@@ -588,7 +590,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
s = getUniqueSymbol(program, "label_1", null);
editLabel(s);
setText("namespace_1::label_1");
- dialogOK();
+ pressOk();
// make sure there were no problems
assertTrue(
@@ -599,18 +601,128 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
s = st.getSymbols("label_1").next();
editLabel(s);
setText("Global::label_1");
- dialogOK();
+ pressOk();
assertTrue("Encountered a problem changing a symbol's namespace to " +
"the Global namespace while editing the symbol", !dialog.isVisible());
}
@Test
- public void testEntryNamespacePathWithAmbiguousFunctionName() {
- Symbol origEntry = getUniqueSymbol(program, "entry", null);
- assertNotNull(origEntry);
+ public void testSetLabelNamespace_InsideFunctionBody_ToFunctionNamespace() {
+ Symbol entry = getUniqueSymbol(program, "entry", null);
+ assertNotNull(entry);
- Symbol dupEntry = st.getPrimarySymbol(addr(0x1002239));
+ Address inBodyAddress = entry.getAddress().add(1);
+ addLabel(inBodyAddress);
+ String newName = "label_1";
+ setText("entry" + Namespace.DELIMITER + newName);
+ pressOk();
+ assertFalse("Encountered a problem adding a label to the Global namespace",
+ dialog.isVisible());
+
+ Symbol label1 = getSymbol(newName);
+ Namespace parentNamespace = label1.getParentNamespace();
+ assertTrue("Namespace is not a function", parentNamespace instanceof Function);
+ Function fun = (Function) parentNamespace;
+ assertEquals(entry.getAddress(), fun.getEntryPoint());
+ }
+
+ @Test
+ public void testSetLabelNamespace_InsideFunctionBody_ToExistingNonFunctionNamespace() {
+
+ Symbol entry = getUniqueSymbol(program, "entry", null);
+ assertNotNull(entry);
+
+ String namespaceName = "NewNamespace";
+ createNamespace(namespaceName);
+
+ Address inBodyAddress = entry.getAddress().add(1);
+ addLabel(inBodyAddress);
+ String newName = "label_1";
+ setText(namespaceName + Namespace.DELIMITER + newName);
+ pressOk();
+ assertFalse("Encountered a problem adding a label to the Global namespace",
+ dialog.isVisible());
+
+ Symbol label1 = getSymbol(newName);
+ Namespace parentNamespace = label1.getParentNamespace();
+ assertFalse("Namespace is not a function", parentNamespace instanceof Function);
+ }
+
+ @Test
+ public void testSetLabelNamespace_InsideFunctionBody_ToNonExistentNonFunctionNamespace() {
+
+ Symbol entry = getUniqueSymbol(program, "entry", null);
+ assertNotNull(entry);
+
+ String namespaceName = "NewNamespace";
+ Address inBodyAddress = entry.getAddress().add(1);
+ addLabel(inBodyAddress);
+ String newName = "label_1";
+ setText(namespaceName + Namespace.DELIMITER + newName);
+ pressOk();
+ assertFalse("Encountered a problem adding a label to the Global namespace",
+ dialog.isVisible());
+
+ Symbol label1 = getSymbol(newName);
+ Namespace parentNamespace = label1.getParentNamespace();
+ assertFalse("Namespace is not a function", parentNamespace instanceof Function);
+ }
+
+ @Test
+ public void testEntryNamespacePathWithAmbiguousFunctionName() {
+ Symbol entry = getUniqueSymbol(program, "entry", null);
+ assertNotNull(entry);
+
+ Address otherEntryAddress = addr(0x1002239);
+ Symbol dupEntry = createOtherEntry(otherEntryAddress);
+
+ Address inBodyAddress = otherEntryAddress.add(1);
+ addLabel(inBodyAddress);
+ String newName = "label_1";
+ setText("entry" + Namespace.DELIMITER + newName);
+ pressOk();
+ assertFalse("Encountered a problem adding a label to the Global namespace",
+ dialog.isVisible());
+
+ Symbol label1 = getSymbol(newName);
+ Namespace parentNamespace = label1.getParentNamespace();
+ assertTrue("Namespace is not a function", parentNamespace instanceof Function);
+ Function fun = (Function) parentNamespace;
+ assertEquals(dupEntry.getAddress(), fun.getEntryPoint());
+ }
+
+ @Test
+ public void testSetNamespace_NonExistentNamespace_SameNameAsFunction() throws Exception {
+
+ //
+ // Test that we can create a new namespace using the dialog when:
+ // 1) that namespace does not exist
+ // 2) the namespace matches the existing function name
+ // 3) the function name is not default
+ //
+
+ String functionName = "Foo";
+ Symbol function = createFunction(functionName);
+
+ editLabel(function);
+ String nsName = functionName;
+ setText(nsName + Namespace.DELIMITER + functionName);
+ pressOk();
+ assertFalse("Rename unsuccesful", dialog.isShowing());
+
+ Symbol newFunction = getSymbol(functionName);
+ Namespace parentNs = newFunction.getParentNamespace();
+ assertFalse(parentNs instanceof Function);
+ assertEquals(nsName, parentNs.getName());
+ }
+
+//==================================================================================================
+// Private Methods
+//==================================================================================================
+
+ private Symbol createOtherEntry(Address otherAddress) {
+ Symbol dupEntry = st.getPrimarySymbol(otherAddress);
assertNotNull(dupEntry);
int id = program.startTransaction("test");
@@ -618,42 +730,48 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
dupEntry.setName("entry", SourceType.USER_DEFINED);
}
catch (Exception e) {
- fail("Got Exception trying to set the function name to entry at 0x1002239 ");
+ fail("Got Exception trying to set the function name to entry at " + otherAddress);
}
finally {
program.endTransaction(id, true);
}
-
- Address entryAddress = dupEntry.getAddress();
- addLabel(entryAddress);
- setText("entry::label_1");
- dialogOK();
-
- assertTrue("Encountered a problem adding a label to the Global " + "namespace",
- !dialog.isVisible());
-
- SymbolIterator symbolIt = st.getSymbols("label_1");
- Symbol label1 = symbolIt.next();
- assertNotNull(label1);
- Namespace parentNamespace = label1.getParentNamespace();
- assertTrue(parentNamespace instanceof Function);
- Function fun = (Function) parentNamespace;
- assertEquals(dupEntry.getAddress(), fun.getEntryPoint());
+ return dupEntry;
+ }
+
+ private Symbol getSymbol(String functionName) {
+
+ SymbolIterator it = st.getSymbols(functionName);
+ Symbol newLabel = it.next();
+ assertNotNull(newLabel);
+ assertEquals(functionName, newLabel.getName());
+ return newLabel;
+ }
+
+ private Symbol createFunction(String name) throws Exception {
+ Symbol entry = getUniqueSymbol(program, "entry", null);
+ createEntryFunction();
+ editLabel(entry);
+ setText(name);
+ pressOk();
+
+ SymbolIterator it = st.getSymbols(name);
+ Symbol newLabel = it.next();
+ assertNotNull(newLabel);
+ assertEquals(name, newLabel.getName());
+ return newLabel;
}
-//==================================================================================================
-// Private Methods
-//==================================================================================================
private Address addr(long addr) {
return program.getAddressFactory().getAddress(Long.toHexString(addr));
}
- private void dialogCancel() {
+ private void pressCancel() {
runSwing(() -> invokeInstanceMethod("cancelCallback", dialog));
}
- private void dialogOK() {
- runSwing(() -> invokeInstanceMethod("okCallback", dialog));
+ private void pressOk() {
+ runSwing(() -> invokeInstanceMethod("okCallback", dialog), false);
+ waitForSwing();
}
private void setText(final String text) {
@@ -738,4 +856,8 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(tool.execute(cmd, program));
}
}
+
+ private void createNamespace(String name) {
+ applyCmd(program, new CreateNamespacesCmd(name, SourceType.USER_DEFINED));
+ }
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin1Test.java
index c267d9e113..5f7f26d3bc 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin1Test.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin1Test.java
@@ -651,7 +651,7 @@ public class SymbolTreePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
String newNamespace = "bob";
String prefix = "MY";
String newNameWithoutNamespace = prefix + s.getName();
- String newName = newNamespace + Namespace.NAMESPACE_DELIMITER + newNameWithoutNamespace;
+ String newName = newNamespace + Namespace.DELIMITER + newNameWithoutNamespace;
util.rename(advapi32Node, newName);
util.waitForTree();
assertEquals(newNameWithoutNamespace, s.getName());
@@ -681,7 +681,7 @@ public class SymbolTreePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
GTreeNode nsNode = newNsNode;
String newNamespace = "OuterNamespace";
String newName = "MyNamespace";
- String newFullName = newNamespace + Namespace.NAMESPACE_DELIMITER + newName;
+ String newFullName = newNamespace + Namespace.DELIMITER + newName;
setEditorText(path, nsNode, newFullName);
namespacesNode = rootNode.getChild("Namespaces");
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 654342d9ed..6cd1458227 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
@@ -1379,7 +1379,7 @@ public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
Command command = new CreateNamespacesCmd(namespaceName, SourceType.USER_DEFINED);
if (tool.execute(command, program)) {
List namespaces =
- NamespaceUtils.getNamespaces(namespaceName, null, program);
+ NamespaceUtils.getNamespaceByPath(program, null, namespaceName);
if (namespaces.size() != 1) {
Assert.fail("Unable to find the newly created parent namespace.");
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/label/CreateNamespacesCmdTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/label/CreateNamespacesCmdTest.java
index 8791f88077..c6d1485b0e 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/label/CreateNamespacesCmdTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/label/CreateNamespacesCmdTest.java
@@ -308,7 +308,7 @@ public class CreateNamespacesCmdTest extends AbstractGenericTest {
for (int i = 0; i < namespaceNames.length; i++) {
buffer.append(namespaceNames[i]);
if (i + 1 < namespaceNames.length) {
- buffer.append(Namespace.NAMESPACE_DELIMITER);
+ buffer.append(Namespace.DELIMITER);
}
}
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateRtti1BackgroundCmd.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateRtti1BackgroundCmd.java
index 06acd97d3e..2a993b5f4b 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateRtti1BackgroundCmd.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateRtti1BackgroundCmd.java
@@ -107,7 +107,7 @@ public class CreateRtti1BackgroundCmd extends AbstractCreateDataBackgroundCmd