Improvements made to GhidraScript and FlatProgramAPI createLabel methods

set allow namespace specification and handle label promotion to function
name when makePrimary is true at existing function entry point.
This commit is contained in:
ghidra1 2020-05-15 11:54:27 -04:00
parent 7385544bed
commit 82ebcb26f6
3 changed files with 60 additions and 21 deletions

View file

@ -33,19 +33,21 @@ public class SetLabelPrimaryCmd implements Command {
private SymbolTable st;
private Address addr;
private String name;
private Namespace scope;
private Namespace namespace;
private String errorMsg;
private Symbol symbol;
/**
* Constructs a new command for setting the primary state of a label.
* @param addr the address of the label to make primary.
* @param name the name of the label to make primary.
* @param scope the scope of the label to make primary. (the namespace that the label is associated with)
* @param namespace the parent namespace of the label to make primary.
*/
public SetLabelPrimaryCmd(Address addr, String name, Namespace scope) {
public SetLabelPrimaryCmd(Address addr, String name, Namespace namespace) {
this.addr = addr;
this.name = name;
this.scope = scope;
this.namespace = namespace;
}
/**
@ -57,27 +59,29 @@ public class SetLabelPrimaryCmd implements Command {
Program program = (Program) obj;
st = program.getSymbolTable();
Symbol oldSymbol = st.getPrimarySymbol(addr);
Symbol newSymbol = st.getSymbol(name, addr, scope);
if (oldSymbol == null) {
errorMsg = "No Symbols at address: " + addr;
return false;
}
if (newSymbol == null) {
symbol = st.getSymbol(name, addr, namespace);
if (symbol == null) {
// no new symbol - not an error condition if the previous symbol was dynamic. The
// assumption here is that the user has performed an operation that did not actually
// change the state of the symbol, like changing the namespace of a default symbol,
// which has no effect
if (!oldSymbol.isDynamic()) {
errorMsg =
"Symbol " + name + " does not exist in namespace " + scope + " at address " +
"Symbol " + name + " does not exist in namespace " + namespace +
" at address " +
addr;
return false;
}
return true;
}
if (oldSymbol.getSymbolType() == SymbolType.FUNCTION) {
if (oldSymbol == newSymbol) {
if (oldSymbol == symbol) {
return true; // function symbol is already primary
}
// keep the function symbol and rename it to the new symbol name;
@ -85,14 +89,17 @@ public class SetLabelPrimaryCmd implements Command {
String oldName = oldSymbol.getName();
SourceType oldSource = oldSymbol.getSource();
Namespace oldParent = oldSymbol.getParentNamespace();
Namespace parentNamespace = newSymbol.getParentNamespace();
if (parentNamespace == oldSymbol.getObject()) {
// parent is the same as the function, so drop the namespace and use global
parentNamespace = program.getGlobalNamespace();
if (symbol.getParentNamespace() == oldSymbol.getObject()) {
errorMsg = "local label can not be made primary at function entry point: " +
symbol.getName(true);
return false;
}
st.removeSymbolSpecial(newSymbol);
SourceType symbolSource = symbol.getSource();
namespace = symbol.getParentNamespace(); // update namespace in case null was specified
symbol.delete();
try {
oldSymbol.setNameAndNamespace(name, parentNamespace, newSymbol.getSource());
oldSymbol.setNameAndNamespace(name, namespace, symbolSource);
symbol = oldSymbol;
// If renamed oldSymbol is now Default source don't keep old name (handles special Thunk rename case)
if (oldSource != SourceType.DEFAULT && oldSymbol.getSource() != SourceType.DEFAULT) {
// put the other symbol back using the old namespace and old source
@ -111,7 +118,10 @@ public class SetLabelPrimaryCmd implements Command {
}
return false;
}
newSymbol.setPrimary();
if (!symbol.setPrimary()) {
errorMsg = "Set primary not permitted for " + symbol.getName(true);
return false;
}
return true;
}
@ -131,4 +141,12 @@ public class SetLabelPrimaryCmd implements Command {
return "Set Primary Label";
}
/**
* Get transformed symbol
* @return symbol (may be null if command did not execute successfully)
*/
public Symbol getSymbol() {
return symbol;
}
}

View file

@ -25,6 +25,7 @@ import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.cmd.function.DeleteFunctionCmd;
import ghidra.app.cmd.label.DeleteLabelCmd;
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.plugin.core.clear.ClearCmd;
import ghidra.app.plugin.core.clear.ClearOptions;
@ -394,7 +395,7 @@ public class FlatProgramAPI {
* @param address the address to create the symbol
* @param name the name of the symbol
* @param makePrimary true if the symbol should be made primary
* @return the newly created symbol
* @return the newly created code or function symbol
*/
public final Symbol createLabel(Address address, String name, boolean makePrimary)
throws Exception {
@ -420,15 +421,35 @@ public class FlatProgramAPI {
* @param name the name of the symbol
* @param makePrimary true if the symbol should be made primary
* @param sourceType the source type.
* @return the newly created symbol
* @return the newly created code or function symbol
*/
public final Symbol createLabel(Address address, String name, boolean makePrimary,
SourceType sourceType) throws Exception {
return createLabel(address, name, null, makePrimary, sourceType);
}
/**
* Creates a label at the specified address in the specified namespace.
* If makePrimary==true, then the new label is made primary if permitted.
* If makeUnique==true, then if the name is a duplicate, the address
* will be concatenated to name to make it unique.
* @param address the address to create the symbol
* @param name the name of the symbol
* @param namespace label's parent namespace
* @param makePrimary true if the symbol should be made primary
* @param sourceType the source type.
* @return the newly created code or function symbol
*/
public final Symbol createLabel(Address address, String name, Namespace namespace,
boolean makePrimary, SourceType sourceType) throws Exception {
Symbol symbol;
SymbolTable symbolTable = currentProgram.getSymbolTable();
symbol = symbolTable.createLabel(address, name, null, sourceType);
if (makePrimary) {
symbol.setPrimary();
symbol = symbolTable.createLabel(address, name, namespace, sourceType);
if (makePrimary && !symbol.isPrimary()) {
SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(address, name, namespace);
if (cmd.applyTo(currentProgram)) {
symbol = cmd.getSymbol();
}
}
return symbol;
}

View file

@ -91,7 +91,7 @@ public interface SymbolTable {
* @param namespace the namespace of the symbol.
* @param source the source of this symbol
* <br>Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT.
*
* @return new code or function symbol
* @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type
* that doesn't allow it, or an improper addr if specified
*/