mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 15:13:09 +08:00
GP-3350 revised ApplyFunctionSignatureCmd with new FunctionRenameOption
enum
This commit is contained in:
+48
-37
@@ -41,20 +41,22 @@ import ghidra.util.task.TaskMonitor;
|
|||||||
public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
||||||
private Address entryPt;
|
private Address entryPt;
|
||||||
private SourceType source;
|
private SourceType source;
|
||||||
private boolean setName;
|
private FunctionRenameOption functionRenameOption;
|
||||||
private boolean preserveCallingConvention;
|
private boolean preserveCallingConvention;
|
||||||
private FunctionSignature signature;
|
private FunctionSignature signature;
|
||||||
private Program program;
|
private Program program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new command for creating a function.
|
* Constructs a new command for creating a function.
|
||||||
|
* Only a function with a default name will be renamed to the function signature's name
|
||||||
|
* (see {@link FunctionRenameOption#RENAME_IF_DEFAULT}).
|
||||||
* @param entry entry point address for the function to be created.
|
* @param entry entry point address for the function to be created.
|
||||||
* @param signature function signature to apply
|
* @param signature function signature to apply
|
||||||
* @param source the source of this function signature
|
* @param source the source of this function signature
|
||||||
*/
|
*/
|
||||||
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature,
|
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature,
|
||||||
SourceType source) {
|
SourceType source) {
|
||||||
this(entry, signature, source, false, false);
|
this(entry, signature, source, false, FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,17 +65,35 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||||||
* @param signature function signature to apply
|
* @param signature function signature to apply
|
||||||
* @param source the source of this function signature
|
* @param source the source of this function signature
|
||||||
* @param preserveCallingConvention if true the function calling convention will not be changed
|
* @param preserveCallingConvention if true the function calling convention will not be changed
|
||||||
* @param setName true if name of the function should be set to the name
|
* @param forceSetName true if name of the function should be set to the name, otherwise name
|
||||||
* of the signature
|
* will only be set name if currently default (e.g., FUN_1234). A value of true is equivalent to
|
||||||
|
* {@link FunctionRenameOption#RENAME}, while a value of false is equivalent to
|
||||||
|
* {@link FunctionRenameOption#RENAME_IF_DEFAULT}.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "10.3", forRemoval = true)
|
||||||
|
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature, SourceType source,
|
||||||
|
boolean preserveCallingConvention, boolean forceSetName) {
|
||||||
|
this(entry, signature, source, preserveCallingConvention,
|
||||||
|
forceSetName ? FunctionRenameOption.RENAME : FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new command for creating a function.
|
||||||
|
* @param entry entry point address for the function to be created.
|
||||||
|
* @param signature function signature to apply
|
||||||
|
* @param source the source of this function signature
|
||||||
|
* @param preserveCallingConvention if true the function calling convention will not be changed
|
||||||
|
* @param functionRenameOption controls renaming of the function using the name from the
|
||||||
|
* specified function signature.
|
||||||
*/
|
*/
|
||||||
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature, SourceType source,
|
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature, SourceType source,
|
||||||
boolean preserveCallingConvention, boolean setName) {
|
boolean preserveCallingConvention, FunctionRenameOption functionRenameOption) {
|
||||||
super("Create Function", true, false, false);
|
super("Create Function", true, false, false);
|
||||||
this.entryPt = entry;
|
this.entryPt = entry;
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.preserveCallingConvention = preserveCallingConvention;
|
this.preserveCallingConvention = preserveCallingConvention;
|
||||||
this.setName = setName;
|
this.functionRenameOption = functionRenameOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,7 +109,7 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||||||
monitor.setMessage("Rename " + func.getName());
|
monitor.setMessage("Rename " + func.getName());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setSignature(func, signature, preserveCallingConvention, setName, source);
|
setSignature(func);
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
Msg.warn(this, e.getMessage());
|
Msg.warn(this, e.getMessage());
|
||||||
@@ -106,22 +126,14 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a function's signature in the program.
|
* Sets a function's signature in the program using the command details.
|
||||||
* @param func the function
|
* @param func the function
|
||||||
* @param signature the signature to apply
|
|
||||||
* @param preserveCallingConvention if true, the functions calling convention will not be
|
|
||||||
* modified
|
|
||||||
* @param forceName force the name of the signature onto the function
|
|
||||||
* normally the name is only set on default function names (not user-defined).
|
|
||||||
* @param source the source of this function signature
|
|
||||||
*/
|
*/
|
||||||
private boolean setSignature(Function func, FunctionSignature signature,
|
private boolean setSignature(Function func) throws InvalidInputException {
|
||||||
boolean preserveCallingConvention, boolean forceName, SourceType source)
|
|
||||||
throws InvalidInputException {
|
|
||||||
|
|
||||||
// take on the signatures name if this is not a user defined symbol
|
// take on the signatures name if this is not a user defined symbol
|
||||||
String name = signature.getName();
|
String name = signature.getName();
|
||||||
setName(func, name, source, forceName);
|
setName(func, name);
|
||||||
|
|
||||||
CompilerSpec compilerSpec = program.getCompilerSpec();
|
CompilerSpec compilerSpec = program.getCompilerSpec();
|
||||||
String conventionName = getCallingConvention(func, compilerSpec);
|
String conventionName = getCallingConvention(func, compilerSpec);
|
||||||
@@ -293,37 +305,38 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setName(Function function, String name, SourceType source,
|
/**
|
||||||
boolean forceName) throws InvalidInputException {
|
*
|
||||||
|
* @param function function to be renamed
|
||||||
|
* @param name function name to be applied
|
||||||
|
* @throws InvalidInputException if invalid name is specified or a duplicate name occurs
|
||||||
|
*/
|
||||||
|
private void setName(Function function, String name) throws InvalidInputException {
|
||||||
|
|
||||||
if (name == null) {
|
if (functionRenameOption == FunctionRenameOption.NO_CHANGE || name == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program program = function.getProgram();
|
|
||||||
Address entryPoint = function.getEntryPoint();
|
|
||||||
SymbolUtilities.validateName(name);
|
SymbolUtilities.validateName(name);
|
||||||
|
if (function.getName().equals(name)) {
|
||||||
SymbolTable symbolTable = program.getSymbolTable();
|
|
||||||
Symbol sym = symbolTable.getPrimarySymbol(entryPoint);
|
|
||||||
if (sym == null || sym.getName().equals(name)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!forceName && sym.getSource() != SourceType.DEFAULT) {
|
if (functionRenameOption == FunctionRenameOption.RENAME_IF_DEFAULT &&
|
||||||
|
function.getSymbol().getSource() != SourceType.DEFAULT) {
|
||||||
// not default and we are not forcing the rename
|
// not default and we are not forcing the rename
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
removeCodeSymbol(symbolTable, entryPoint, name, function.getParentNamespace());
|
removeCodeSymbol(function.getEntryPoint(), name, function.getParentNamespace());
|
||||||
sym.setName(name, source);
|
function.setName(name, source);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
|
// unexpected
|
||||||
throw new InvalidInputException(
|
throw new InvalidInputException(
|
||||||
"Function name conflict occurred when applying function signature.");
|
"Function name conflict occurred when applying function signature.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -361,13 +374,11 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||||||
return getUniqueName(symbolTable, function, name);
|
return getUniqueName(symbolTable, function, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void removeCodeSymbol(SymbolTable symbolTable, Address address, String name,
|
private void removeCodeSymbol(Address address, String name, Namespace namespace) {
|
||||||
Namespace namespace) {
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
Symbol otherSym = symbolTable.getSymbol(name, address, namespace);
|
Symbol otherSym = symbolTable.getSymbol(name, address, namespace);
|
||||||
if (otherSym != null) {
|
if (otherSym != null && otherSym.getSymbolType() == SymbolType.LABEL) {
|
||||||
if (otherSym.getSymbolType() == SymbolType.LABEL) {
|
otherSym.delete(); // remove label so function rename may use it
|
||||||
otherSym.delete(); // replace label if function name matches
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.cmd.function;
|
||||||
|
|
||||||
|
import ghidra.program.model.data.FunctionDefinition;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.listing.FunctionSignature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Option for controlling the renaming of a {@link Function} when applying a
|
||||||
|
* {@link FunctionSignature} or {@link FunctionDefinition}.
|
||||||
|
*
|
||||||
|
* See {@link ApplyFunctionSignatureCmd}.
|
||||||
|
*/
|
||||||
|
public enum FunctionRenameOption {
|
||||||
|
/**
|
||||||
|
* {@link #NO_CHANGE} indicates that the current {@link Function} name should be changed.
|
||||||
|
*/
|
||||||
|
NO_CHANGE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link #RENAME_IF_DEFAULT} indicates that the current {@link Function} name should be only
|
||||||
|
* be changed if it is a default name (e.g., FUN_1234).
|
||||||
|
*/
|
||||||
|
RENAME_IF_DEFAULT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link #RENAME} indicates that the current {@link Function} name should always be changed.
|
||||||
|
*/
|
||||||
|
RENAME;
|
||||||
|
}
|
||||||
+2
-1
@@ -19,6 +19,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||||
|
import ghidra.app.cmd.function.FunctionRenameOption;
|
||||||
import ghidra.framework.cmd.Command;
|
import ghidra.framework.cmd.Command;
|
||||||
import ghidra.framework.cmd.CompoundCmd;
|
import ghidra.framework.cmd.CompoundCmd;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
@@ -175,7 +176,7 @@ public class EditFunctionSignatureDialog extends AbstractEditFunctionSignatureDi
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), definition,
|
cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), definition,
|
||||||
SourceType.USER_DEFINED, true, true);
|
SourceType.USER_DEFINED, true, FunctionRenameOption.RENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompoundCmd compoundCommand = new CompoundCmd("Update Function Signature");
|
CompoundCmd compoundCommand = new CompoundCmd("Update Function Signature");
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ public class DemangledFunction extends DemangledObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(),
|
ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(),
|
||||||
signature, SourceType.IMPORTED, true, false);
|
signature, SourceType.IMPORTED, true, FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||||
cmd.applyTo(program);
|
cmd.applyTo(program);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class FunctionsXmlMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplyFunctionSignatureCmd afsCmd = new ApplyFunctionSignatureCmd(func.getEntryPoint(),
|
ApplyFunctionSignatureCmd afsCmd = new ApplyFunctionSignatureCmd(func.getEntryPoint(),
|
||||||
funcDef, SourceType.IMPORTED, false, false);
|
funcDef, SourceType.IMPORTED, false, FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||||
if (!afsCmd.applyTo(program, monitor)) {
|
if (!afsCmd.applyTo(program, monitor)) {
|
||||||
// TODO: continue trying to add local vars after failing to update the function signature?
|
// TODO: continue trying to add local vars after failing to update the function signature?
|
||||||
log.appendMsg("Failed to update function " + funcDesc(func) + " with signature \"" +
|
log.appendMsg("Failed to update function " + funcDesc(func) + " with signature \"" +
|
||||||
|
|||||||
Reference in New Issue
Block a user