mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-10-22 21:21:02 +00:00
Merge branch 'GP-3350_ghidra1_ReviseApplyFunctionSignatureCmd'
This commit is contained in:
commit
f862cdd93d
|
@ -41,20 +41,22 @@ import ghidra.util.task.TaskMonitor;
|
|||
public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
||||
private Address entryPt;
|
||||
private SourceType source;
|
||||
private boolean setName;
|
||||
private FunctionRenameOption functionRenameOption;
|
||||
private boolean preserveCallingConvention;
|
||||
private FunctionSignature signature;
|
||||
private Program program;
|
||||
|
||||
/**
|
||||
* 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 signature function signature to apply
|
||||
* @param source the source of this function signature
|
||||
*/
|
||||
public ApplyFunctionSignatureCmd(Address entry, FunctionSignature signature,
|
||||
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 source the source of this function signature
|
||||
* @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
|
||||
* of the signature
|
||||
* @param forceSetName true if name of the function should be set to the name, otherwise name
|
||||
* 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,
|
||||
boolean preserveCallingConvention, boolean setName) {
|
||||
boolean preserveCallingConvention, FunctionRenameOption functionRenameOption) {
|
||||
super("Create Function", true, false, false);
|
||||
this.entryPt = entry;
|
||||
this.signature = signature;
|
||||
this.source = source;
|
||||
this.preserveCallingConvention = preserveCallingConvention;
|
||||
this.setName = setName;
|
||||
this.functionRenameOption = functionRenameOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,7 +109,7 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||
monitor.setMessage("Rename " + func.getName());
|
||||
|
||||
try {
|
||||
setSignature(func, signature, preserveCallingConvention, setName, source);
|
||||
setSignature(func);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
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 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,
|
||||
boolean preserveCallingConvention, boolean forceName, SourceType source)
|
||||
throws InvalidInputException {
|
||||
private boolean setSignature(Function func) throws InvalidInputException {
|
||||
|
||||
// take on the signatures name if this is not a user defined symbol
|
||||
String name = signature.getName();
|
||||
setName(func, name, source, forceName);
|
||||
setName(func, name);
|
||||
|
||||
CompilerSpec compilerSpec = program.getCompilerSpec();
|
||||
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;
|
||||
}
|
||||
|
||||
Program program = function.getProgram();
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
SymbolUtilities.validateName(name);
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol sym = symbolTable.getPrimarySymbol(entryPoint);
|
||||
if (sym == null || sym.getName().equals(name)) {
|
||||
if (function.getName().equals(name)) {
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
removeCodeSymbol(symbolTable, entryPoint, name, function.getParentNamespace());
|
||||
sym.setName(name, source);
|
||||
removeCodeSymbol(function.getEntryPoint(), name, function.getParentNamespace());
|
||||
function.setName(name, source);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
// unexpected
|
||||
throw new InvalidInputException(
|
||||
"Function name conflict occurred when applying function signature.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -361,13 +374,11 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
|
|||
return getUniqueName(symbolTable, function, name);
|
||||
}
|
||||
|
||||
private static void removeCodeSymbol(SymbolTable symbolTable, Address address, String name,
|
||||
Namespace namespace) {
|
||||
private void removeCodeSymbol(Address address, String name, Namespace namespace) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol otherSym = symbolTable.getSymbol(name, address, namespace);
|
||||
if (otherSym != null) {
|
||||
if (otherSym.getSymbolType() == SymbolType.LABEL) {
|
||||
otherSym.delete(); // replace label if function name matches
|
||||
}
|
||||
if (otherSym != null && otherSym.getSymbolType() == SymbolType.LABEL) {
|
||||
otherSym.delete(); // remove label so function rename may use it
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -19,6 +19,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||
import ghidra.app.cmd.function.FunctionRenameOption;
|
||||
import ghidra.framework.cmd.Command;
|
||||
import ghidra.framework.cmd.CompoundCmd;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
|
@ -175,7 +176,7 @@ public class EditFunctionSignatureDialog extends AbstractEditFunctionSignatureDi
|
|||
return null;
|
||||
}
|
||||
cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), definition,
|
||||
SourceType.USER_DEFINED, true, true);
|
||||
SourceType.USER_DEFINED, true, FunctionRenameOption.RENAME);
|
||||
}
|
||||
|
||||
CompoundCmd compoundCommand = new CompoundCmd("Update Function Signature");
|
||||
|
|
|
@ -454,7 +454,7 @@ public class DemangledFunction extends DemangledObject {
|
|||
}
|
||||
|
||||
ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(),
|
||||
signature, SourceType.IMPORTED, true, false);
|
||||
signature, SourceType.IMPORTED, true, FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||
cmd.applyTo(program);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -245,7 +245,7 @@ class FunctionsXmlMgr {
|
|||
}
|
||||
|
||||
ApplyFunctionSignatureCmd afsCmd = new ApplyFunctionSignatureCmd(func.getEntryPoint(),
|
||||
funcDef, SourceType.IMPORTED, false, false);
|
||||
funcDef, SourceType.IMPORTED, false, FunctionRenameOption.RENAME_IF_DEFAULT);
|
||||
if (!afsCmd.applyTo(program, monitor)) {
|
||||
// TODO: continue trying to add local vars after failing to update the function signature?
|
||||
log.appendMsg("Failed to update function " + funcDesc(func) + " with signature \"" +
|
||||
|
|
Loading…
Reference in New Issue
Block a user