mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +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 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue