diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/flatapi/FlatProgramAPI.java b/Ghidra/Features/Base/src/main/java/ghidra/program/flatapi/FlatProgramAPI.java index 33933b397e..b5d5f5cc96 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/flatapi/FlatProgramAPI.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/flatapi/FlatProgramAPI.java @@ -246,7 +246,7 @@ public class FlatProgramAPI { /** * Clears the code units (instructions or data) in the specified range. * @param start the start address - * @param end the end address + * @param end the end address (INCLUSIVE) * @throws CancelledException if cancelled */ public final void clearListing(Address start, Address end) throws CancelledException { @@ -1506,7 +1506,7 @@ public class FlatProgramAPI { /** * Returns the non-function namespace with the given name contained inside the * specified parent namespace. - * Pass null for namespace to indicate the global namespace. + * Pass null for parent to indicate the global namespace. * @param parent the parent namespace, or null for global namespace * @param namespaceName the requested namespace's name * @return the namespace with the given name or null if not found @@ -1514,6 +1514,66 @@ public class FlatProgramAPI { public final Namespace getNamespace(Namespace parent, String namespaceName) { return currentProgram.getSymbolTable().getNamespace(namespaceName, parent); } + +/** + * Creates a new {@link Namespace} with the given name contained inside the + * specified parent namespace. + * Pass null for parent to indicate the global namespace. + * If a {@link Namespace} or {@link GhidraClass} with the given name already exists, the + * existing one will be returned. + * @param parent the parent namespace, or null for global namespace + * @param namespaceName the requested namespace's name + * @return the namespace with the given name + * @throws DuplicateNameException if a {@link Library} symbol exists with the given name + * @throws InvalidInputException if the name is invalid + * @throws IllegalArgumentException if parent Namespace does not correspond to + * currerntProgram + */ + public final Namespace createNamespace(Namespace parent, String namespaceName) + throws DuplicateNameException, InvalidInputException { + SymbolTable symbolTable = currentProgram.getSymbolTable(); + Namespace ns = symbolTable.getNamespace(namespaceName, parent); + if (ns != null) { + SymbolType type = ns.getSymbol().getSymbolType(); + if (type == SymbolType.NAMESPACE || type == SymbolType.CLASS) { + return ns; + } + } + return symbolTable.createNameSpace(parent, namespaceName, SourceType.USER_DEFINED); + } + + /** + * Creates a new {@link GhidraClass} with the given name contained inside the + * specified parent namespace. + * Pass null for parent to indicate the global namespace. + * If a GhidraClass with the given name already exists, the existing one will be returned. + * @param parent the parent namespace, or null for global namespace + * @param className the requested classes name + * @return the GhidraClass with the given name + * @throws InvalidInputException if the name is invalid + * @throws DuplicateNameException thrown if a {@link Library} or {@link Namespace} + * symbol already exists with the given name. + * Use {@link SymbolTable#convertNamespaceToClass(Namespace)} for converting an + * existing Namespace to a GhidraClass. + * @throws IllegalArgumentException if the given parent namespace is not from + * the {@link #currentProgram}. + * @throws ConcurrentModificationException if the given parent has been deleted + * @throws IllegalArgumentException if parent Namespace does not correspond to + * currerntProgram + * @see SymbolTable#convertNamespaceToClass(Namespace) + */ + public final GhidraClass createClass(Namespace parent, String className) + throws DuplicateNameException, InvalidInputException { + SymbolTable symbolTable = currentProgram.getSymbolTable(); + Namespace ns = symbolTable.getNamespace(className, parent); + if (ns != null) { + SymbolType type = ns.getSymbol().getSymbolType(); + if (type == SymbolType.CLASS) { + return (GhidraClass) ns; + } + } + return symbolTable.createClass(parent, className, SourceType.USER_DEFINED); + } /** * Creates a fragment in the root folder of the default program tree. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java index 8657972ff9..ee31fac974 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java @@ -2579,6 +2579,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { checkValidNamespaceArgument(namespace); + if (namespace.isGlobal() || namespace.isLibrary()) { + throw new IllegalArgumentException( + "May not convert namespace to class: " + namespace.getName(true)); + } + Symbol namespaceSymbol = namespace.getSymbol(); String name = namespaceSymbol.getName(); SourceType originalSource = namespaceSymbol.getSource(); @@ -2729,7 +2734,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { * it will be returned. * @param addr the address for the new symbol (memory or external) * @param name the name of the new symbol - * @param namespace the namespace for the new symbol + * @param namespace the namespace for the new symbol (null may be specified for global namespace) * @param source the SourceType of the new symbol * @param stringData special use depending on the symbol type and whether or not it is external * @return the new symbol @@ -2789,7 +2794,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { * * @param addr the address for the new symbol * @param name the name of the new symbol - * @param namespace the namespace for the new symbol + * @param namespace the namespace for the new symbol (null may be specified for global namespace) * @param source the SourceType of the new symbol * @param stringData special use depending on the symbol type and whether or not it is external. * @return the new symbol diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java index 43096be32b..3c97f23937 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java @@ -86,7 +86,8 @@ public interface SymbolTable { * @throws InvalidInputException thrown if names contains white space, is zero length, or is * null for non-default source. Also thrown if invalid parentNamespace is specified. * @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type - * that doesn't allow it, or an improper addr is specified + * that doesn't allow it, specify an improper addr, or specify a namespace which does not + * correspond to this symbol table's program. */ public Symbol createLabel(Address addr, String name, Namespace namespace, SourceType source) throws InvalidInputException; @@ -137,6 +138,8 @@ public interface SymbolTable { * @param namespace the namespace of the symbol to retrieve. May be null which indicates global * namespace. * @return the symbol which matches the specified criteria or null if not found + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. * @see #getGlobalSymbol(String, Address) for a convenience method if the namespace is the * global namespace. */ @@ -182,6 +185,8 @@ public interface SymbolTable { * @param name the name of the symbols to search for. * @param namespace the namespace to search. If null, then the global namespace is assumed. * @return a list of all the label or function symbols with the given name in the given namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public List getLabelOrFunctionSymbols(String name, Namespace namespace); @@ -190,6 +195,8 @@ public interface SymbolTable { * @param name the name of the namespace symbol to retrieve. * @param namespace the namespace containing the symbol to retrieve. * @return a generic namespace symbol with the given name in the given namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public Symbol getNamespaceSymbol(String name, Namespace namespace); @@ -205,6 +212,8 @@ public interface SymbolTable { * @param name the name of the class. * @param namespace the namespace to search for the class. * @return the class symbol with the given name in the given namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public Symbol getClassSymbol(String name, Namespace namespace); @@ -213,6 +222,8 @@ public interface SymbolTable { * @param name the name of the parameter. * @param namespace the namespace (function) to search for the class. * @return the parameter symbol with the given name in the given namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public Symbol getParameterSymbol(String name, Namespace namespace); @@ -221,6 +232,8 @@ public interface SymbolTable { * @param name the name of the local variable. * @param namespace the namespace (function) to search for the class. * @return the local variable symbol with the given name in the given namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public Symbol getLocalVariableSymbol(String name, Namespace namespace); @@ -233,6 +246,8 @@ public interface SymbolTable { * @param name the name of the symbols to retrieve. * @param namespace the namespace to search for symbols. * @return all symbols which satisfy specified criteria + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public List getSymbols(String name, Namespace namespace); @@ -252,6 +267,8 @@ public interface SymbolTable { * @param name the name of the namespace to be retrieved. * @param namespace the parent namespace of the namespace to be retrieved. * @return the namespace with the given name in the given parent namespace. + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public Namespace getNamespace(String name, Namespace namespace); @@ -333,6 +350,8 @@ public interface SymbolTable { * * @param namespace the namespace to search for symbols. * @return symbol iterator + * @throws IllegalArgumentException amespace which does not correspond to this + * symbol table's program. */ public SymbolIterator getSymbols(Namespace namespace); @@ -527,14 +546,15 @@ public interface SymbolTable { /** * Create a class namespace in the given parent namespace. - * @param parent parent namespace + * @param parent parent namespace (may be null for global namespace) * @param name name of the namespace * @param source the source of this class namespace's symbol * @return new class namespace * @throws DuplicateNameException thrown if another non function or label symbol exists with * the given name * @throws InvalidInputException throw if the name has invalid characters or is null - * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. + * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT' + * or specify a parent Namespace which does not correspond to this symbol table's program. */ public GhidraClass createClass(Namespace parent, String name, SourceType source) throws DuplicateNameException, InvalidInputException; @@ -565,14 +585,15 @@ public interface SymbolTable { /** * Creates a new namespace. - * @param parent the parent namespace for the new namespace + * @param parent the parent namespace for the new namespace (may be null for global namespace) * @param name the name of the new namespace * @param source the source of this namespace's symbol * @return the new Namespace object. * @throws DuplicateNameException thrown if another non function or label symbol * exists with the given name * @throws InvalidInputException if the name is invalid. - * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. + * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT' + * or specify a parent Namespace which does not correspond to this symbol table's program. */ public Namespace createNameSpace(Namespace parent, String name, SourceType source) throws DuplicateNameException, InvalidInputException; @@ -585,6 +606,8 @@ public interface SymbolTable { * @throws IllegalArgumentException if the given parent namespace is from a different program * than that of this symbol table * @throws ConcurrentModificationException if the given parent namespace has been deleted + * @throws IllegalArgumentException namespace does not correspond to this symbol table's program + * or namespace not allowed (e.g., global or library namespace). */ public GhidraClass convertNamespaceToClass(Namespace namespace);