mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
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:
parent
7385544bed
commit
82ebcb26f6
3 changed files with 60 additions and 21 deletions
|
@ -33,19 +33,21 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
private SymbolTable st;
|
private SymbolTable st;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private String name;
|
private String name;
|
||||||
private Namespace scope;
|
private Namespace namespace;
|
||||||
private String errorMsg;
|
private String errorMsg;
|
||||||
|
|
||||||
|
private Symbol symbol;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for setting the primary state of a label.
|
* Constructs a new command for setting the primary state of a label.
|
||||||
* @param addr the address of the label to make primary.
|
* @param addr the address of the label to make primary.
|
||||||
* @param name the name 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.addr = addr;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.scope = scope;
|
this.namespace = namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,27 +59,29 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
Program program = (Program) obj;
|
Program program = (Program) obj;
|
||||||
st = program.getSymbolTable();
|
st = program.getSymbolTable();
|
||||||
Symbol oldSymbol = st.getPrimarySymbol(addr);
|
Symbol oldSymbol = st.getPrimarySymbol(addr);
|
||||||
Symbol newSymbol = st.getSymbol(name, addr, scope);
|
|
||||||
|
|
||||||
if (oldSymbol == null) {
|
if (oldSymbol == null) {
|
||||||
errorMsg = "No Symbols at address: " + addr;
|
errorMsg = "No Symbols at address: " + addr;
|
||||||
return false;
|
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
|
// 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
|
// 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,
|
// change the state of the symbol, like changing the namespace of a default symbol,
|
||||||
// which has no effect
|
// which has no effect
|
||||||
if (!oldSymbol.isDynamic()) {
|
if (!oldSymbol.isDynamic()) {
|
||||||
errorMsg =
|
errorMsg =
|
||||||
"Symbol " + name + " does not exist in namespace " + scope + " at address " +
|
"Symbol " + name + " does not exist in namespace " + namespace +
|
||||||
|
" at address " +
|
||||||
addr;
|
addr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (oldSymbol.getSymbolType() == SymbolType.FUNCTION) {
|
if (oldSymbol.getSymbolType() == SymbolType.FUNCTION) {
|
||||||
if (oldSymbol == newSymbol) {
|
if (oldSymbol == symbol) {
|
||||||
return true; // function symbol is already primary
|
return true; // function symbol is already primary
|
||||||
}
|
}
|
||||||
// keep the function symbol and rename it to the new symbol name;
|
// 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();
|
String oldName = oldSymbol.getName();
|
||||||
SourceType oldSource = oldSymbol.getSource();
|
SourceType oldSource = oldSymbol.getSource();
|
||||||
Namespace oldParent = oldSymbol.getParentNamespace();
|
Namespace oldParent = oldSymbol.getParentNamespace();
|
||||||
Namespace parentNamespace = newSymbol.getParentNamespace();
|
if (symbol.getParentNamespace() == oldSymbol.getObject()) {
|
||||||
if (parentNamespace == oldSymbol.getObject()) {
|
errorMsg = "local label can not be made primary at function entry point: " +
|
||||||
// parent is the same as the function, so drop the namespace and use global
|
symbol.getName(true);
|
||||||
parentNamespace = program.getGlobalNamespace();
|
return false;
|
||||||
}
|
}
|
||||||
st.removeSymbolSpecial(newSymbol);
|
SourceType symbolSource = symbol.getSource();
|
||||||
|
namespace = symbol.getParentNamespace(); // update namespace in case null was specified
|
||||||
|
symbol.delete();
|
||||||
try {
|
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 renamed oldSymbol is now Default source don't keep old name (handles special Thunk rename case)
|
||||||
if (oldSource != SourceType.DEFAULT && oldSymbol.getSource() != SourceType.DEFAULT) {
|
if (oldSource != SourceType.DEFAULT && oldSymbol.getSource() != SourceType.DEFAULT) {
|
||||||
// put the other symbol back using the old namespace and old source
|
// put the other symbol back using the old namespace and old source
|
||||||
|
@ -111,7 +118,10 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
newSymbol.setPrimary();
|
if (!symbol.setPrimary()) {
|
||||||
|
errorMsg = "Set primary not permitted for " + symbol.getName(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,4 +141,12 @@ public class SetLabelPrimaryCmd implements Command {
|
||||||
return "Set Primary Label";
|
return "Set Primary Label";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transformed symbol
|
||||||
|
* @return symbol (may be null if command did not execute successfully)
|
||||||
|
*/
|
||||||
|
public Symbol getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.cmd.function.CreateFunctionCmd;
|
import ghidra.app.cmd.function.CreateFunctionCmd;
|
||||||
import ghidra.app.cmd.function.DeleteFunctionCmd;
|
import ghidra.app.cmd.function.DeleteFunctionCmd;
|
||||||
import ghidra.app.cmd.label.DeleteLabelCmd;
|
import ghidra.app.cmd.label.DeleteLabelCmd;
|
||||||
|
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
import ghidra.app.plugin.core.clear.ClearCmd;
|
import ghidra.app.plugin.core.clear.ClearCmd;
|
||||||
import ghidra.app.plugin.core.clear.ClearOptions;
|
import ghidra.app.plugin.core.clear.ClearOptions;
|
||||||
|
@ -394,7 +395,7 @@ public class FlatProgramAPI {
|
||||||
* @param address the address to create the symbol
|
* @param address the address to create the symbol
|
||||||
* @param name the name of the symbol
|
* @param name the name of the symbol
|
||||||
* @param makePrimary true if the symbol should be made primary
|
* @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)
|
public final Symbol createLabel(Address address, String name, boolean makePrimary)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
@ -420,15 +421,35 @@ public class FlatProgramAPI {
|
||||||
* @param name the name of the symbol
|
* @param name the name of the symbol
|
||||||
* @param makePrimary true if the symbol should be made primary
|
* @param makePrimary true if the symbol should be made primary
|
||||||
* @param sourceType the source type.
|
* @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,
|
public final Symbol createLabel(Address address, String name, boolean makePrimary,
|
||||||
SourceType sourceType) throws Exception {
|
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;
|
Symbol symbol;
|
||||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||||
symbol = symbolTable.createLabel(address, name, null, sourceType);
|
symbol = symbolTable.createLabel(address, name, namespace, sourceType);
|
||||||
if (makePrimary) {
|
if (makePrimary && !symbol.isPrimary()) {
|
||||||
symbol.setPrimary();
|
SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(address, name, namespace);
|
||||||
|
if (cmd.applyTo(currentProgram)) {
|
||||||
|
symbol = cmd.getSymbol();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public interface SymbolTable {
|
||||||
* @param namespace the namespace of the symbol.
|
* @param namespace the namespace of the symbol.
|
||||||
* @param source the source of this symbol
|
* @param source the source of this symbol
|
||||||
* <br>Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT.
|
* <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
|
* @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
|
* that doesn't allow it, or an improper addr if specified
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue