mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 14:20:11 +08:00
GP-356 refactor of EditFunctionSignatureDialog and the various
extensions.
This commit is contained in:
+72
-112
@@ -18,25 +18,21 @@ package ghidra.app.plugin.core.datamgr.editor;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.ComboBoxModel;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
|
|
||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
import docking.actions.DockingToolActions;
|
import docking.actions.DockingToolActions;
|
||||||
import docking.actions.SharedDockingActionPlaceholder;
|
import docking.actions.SharedDockingActionPlaceholder;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
|
||||||
import docking.widgets.combobox.GhidraComboBox;
|
|
||||||
import docking.widgets.label.GLabel;
|
|
||||||
import ghidra.app.plugin.core.compositeeditor.*;
|
import ghidra.app.plugin.core.compositeeditor.*;
|
||||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||||
import ghidra.app.plugin.core.function.EditFunctionSignatureDialog;
|
import ghidra.app.plugin.core.function.AbstractEditFunctionSignatureDialog;
|
||||||
import ghidra.framework.model.DomainObject;
|
import ghidra.framework.model.DomainObject;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
import ghidra.program.model.data.Enum;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.FunctionSignature;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages program and archive data type editors.
|
* Manages program and archive data type editors.
|
||||||
@@ -238,8 +234,8 @@ public class DataTypeEditorManager
|
|||||||
list.add(editor);
|
list.add(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (EditorProvider element : list) {
|
||||||
dismissEditor(list.get(i));
|
dismissEditor(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,55 +515,10 @@ public class DataTypeEditorManager
|
|||||||
editFunctionSignature(category, functionDefinition);
|
editFunctionSignature(category, functionDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void editFunctionSignature(final Category category,
|
private void editFunctionSignature(Category category, FunctionDefinition functionDefinition) {
|
||||||
final FunctionDefinition functionDefinition) {
|
|
||||||
|
|
||||||
Function function =
|
|
||||||
new UndefinedFunction(plugin.getProgram(), plugin.getProgram().getMinAddress()) {
|
|
||||||
@Override
|
|
||||||
public String getCallingConventionName() {
|
|
||||||
if (functionDefinition == null) {
|
|
||||||
return super.getCallingConventionName();
|
|
||||||
}
|
|
||||||
return functionDefinition.getGenericCallingConvention().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCallingConvention(String name) throws InvalidInputException {
|
|
||||||
// no-op; we handle this in the editor dialog
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setInline(boolean isInline) {
|
|
||||||
// can't edit this from the DataTypeManager
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNoReturn(boolean hasNoReturn) {
|
|
||||||
// can't edit this from the DataTypeManager
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FunctionSignature getSignature() {
|
|
||||||
if (functionDefinition != null) {
|
|
||||||
return functionDefinition;
|
|
||||||
}
|
|
||||||
return super.getSignature();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
if (functionDefinition != null) {
|
|
||||||
return functionDefinition.getName();
|
|
||||||
}
|
|
||||||
return "newFunction";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// DT how do I do the same as the other creates.
|
|
||||||
PluginTool tool = plugin.getTool();
|
PluginTool tool = plugin.getTool();
|
||||||
DTMEditFunctionSignatureDialog editSigDialog = new DTMEditFunctionSignatureDialog(
|
DTMEditFunctionSignatureDialog editSigDialog = new DTMEditFunctionSignatureDialog(
|
||||||
plugin.getTool(), "Edit Function Signature", function, category, functionDefinition);
|
plugin.getTool(), "Edit Function Signature", category, functionDefinition);
|
||||||
editSigDialog.setHelpLocation(
|
editSigDialog.setHelpLocation(
|
||||||
new HelpLocation("DataTypeManagerPlugin", "Function_Definition"));
|
new HelpLocation("DataTypeManagerPlugin", "Function_Definition"));
|
||||||
tool.showDialog(editSigDialog);
|
tool.showDialog(editSigDialog);
|
||||||
@@ -577,64 +528,73 @@ public class DataTypeEditorManager
|
|||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private class DTMEditFunctionSignatureDialog extends EditFunctionSignatureDialog {
|
/**
|
||||||
|
* <code>DTMEditFunctionSignatureDialog</code> provides the ability to edit the
|
||||||
|
* function signature associated with a specific {@link FunctionDefinition}.
|
||||||
|
* Use of this editor requires the presence of the tool-based datatype manager service.
|
||||||
|
*/
|
||||||
|
private class DTMEditFunctionSignatureDialog extends AbstractEditFunctionSignatureDialog {
|
||||||
|
private final FunctionDefinition functionDefinition;
|
||||||
|
private final FunctionSignature oldSignature;
|
||||||
private final Category category;
|
private final Category category;
|
||||||
private final FunctionDefinition functionDefinitionDataType;
|
|
||||||
|
|
||||||
DTMEditFunctionSignatureDialog(PluginTool pluginTool, String title, Function function,
|
DTMEditFunctionSignatureDialog(PluginTool pluginTool, String title, Category category,
|
||||||
Category category, FunctionDefinition functionDefinition) {
|
FunctionDefinition functionDefinition) {
|
||||||
super(pluginTool, title, function);
|
super(pluginTool, title, false, false, false);
|
||||||
|
this.functionDefinition = functionDefinition;
|
||||||
this.category = category;
|
this.category = category;
|
||||||
this.functionDefinitionDataType = functionDefinition;
|
this.oldSignature = buildSignature();
|
||||||
|
|
||||||
if (functionDefinitionDataType != null) {
|
|
||||||
setCallingConvention(
|
|
||||||
functionDefinitionDataType.getGenericCallingConvention().toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FunctionSignature buildSignature() {
|
||||||
|
if (functionDefinition != null) {
|
||||||
|
if (category.getDataTypeManager() != functionDefinition.getDataTypeManager()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"functionDefinition and category must have same Datatypemanager");
|
||||||
|
}
|
||||||
|
return functionDefinition;
|
||||||
|
}
|
||||||
|
return new FunctionDefinitionDataType("newFunction");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installCallingConventionWidget(JPanel parentPanel) {
|
protected String[] getSupportedCallFixupNames() {
|
||||||
callingConventionComboBox = new GhidraComboBox<>();
|
return null; // Call fixup not supported on FunctionDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCallFixupName() {
|
||||||
|
return null; // Call fixup not supported on FunctionDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FunctionSignature getFunctionSignature() {
|
||||||
|
return oldSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPrototypeString() {
|
||||||
|
return getFunctionSignature().getPrototypeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCallingConventionName() {
|
||||||
|
return getFunctionSignature().getGenericCallingConvention().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getCallingConventionNames() {
|
||||||
GenericCallingConvention[] values = GenericCallingConvention.values();
|
GenericCallingConvention[] values = GenericCallingConvention.values();
|
||||||
String[] choices = new String[values.length];
|
List<String> choices = new ArrayList<>();
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (GenericCallingConvention value : values) {
|
||||||
choices[i] = values[i].toString();
|
choices.add(value.toString());
|
||||||
}
|
}
|
||||||
|
return choices;
|
||||||
setCallingConventionChoices(choices);
|
|
||||||
parentPanel.add(new GLabel("Calling Convention:"));
|
|
||||||
parentPanel.add(callingConventionComboBox);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installInlineWidget(JPanel parentPanel) {
|
protected DataTypeManager getDataTypeManager() {
|
||||||
inlineCheckBox = new GCheckBox("Inline");
|
return category.getDataTypeManager();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void installNoReturnWidget(JPanel parentPanel) {
|
|
||||||
noReturnCheckBox = new GCheckBox("No Return");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void installCallFixupWidget(JPanel parentPanel) {
|
|
||||||
// don't add this panel
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setCallingConvention(String callingConvention) {
|
|
||||||
ComboBoxModel<?> model = callingConventionComboBox.getModel();
|
|
||||||
int size = model.getSize();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
Object item = model.getElementAt(i);
|
|
||||||
if (item.equals(callingConvention)) {
|
|
||||||
callingConventionComboBox.setSelectedItem(callingConvention);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callingConventionComboBox.setSelectedItem(GenericCallingConvention.unknown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -657,9 +617,9 @@ public class DataTypeEditorManager
|
|||||||
GenericCallingConvention.getGenericCallingConvention(getCallingConvention());
|
GenericCallingConvention.getGenericCallingConvention(getCallingConvention());
|
||||||
newDefinition.setGenericCallingConvention(callingConvention);
|
newDefinition.setGenericCallingConvention(callingConvention);
|
||||||
|
|
||||||
DataTypeManager manager = category.getDataTypeManager();
|
DataTypeManager manager = getDataTypeManager();
|
||||||
SourceArchive sourceArchive = manager.getLocalSourceArchive();
|
SourceArchive sourceArchive = manager.getLocalSourceArchive();
|
||||||
if (functionDefinitionDataType == null) {
|
if (functionDefinition == null) {
|
||||||
newDefinition.setSourceArchive(sourceArchive);
|
newDefinition.setSourceArchive(sourceArchive);
|
||||||
newDefinition.setCategoryPath(category.getCategoryPath());
|
newDefinition.setCategoryPath(category.getCategoryPath());
|
||||||
int id = manager.startTransaction("Create Function Definition");
|
int id = manager.startTransaction("Create Function Definition");
|
||||||
@@ -669,14 +629,14 @@ public class DataTypeEditorManager
|
|||||||
else {
|
else {
|
||||||
int id = manager.startTransaction("Edit Function Definition");
|
int id = manager.startTransaction("Edit Function Definition");
|
||||||
try {
|
try {
|
||||||
if (!functionDefinitionDataType.getName().equals(newDefinition.getName())) {
|
if (!functionDefinition.getName().equals(newDefinition.getName())) {
|
||||||
functionDefinitionDataType.setName(newDefinition.getName());
|
functionDefinition.setName(newDefinition.getName());
|
||||||
}
|
}
|
||||||
functionDefinitionDataType.setArguments(newDefinition.getArguments());
|
functionDefinition.setArguments(newDefinition.getArguments());
|
||||||
functionDefinitionDataType.setGenericCallingConvention(
|
functionDefinition.setGenericCallingConvention(
|
||||||
newDefinition.getGenericCallingConvention());
|
newDefinition.getGenericCallingConvention());
|
||||||
functionDefinitionDataType.setReturnType(newDefinition.getReturnType());
|
functionDefinition.setReturnType(newDefinition.getReturnType());
|
||||||
functionDefinitionDataType.setVarArgs(newDefinition.hasVarArgs());
|
functionDefinition.setVarArgs(newDefinition.hasVarArgs());
|
||||||
}
|
}
|
||||||
catch (InvalidNameException | DuplicateNameException e) {
|
catch (InvalidNameException | DuplicateNameException e) {
|
||||||
// not sure why we are squashing this? ...assuming this can't happen
|
// not sure why we are squashing this? ...assuming this can't happen
|
||||||
|
|||||||
+435
@@ -0,0 +1,435 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.plugin.core.function;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import docking.DialogComponentProvider;
|
||||||
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
|
import docking.widgets.combobox.GhidraComboBox;
|
||||||
|
import docking.widgets.label.GDLabel;
|
||||||
|
import docking.widgets.label.GLabel;
|
||||||
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
|
import ghidra.app.util.cparser.C.ParseException;
|
||||||
|
import ghidra.app.util.parser.FunctionSignatureParser;
|
||||||
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
|
import ghidra.program.model.data.FunctionDefinitionDataType;
|
||||||
|
import ghidra.program.model.listing.FunctionSignature;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>EditFunctionSignatureDialog</code> provides an abstract implementation
|
||||||
|
* a function signature editor. Use of this editor requires the presence of the tool-based
|
||||||
|
* datatype manager service.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractEditFunctionSignatureDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
|
private static final String NONE_CHOICE = "-NONE-";
|
||||||
|
private static int SIGNATURE_COLUMNS = 60;
|
||||||
|
|
||||||
|
protected JLabel signatureLabel;
|
||||||
|
protected JTextField signatureField;
|
||||||
|
protected JComboBox<String> callingConventionComboBox;
|
||||||
|
protected JComboBox<String> callFixupComboBox;
|
||||||
|
protected JCheckBox inlineCheckBox;
|
||||||
|
protected JCheckBox noReturnCheckBox;
|
||||||
|
|
||||||
|
protected boolean allowInLine;
|
||||||
|
protected boolean allowNoReturn;
|
||||||
|
protected boolean allowCallFixup;
|
||||||
|
|
||||||
|
protected PluginTool tool;
|
||||||
|
|
||||||
|
// Due to delayed initialization and tests not actually displaying dialog
|
||||||
|
// we will track function info initialization
|
||||||
|
boolean initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract function signature editor
|
||||||
|
*
|
||||||
|
* @param tool A reference to the active tool.
|
||||||
|
* @param title The title of the dialog.
|
||||||
|
* @param allowInLine true if in-line attribute control should be included
|
||||||
|
* @param allowNoReturn true if no-return attribute control should be added
|
||||||
|
* @param allowCallFixup true if call-fixup choice should be added
|
||||||
|
*/
|
||||||
|
public AbstractEditFunctionSignatureDialog(PluginTool tool, String title, boolean allowInLine,
|
||||||
|
boolean allowNoReturn, boolean allowCallFixup) {
|
||||||
|
|
||||||
|
super(title, true, true, true, false);
|
||||||
|
this.tool = tool;
|
||||||
|
this.allowInLine = allowInLine;
|
||||||
|
this.allowNoReturn = allowNoReturn;
|
||||||
|
this.allowCallFixup = allowCallFixup;
|
||||||
|
|
||||||
|
addWorkPanel(buildMainPanel());
|
||||||
|
addOKButton();
|
||||||
|
addCancelButton();
|
||||||
|
setDefaultButton(okButton);
|
||||||
|
setRememberSize(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getComponent() {
|
||||||
|
setFunctionInfo(); //delay update for after construction
|
||||||
|
return super.getComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DataTypeManager associated with function or function definition
|
||||||
|
*/
|
||||||
|
protected abstract DataTypeManager getDataTypeManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return optional initial function signature which can assist parse with
|
||||||
|
* identifying referenced datatypes within signature
|
||||||
|
*/
|
||||||
|
protected abstract FunctionSignature getFunctionSignature();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the initial signature string for the dialog
|
||||||
|
*/
|
||||||
|
protected abstract String getPrototypeString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return initial calling convention name
|
||||||
|
*/
|
||||||
|
protected abstract String getCallingConventionName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list of acceptable calling convention names
|
||||||
|
*/
|
||||||
|
protected abstract List<String> getCallingConventionNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return initial in-line attribute value
|
||||||
|
*/
|
||||||
|
protected boolean isInline() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return initial no-return attribute value
|
||||||
|
*/
|
||||||
|
protected boolean hasNoReturn() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return initial call-fixup name or null if n/a
|
||||||
|
*/
|
||||||
|
protected abstract String getCallFixupName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array of allowed call fixup names or null
|
||||||
|
*/
|
||||||
|
protected abstract String[] getSupportedCallFixupNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method must be invoked following construction to fetch function info
|
||||||
|
* and update components.
|
||||||
|
*/
|
||||||
|
private void setFunctionInfo() {
|
||||||
|
if (initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
signatureField.setText(getPrototypeString());
|
||||||
|
setCallingConventionChoices();
|
||||||
|
callingConventionComboBox.setSelectedItem(getCallingConventionName());
|
||||||
|
if (allowInLine) {
|
||||||
|
inlineCheckBox.setSelected(isInline());
|
||||||
|
}
|
||||||
|
if (allowNoReturn) {
|
||||||
|
noReturnCheckBox.setSelected(hasNoReturn());
|
||||||
|
}
|
||||||
|
if (allowCallFixup) {
|
||||||
|
setCallFixupChoices();
|
||||||
|
|
||||||
|
String callFixupName = getCallFixupName();
|
||||||
|
if (callFixupName != null) {
|
||||||
|
callFixupComboBox.setSelectedItem(callFixupName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel buildMainPanel() {
|
||||||
|
JPanel mainPanel = new JPanel();
|
||||||
|
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
||||||
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 2));
|
||||||
|
mainPanel.add(buildSignaturePanel());
|
||||||
|
mainPanel.add(buildAttributePanel());
|
||||||
|
if (allowCallFixup) {
|
||||||
|
installCallFixupWidget(mainPanel);
|
||||||
|
}
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installCallFixupWidget(JPanel parentPanel) {
|
||||||
|
JPanel callFixupPanel = buildCallFixupPanel();
|
||||||
|
parentPanel.add(callFixupPanel != null ? callFixupPanel : buildSpacerPanel());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel buildSignaturePanel() {
|
||||||
|
JPanel signaturePanel = new JPanel();
|
||||||
|
signaturePanel.setLayout(new BoxLayout(signaturePanel, BoxLayout.X_AXIS));
|
||||||
|
|
||||||
|
signatureField = new JTextField(SIGNATURE_COLUMNS);
|
||||||
|
signatureLabel = new GDLabel("Signature:");
|
||||||
|
signaturePanel.add(signatureLabel);
|
||||||
|
signaturePanel.add(signatureField);
|
||||||
|
|
||||||
|
signaturePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
|
||||||
|
return signaturePanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component buildSpacerPanel() {
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
|
||||||
|
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
||||||
|
panel.add(Box.createVerticalStrut(20));
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel buildAttributePanel() {
|
||||||
|
JPanel attributePanel = new JPanel();
|
||||||
|
attributePanel.setLayout(new BoxLayout(attributePanel, BoxLayout.X_AXIS));
|
||||||
|
attributePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
|
||||||
|
installCallingConventionWidget(attributePanel);
|
||||||
|
if (allowInLine) {
|
||||||
|
installInlineWidget(attributePanel);
|
||||||
|
}
|
||||||
|
if (allowNoReturn) {
|
||||||
|
installNoReturnWidget(attributePanel);
|
||||||
|
}
|
||||||
|
attributePanel.add(Box.createGlue());
|
||||||
|
|
||||||
|
return attributePanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installCallingConventionWidget(JPanel parentPanel) {
|
||||||
|
callingConventionComboBox = new GhidraComboBox<>();
|
||||||
|
parentPanel.add(new GLabel("Calling Convention:"));
|
||||||
|
parentPanel.add(callingConventionComboBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installInlineWidget(JPanel parentPanel) {
|
||||||
|
inlineCheckBox = new GCheckBox("Inline");
|
||||||
|
inlineCheckBox.addChangeListener(e -> {
|
||||||
|
if (inlineCheckBox.isSelected() && callFixupComboBox != null) {
|
||||||
|
callFixupComboBox.setSelectedItem(NONE_CHOICE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
parentPanel.add(inlineCheckBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installNoReturnWidget(JPanel parentPanel) {
|
||||||
|
noReturnCheckBox = new GCheckBox("No Return");
|
||||||
|
parentPanel.add(noReturnCheckBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel buildCallFixupPanel() {
|
||||||
|
|
||||||
|
if (allowCallFixup) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
JPanel callFixupPanel = new JPanel();
|
||||||
|
callFixupPanel.setLayout(new BoxLayout(callFixupPanel, BoxLayout.X_AXIS));
|
||||||
|
|
||||||
|
callFixupComboBox = new GhidraComboBox<>();
|
||||||
|
callFixupComboBox.addItemListener(e -> {
|
||||||
|
if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!NONE_CHOICE.equals(e.getItem())) {
|
||||||
|
inlineCheckBox.setSelected(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
callFixupPanel.add(new GLabel("Call-Fixup:"));
|
||||||
|
callFixupPanel.add(callFixupComboBox);
|
||||||
|
|
||||||
|
callFixupPanel.add(Box.createGlue());
|
||||||
|
callFixupPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
|
||||||
|
return callFixupPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return plugin tool for which dialog was constructed
|
||||||
|
*/
|
||||||
|
protected PluginTool getTool() {
|
||||||
|
return tool;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSignature() {
|
||||||
|
return signatureField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCallingConventionChoices() {
|
||||||
|
callingConventionComboBox.removeAllItems();
|
||||||
|
for (String element : getCallingConventionNames()) {
|
||||||
|
callingConventionComboBox.addItem(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return current calling convention selection from dialog
|
||||||
|
*/
|
||||||
|
protected String getCallingConvention() {
|
||||||
|
return (String) callingConventionComboBox.getSelectedItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return current in-line attribute value from dialog
|
||||||
|
*/
|
||||||
|
protected boolean isInlineSelected() {
|
||||||
|
return inlineCheckBox != null ? inlineCheckBox.isSelected() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return current no-return attribute value from dialog
|
||||||
|
*/
|
||||||
|
protected boolean hasNoReturnSelected() {
|
||||||
|
return noReturnCheckBox != null ? noReturnCheckBox.isSelected() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCallFixupChoices() {
|
||||||
|
String[] callFixupNames = getSupportedCallFixupNames();
|
||||||
|
callFixupComboBox.addItem(NONE_CHOICE);
|
||||||
|
if (callFixupNames != null) {
|
||||||
|
for (String element : callFixupNames) {
|
||||||
|
callFixupComboBox.addItem(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return current call fixup selection from dialog or null
|
||||||
|
*/
|
||||||
|
protected String getCallFixupSelection() {
|
||||||
|
if (callFixupComboBox != null) {
|
||||||
|
String callFixup = (String) callFixupComboBox.getSelectedItem();
|
||||||
|
if (callFixup != null && !NONE_CHOICE.equals(callFixup)) {
|
||||||
|
return callFixup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets called when the user clicks on the OK Button. The base
|
||||||
|
* class calls this method. This method will invoke {@link #applyChanges()}
|
||||||
|
* and close dialog if that method returns true. If false is returned, the
|
||||||
|
* {@link #applyChanges()} method should display a status message to indicate
|
||||||
|
* the failure.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void okCallback() {
|
||||||
|
// only close the dialog if the user made valid changes
|
||||||
|
try {
|
||||||
|
if (applyChanges()) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
// ignore - do not close
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cancelCallback() {
|
||||||
|
setStatusText("");
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user initiates changes that need to be applied to the
|
||||||
|
* underlying function or function definition
|
||||||
|
*
|
||||||
|
* @return true if applied successfully, otherwise false which will keep
|
||||||
|
* dialog displayed (a status message should bet set)
|
||||||
|
* @throws CancelledException if operation cancelled by user
|
||||||
|
*/
|
||||||
|
protected abstract boolean applyChanges() throws CancelledException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform parse of current user-specified function signature (see {@link #getSignature()})
|
||||||
|
* and return valid {@link FunctionDefinitionDataType} if parse successful.
|
||||||
|
* @return function definition data type if parse successful, otherwise null
|
||||||
|
* @throws CancelledException if function signature entry cancelled
|
||||||
|
*/
|
||||||
|
protected final FunctionDefinitionDataType parseSignature() throws CancelledException {
|
||||||
|
setFunctionInfo(); // needed for testing which never shows dialog
|
||||||
|
FunctionSignatureParser parser = new FunctionSignatureParser(
|
||||||
|
getDataTypeManager(), tool.getService(DataTypeManagerService.class));
|
||||||
|
try {
|
||||||
|
// FIXME: Parser returns FunctionDefinition which only supports GenericCallingConventions
|
||||||
|
return parser.parse(getFunctionSignature(), getSignature());
|
||||||
|
}
|
||||||
|
catch (ParseException e) {
|
||||||
|
setStatusText("Invalid Signature: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if user-specified function signature has been modified from original
|
||||||
|
* @return true if modified signature has been entered, else false
|
||||||
|
*/
|
||||||
|
protected final boolean isSignatureChanged() {
|
||||||
|
return !getSignature().equals(getPrototypeString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if user has changed the selected calling convention from the original
|
||||||
|
* @return true if a change in the selected calling convention has been made
|
||||||
|
*/
|
||||||
|
protected final boolean isCallingConventionChanged() {
|
||||||
|
String current = getCallingConventionName();
|
||||||
|
if (current == null && this.getCallingConvention() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (current == null && this.getCallingConvention().equals("default")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (current == null && this.getCallingConvention().equals("unknown")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (current == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (current.equals(getCallingConvention())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dialogShown() {
|
||||||
|
signatureField.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
+88
-292
@@ -15,300 +15,122 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.function;
|
package ghidra.app.plugin.core.function;
|
||||||
|
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.event.ItemEvent;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
|
||||||
import docking.widgets.combobox.GhidraComboBox;
|
|
||||||
import docking.widgets.label.GDLabel;
|
|
||||||
import docking.widgets.label.GLabel;
|
|
||||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
|
||||||
import ghidra.app.util.cparser.C.ParseException;
|
|
||||||
import ghidra.app.util.parser.FunctionSignatureParser;
|
|
||||||
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;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.data.FunctionDefinitionDataType;
|
import ghidra.program.model.data.FunctionDefinitionDataType;
|
||||||
import ghidra.program.model.lang.PrototypeModel;
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.FunctionSignature;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>EditFunctionSignatureDialog</code> provides the ability to edit function
|
* <code>EditFunctionSignatureDialog</code> provides the ability to edit the
|
||||||
* signatures. Use of this editor requires the presence of the tool-based
|
* function signature associated with a specific {@link Function}.
|
||||||
* datatype manager service.
|
* Use of this editor requires the presence of the tool-based datatype manager service.
|
||||||
*/
|
*/
|
||||||
public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
public class EditFunctionSignatureDialog extends AbstractEditFunctionSignatureDialog {
|
||||||
|
|
||||||
private static final String NONE_CHOICE = "-NONE-";
|
protected final Function function;
|
||||||
|
protected final String oldFunctionSignature;
|
||||||
protected JLabel signatureLabel;
|
|
||||||
protected JTextField signatureField;
|
|
||||||
protected JComboBox<String> callingConventionComboBox;
|
|
||||||
protected JComboBox<String> callFixupComboBox;
|
|
||||||
protected JCheckBox inlineCheckBox;
|
|
||||||
protected JCheckBox noReturnCheckBox;
|
|
||||||
|
|
||||||
protected PluginTool tool;
|
|
||||||
protected Function function;
|
|
||||||
protected String oldFunctionName;
|
|
||||||
protected String oldFunctionSignature;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is not meant to be instantiated directly, but rather by
|
* Edit function signature for a specified Function
|
||||||
* subclasses.
|
* @param tool A reference to the active tool.
|
||||||
*
|
|
||||||
* @param plugin A reference to the FunctionPlugin.
|
|
||||||
* @param title The title of the dialog.
|
* @param title The title of the dialog.
|
||||||
* @param function the function which is having its signature edited.
|
* @param function the function which is having its signature edited.
|
||||||
*/
|
*/
|
||||||
public EditFunctionSignatureDialog(PluginTool tool, String title, final Function function) {
|
public EditFunctionSignatureDialog(PluginTool tool, String title, final Function function) {
|
||||||
|
super(tool, title, allowInLine(function), true, allowCallFixup(function));
|
||||||
super(title, true, true, true, false);
|
|
||||||
this.tool = tool;
|
|
||||||
this.function = function;
|
this.function = function;
|
||||||
this.oldFunctionName = function.getName();
|
|
||||||
this.oldFunctionSignature = function.getSignature().getPrototypeString();
|
this.oldFunctionSignature = function.getSignature().getPrototypeString();
|
||||||
|
|
||||||
addWorkPanel(buildMainPanel());
|
|
||||||
addOKButton();
|
|
||||||
addCancelButton();
|
|
||||||
setDefaultButton(okButton);
|
|
||||||
setFunctionInfo();
|
|
||||||
setRememberSize(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setFunctionInfo() {
|
protected EditFunctionSignatureDialog(PluginTool tool, String title, final Function function,
|
||||||
setSignature(function.getSignature().getPrototypeString());
|
boolean allowInLine, boolean allowNoReturn, boolean allowCallFixup) {
|
||||||
setCallingConvention(function.getCallingConventionName());
|
super(tool, title, allowInLine, allowNoReturn, allowCallFixup);
|
||||||
setInlineSelected(function.isInline());
|
this.function = function;
|
||||||
inlineCheckBox.setEnabled(!getAffectiveFunction(function).isExternal());
|
this.oldFunctionSignature = function.getSignature().getPrototypeString();
|
||||||
setNoReturnSelected(function.hasNoReturn());
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FunctionSignature getFunctionSignature() {
|
||||||
|
return function.getSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPrototypeString() {
|
||||||
|
return oldFunctionSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCallingConventionName() {
|
||||||
|
return function.getCallingConventionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getCallingConventionNames() {
|
||||||
|
return function.getProgram().getFunctionManager().getCallingConventionNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isInline() {
|
||||||
|
return function.isInline();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasNoReturn() {
|
||||||
|
return function.hasNoReturn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCallFixupName() {
|
||||||
|
return function.getCallFixup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] getCallFixupNames(Function function) {
|
||||||
|
String[] callFixupNames =
|
||||||
|
function.getProgram().getCompilerSpec().getPcodeInjectLibrary().getCallFixupNames();
|
||||||
|
if (callFixupNames.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return callFixupNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getSupportedCallFixupNames() {
|
||||||
|
return getCallFixupNames(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DataTypeManager getDataTypeManager() {
|
||||||
|
return function.getProgram().getDataTypeManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the effective function to which changes will be made. This
|
* Get the effective function to which changes will be made. This
|
||||||
* will be the same as function unless it is a thunk in which case
|
* will be the same as function unless it is a thunk in which case
|
||||||
* the returned function will be the ultimate non-thunk function.
|
* the returned function will be the ultimate non-thunk function.
|
||||||
* @param f
|
* @param f function
|
||||||
* @return non-thunk function
|
* @return non-thunk function
|
||||||
*/
|
*/
|
||||||
protected Function getAffectiveFunction(Function f) {
|
private static Function getEffectiveFunction(Function f) {
|
||||||
return f.isThunk() ? f.getThunkedFunction(true) : f;
|
return f.isThunk() ? f.getThunkedFunction(true) : f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buildMainPanel() {
|
private static boolean allowInLine(Function function) {
|
||||||
JPanel mainPanel = new JPanel();
|
return !getEffectiveFunction(function).isExternal();
|
||||||
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
|
||||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 2));
|
|
||||||
mainPanel.add(buildSignaturePanel());
|
|
||||||
mainPanel.add(buildAttributePanel());
|
|
||||||
|
|
||||||
installCallFixupWidget(mainPanel);
|
|
||||||
|
|
||||||
return mainPanel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void installCallFixupWidget(JPanel parentPanel) {
|
private static boolean allowCallFixup(Function function) {
|
||||||
JPanel callFixupPanel = buildCallFixupPanel();
|
return getCallFixupNames(function) != null;
|
||||||
parentPanel.add(callFixupPanel != null ? callFixupPanel : buildSpacerPanel());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JPanel buildSignaturePanel() {
|
|
||||||
JPanel signaturePanel = new JPanel();
|
|
||||||
signaturePanel.setLayout(new BoxLayout(signaturePanel, BoxLayout.X_AXIS));
|
|
||||||
|
|
||||||
String signature = function.getPrototypeString(false, false);
|
|
||||||
signatureField = new JTextField(signature.length()); // add some extra room to edit
|
|
||||||
signatureField.setText(signature);
|
|
||||||
signatureLabel = new GDLabel("Signature:");
|
|
||||||
signaturePanel.add(signatureLabel);
|
|
||||||
signaturePanel.add(signatureField);
|
|
||||||
|
|
||||||
signaturePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
|
||||||
|
|
||||||
return signaturePanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component buildSpacerPanel() {
|
|
||||||
JPanel panel = new JPanel();
|
|
||||||
|
|
||||||
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
|
||||||
panel.add(Box.createVerticalStrut(20));
|
|
||||||
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JPanel buildAttributePanel() {
|
|
||||||
JPanel attributePanel = new JPanel();
|
|
||||||
attributePanel.setLayout(new BoxLayout(attributePanel, BoxLayout.X_AXIS));
|
|
||||||
attributePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
|
||||||
|
|
||||||
installCallingConventionWidget(attributePanel);
|
|
||||||
installInlineWidget(attributePanel);
|
|
||||||
installNoReturnWidget(attributePanel);
|
|
||||||
attributePanel.add(Box.createGlue());
|
|
||||||
|
|
||||||
return attributePanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void installCallingConventionWidget(JPanel parentPanel) {
|
|
||||||
callingConventionComboBox = new GhidraComboBox<>();
|
|
||||||
List<String> callingConventions =
|
|
||||||
function.getProgram().getFunctionManager().getCallingConventionNames();
|
|
||||||
String[] choices = callingConventions.toArray(new String[callingConventions.size()]);
|
|
||||||
setCallingConventionChoices(choices);
|
|
||||||
parentPanel.add(new GLabel("Calling Convention:"));
|
|
||||||
parentPanel.add(callingConventionComboBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void installInlineWidget(JPanel parentPanel) {
|
|
||||||
inlineCheckBox = new GCheckBox("Inline");
|
|
||||||
inlineCheckBox.addChangeListener(e -> {
|
|
||||||
if (inlineCheckBox.isSelected() && callFixupComboBox != null) {
|
|
||||||
callFixupComboBox.setSelectedItem(NONE_CHOICE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parentPanel.add(inlineCheckBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void installNoReturnWidget(JPanel parentPanel) {
|
|
||||||
noReturnCheckBox = new GCheckBox("No Return");
|
|
||||||
parentPanel.add(noReturnCheckBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JPanel buildCallFixupPanel() {
|
|
||||||
|
|
||||||
String[] callFixupNames =
|
|
||||||
function.getProgram().getCompilerSpec().getPcodeInjectLibrary().getCallFixupNames();
|
|
||||||
if (callFixupNames.length == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
JPanel callFixupPanel = new JPanel();
|
|
||||||
callFixupPanel.setLayout(new BoxLayout(callFixupPanel, BoxLayout.X_AXIS));
|
|
||||||
|
|
||||||
callFixupComboBox = new GhidraComboBox<>();
|
|
||||||
callFixupComboBox.addItem(NONE_CHOICE);
|
|
||||||
for (String element : callFixupNames) {
|
|
||||||
callFixupComboBox.addItem(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
callFixupComboBox.addItemListener(e -> {
|
|
||||||
if (e.getStateChange() == ItemEvent.DESELECTED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!NONE_CHOICE.equals(e.getItem())) {
|
|
||||||
inlineCheckBox.setSelected(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
String callFixupName = function.getCallFixup();
|
|
||||||
if (callFixupName != null) {
|
|
||||||
callFixupComboBox.setSelectedItem(callFixupName);
|
|
||||||
}
|
|
||||||
|
|
||||||
callFixupPanel.add(new GLabel("Call-Fixup:"));
|
|
||||||
callFixupPanel.add(callFixupComboBox);
|
|
||||||
|
|
||||||
callFixupPanel.add(Box.createGlue());
|
|
||||||
callFixupPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
|
||||||
|
|
||||||
return callFixupPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PluginTool getTool() {
|
|
||||||
return tool;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Program getProgram() {
|
|
||||||
return function.getProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Function getFunction() {
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignature() {
|
|
||||||
return signatureField.getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setSignature(String signature) {
|
|
||||||
signatureField.setText(signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setCallingConventionChoices(String[] callingConventions) {
|
|
||||||
callingConventionComboBox.removeAllItems();
|
|
||||||
for (String element : callingConventions) {
|
|
||||||
callingConventionComboBox.addItem(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getCallingConvention() {
|
|
||||||
return (String) callingConventionComboBox.getSelectedItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setCallingConvention(String callingConvention) {
|
|
||||||
callingConventionComboBox.setSelectedItem(callingConvention);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isInlineSelected() {
|
|
||||||
return inlineCheckBox.isSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setInlineSelected(boolean selected) {
|
|
||||||
inlineCheckBox.setSelected(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean hasNoReturnSelected() {
|
|
||||||
return noReturnCheckBox.isSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setNoReturnSelected(boolean selected) {
|
|
||||||
noReturnCheckBox.setSelected(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getCallFixupSelection() {
|
|
||||||
if (callFixupComboBox != null) {
|
|
||||||
String callFixup = (String) callFixupComboBox.getSelectedItem();
|
|
||||||
if (callFixup != null && !NONE_CHOICE.equals(callFixup)) {
|
|
||||||
return callFixup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method gets called when the user clicks on the OK Button. The base
|
|
||||||
* class calls this method.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void okCallback() {
|
|
||||||
// only close the dialog if the user made valid changes
|
|
||||||
try {
|
|
||||||
if (applyChanges()) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (CancelledException e) {
|
|
||||||
// ignore - do not close
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void cancelCallback() {
|
|
||||||
setStatusText("");
|
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,6 +140,7 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
* @return true if the command was successfully created.
|
* @return true if the command was successfully created.
|
||||||
* @throws CancelledException if operation cancelled by user
|
* @throws CancelledException if operation cancelled by user
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected boolean applyChanges() throws CancelledException {
|
protected boolean applyChanges() throws CancelledException {
|
||||||
// create the command
|
// create the command
|
||||||
Command command = createCommand();
|
Command command = createCommand();
|
||||||
@@ -327,7 +150,7 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
if (!getTool().execute(command, getProgram())) {
|
if (!getTool().execute(command, function.getProgram())) {
|
||||||
setStatusText(command.getStatusMsg());
|
setStatusText(command.getStatusMsg());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -336,25 +159,16 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FunctionDefinitionDataType parseSignature() throws CancelledException {
|
|
||||||
FunctionSignatureParser parser = new FunctionSignatureParser(
|
|
||||||
getProgram().getDataTypeManager(), tool.getService(DataTypeManagerService.class));
|
|
||||||
try {
|
|
||||||
return parser.parse(getFunction().getSignature(), getSignature());
|
|
||||||
}
|
|
||||||
catch (ParseException e) {
|
|
||||||
setStatusText("Invalid Signature: " + e.getMessage());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Command createCommand() throws CancelledException {
|
private Command createCommand() throws CancelledException {
|
||||||
|
|
||||||
Command cmd = null;
|
Command cmd = null;
|
||||||
if (!getSignature().equals(this.oldFunctionSignature) || !isSameCallingConvention() ||
|
if (isSignatureChanged() || isCallingConventionChanged() ||
|
||||||
(function.getSignatureSource() == SourceType.DEFAULT)) {
|
(function.getSignatureSource() == SourceType.DEFAULT)) {
|
||||||
|
|
||||||
FunctionDefinitionDataType definition = parseSignature();
|
FunctionDefinitionDataType definition = parseSignature();
|
||||||
|
if (definition == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), definition,
|
cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(), definition,
|
||||||
SourceType.USER_DEFINED, true, true);
|
SourceType.USER_DEFINED, true, true);
|
||||||
}
|
}
|
||||||
@@ -394,6 +208,7 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
return errMsg;
|
return errMsg;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (allowInLine) {
|
||||||
compoundCommand.add(new Command() {
|
compoundCommand.add(new Command() {
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(DomainObject obj) {
|
||||||
@@ -411,6 +226,8 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (allowNoReturn) {
|
||||||
compoundCommand.add(new Command() {
|
compoundCommand.add(new Command() {
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(DomainObject obj) {
|
||||||
@@ -428,6 +245,8 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (allowCallFixup) {
|
||||||
compoundCommand.add(new Command() {
|
compoundCommand.add(new Command() {
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj) {
|
public boolean applyTo(DomainObject obj) {
|
||||||
@@ -445,34 +264,11 @@ public class EditFunctionSignatureDialog extends DialogComponentProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
if (cmd != null) {
|
if (cmd != null) {
|
||||||
compoundCommand.add(cmd);
|
compoundCommand.add(cmd);
|
||||||
}
|
}
|
||||||
return compoundCommand;
|
return compoundCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSameCallingConvention() {
|
|
||||||
PrototypeModel conv = function.getCallingConvention();
|
|
||||||
if (conv == null && this.getCallingConvention() == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (conv == null && this.getCallingConvention().equals("default")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (conv == null && this.getCallingConvention().equals("unknown")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (conv == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (conv.getName().equals(this.getCallingConvention())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void dialogShown() {
|
|
||||||
signatureField.selectAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ public class FunctionDataTypeHTMLRepresentation extends HTMLDataTypeRepresentati
|
|||||||
GenericCallingConvention genericCallingConvention =
|
GenericCallingConvention genericCallingConvention =
|
||||||
functionDefinition.getGenericCallingConvention();
|
functionDefinition.getGenericCallingConvention();
|
||||||
String modifier = genericCallingConvention != GenericCallingConvention.unknown
|
String modifier = genericCallingConvention != GenericCallingConvention.unknown
|
||||||
? (" " + genericCallingConvention.name())
|
? (" " + genericCallingConvention.getDeclarationName())
|
||||||
: "";
|
: "";
|
||||||
return new TextLine(
|
return new TextLine(
|
||||||
HTMLUtilities.friendlyEncodeHTML(returnDataType.getDisplayName()) + modifier);
|
HTMLUtilities.friendlyEncodeHTML(returnDataType.getDisplayName()) + modifier);
|
||||||
|
|||||||
+5
-7
@@ -50,7 +50,7 @@ import ghidra.app.plugin.core.datamgr.actions.CreateTypeDefDialog;
|
|||||||
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||||
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
|
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
|
||||||
import ghidra.app.plugin.core.datamgr.tree.*;
|
import ghidra.app.plugin.core.datamgr.tree.*;
|
||||||
import ghidra.app.plugin.core.function.EditFunctionSignatureDialog;
|
import ghidra.app.plugin.core.function.AbstractEditFunctionSignatureDialog;
|
||||||
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||||
@@ -695,11 +695,9 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
DataType dt = iter.next();
|
DataType dt = iter.next();
|
||||||
listTwo.add(dt);
|
listTwo.add(dt);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < listOne.size(); i++) {
|
for (DataType dt : listOne) {
|
||||||
DataType dt = listOne.get(i);
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int j = 0; j < listTwo.size(); j++) {
|
for (DataType dt2 : listTwo) {
|
||||||
DataType dt2 = listTwo.get(j);
|
|
||||||
if (dt.isEquivalent(dt2)) {
|
if (dt.isEquivalent(dt2)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -807,8 +805,8 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
assertTrue(action.isEnabledForContext(treeContext));
|
assertTrue(action.isEnabledForContext(treeContext));
|
||||||
performAction(action, treeContext, false);
|
performAction(action, treeContext, false);
|
||||||
|
|
||||||
EditFunctionSignatureDialog dialog =
|
AbstractEditFunctionSignatureDialog dialog =
|
||||||
waitForDialogComponent(EditFunctionSignatureDialog.class);
|
waitForDialogComponent(AbstractEditFunctionSignatureDialog.class);
|
||||||
|
|
||||||
JTextField textField = (JTextField) getInstanceField("signatureField", dialog);
|
JTextField textField = (JTextField) getInstanceField("signatureField", dialog);
|
||||||
setText(textField, newSignature);
|
setText(textField, newSignature);
|
||||||
|
|||||||
+127
-65
@@ -29,59 +29,12 @@ import ghidra.program.model.data.*;
|
|||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.*;
|
import ghidra.program.model.pcode.*;
|
||||||
import ghidra.program.model.symbol.Reference;
|
import ghidra.program.model.symbol.Reference;
|
||||||
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
public class OverridePrototypeAction extends AbstractDecompilerAction {
|
public class OverridePrototypeAction extends AbstractDecompilerAction {
|
||||||
|
|
||||||
public class ProtoOverrideDialog extends EditFunctionSignatureDialog {
|
|
||||||
private FunctionDefinition functionDefinition;
|
|
||||||
|
|
||||||
public FunctionDefinition getFunctionDefinition() {
|
|
||||||
return functionDefinition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProtoOverrideDialog(PluginTool tool, Function func, String signature, String conv) {
|
|
||||||
super(tool, "Override Signature", func);
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.DECOMPILER, "ActionOverrideSignature"));
|
|
||||||
setSignature(signature);
|
|
||||||
setCallingConvention(conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method gets called when the user clicks on the OK Button. The base
|
|
||||||
* class calls this method.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void okCallback() {
|
|
||||||
// only close the dialog if the user made valid changes
|
|
||||||
if (parseFunctionDefinition()) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean parseFunctionDefinition() {
|
|
||||||
|
|
||||||
functionDefinition = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
functionDefinition = parseSignature();
|
|
||||||
}
|
|
||||||
catch (CancelledException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionDefinition == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericCallingConvention convention =
|
|
||||||
GenericCallingConvention.guessFromName(getCallingConvention());
|
|
||||||
functionDefinition.setGenericCallingConvention(convention);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public OverridePrototypeAction() {
|
public OverridePrototypeAction() {
|
||||||
super("Override Signature");
|
super("Override Signature");
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.DECOMPILER, "ActionOverrideSignature"));
|
setHelpLocation(new HelpLocation(HelpTopics.DECOMPILER, "ActionOverrideSignature"));
|
||||||
@@ -183,11 +136,30 @@ public class OverridePrototypeAction extends AbstractDecompilerAction {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateSignature(PcodeOp op, String name) {
|
private String generateSignature(PcodeOp op, String name, Function calledfunc) {
|
||||||
|
|
||||||
|
// TODO: If an override has already be placed-down it should probably be used
|
||||||
|
// for the initial signature. HighFunction does not make it easy to grab
|
||||||
|
// existing override prototype
|
||||||
|
|
||||||
|
if (calledfunc != null) {
|
||||||
|
SourceType signatureSource = calledfunc.getSignatureSource();
|
||||||
|
if (signatureSource == SourceType.DEFAULT || signatureSource == SourceType.ANALYSIS) {
|
||||||
|
calledfunc = null; // ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
|
||||||
Varnode vn = op.getOutput();
|
Varnode vn = op.getOutput();
|
||||||
DataType dt = null;
|
DataType dt = null;
|
||||||
if (vn != null) {
|
if (calledfunc != null) {
|
||||||
|
dt = calledfunc.getReturnType();
|
||||||
|
if (Undefined.isUndefined(dt)) {
|
||||||
|
dt = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dt == null && vn != null) {
|
||||||
dt = vn.getHigh().getDataType();
|
dt = vn.getHigh().getDataType();
|
||||||
}
|
}
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
@@ -198,24 +170,46 @@ public class OverridePrototypeAction extends AbstractDecompilerAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.append(' ').append(name).append('(');
|
buf.append(' ').append(name).append('(');
|
||||||
for (int i = 1; i < op.getNumInputs(); ++i) {
|
|
||||||
vn = op.getInput(i);
|
int index = 1;
|
||||||
dt = null;
|
if (calledfunc != null) {
|
||||||
|
for (Parameter p : calledfunc.getParameters()) {
|
||||||
|
String dtName = getInputDataTypeName(op, index, p.getDataType());
|
||||||
|
if (index++ != 1) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
buf.append(dtName);
|
||||||
|
if (p.getSource() != SourceType.DEFAULT) {
|
||||||
|
buf.append(' ');
|
||||||
|
buf.append(p.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = index; i < op.getNumInputs(); ++i) {
|
||||||
|
if (i != 1) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
buf.append(getInputDataTypeName(op, i, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.append(')');
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getInputDataTypeName(PcodeOp op, int inIndex, DataType preferredDt) {
|
||||||
|
if (preferredDt != null && !Undefined.isUndefined(preferredDt)) {
|
||||||
|
return preferredDt.getDisplayName();
|
||||||
|
}
|
||||||
|
Varnode vn = op.getInput(inIndex);
|
||||||
|
DataType dt = null;
|
||||||
if (vn != null) {
|
if (vn != null) {
|
||||||
dt = vn.getHigh().getDataType();
|
dt = vn.getHigh().getDataType();
|
||||||
}
|
}
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
buf.append(dt.getDisplayName());
|
return dt.getDisplayName();
|
||||||
}
|
}
|
||||||
else {
|
return "BAD";
|
||||||
buf.append("BAD");
|
|
||||||
}
|
|
||||||
if (i != op.getNumInputs() - 1) {
|
|
||||||
buf.append(',');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.append(')');
|
|
||||||
return buf.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -257,9 +251,10 @@ public class OverridePrototypeAction extends AbstractDecompilerAction {
|
|||||||
conv = calledfunc.getCallingConventionName();
|
conv = calledfunc.getCallingConventionName();
|
||||||
}
|
}
|
||||||
|
|
||||||
String signature = generateSignature(op, name);
|
String signature = generateSignature(op, name, calledfunc);
|
||||||
PluginTool tool = context.getTool();
|
PluginTool tool = context.getTool();
|
||||||
ProtoOverrideDialog dialog = new ProtoOverrideDialog(tool, func, signature, conv);
|
ProtoOverrideDialog dialog =
|
||||||
|
new ProtoOverrideDialog(tool, calledfunc != null ? calledfunc : func, signature, conv);
|
||||||
tool.showDialog(dialog);
|
tool.showDialog(dialog);
|
||||||
FunctionDefinition fdef = dialog.getFunctionDefinition();
|
FunctionDefinition fdef = dialog.getFunctionDefinition();
|
||||||
if (fdef == null) {
|
if (fdef == null) {
|
||||||
@@ -279,4 +274,71 @@ public class OverridePrototypeAction extends AbstractDecompilerAction {
|
|||||||
program.endTransaction(transaction, commit);
|
program.endTransaction(transaction, commit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>ProtoOverrideDialog</code> provides the ability to edit the
|
||||||
|
* function signature associated with a specific function definition override
|
||||||
|
* at a sub-function callsite.
|
||||||
|
* Use of this editor requires the presence of the tool-based datatype manager service.
|
||||||
|
*/
|
||||||
|
private class ProtoOverrideDialog extends EditFunctionSignatureDialog {
|
||||||
|
private FunctionDefinition functionDefinition;
|
||||||
|
private final String initialSignature;
|
||||||
|
private final String initialConvention;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct signature override for called function
|
||||||
|
* @param tool active tool
|
||||||
|
* @param func function from which program access is achieved and supply of preferred
|
||||||
|
* datatypes when parsing signature
|
||||||
|
* @param signature initial prototype signature to be used
|
||||||
|
* @param conv initial calling convention
|
||||||
|
*/
|
||||||
|
public ProtoOverrideDialog(PluginTool tool, Function func, String signature, String conv) {
|
||||||
|
super(tool, "Override Signature", func, false, false, false);
|
||||||
|
setHelpLocation(new HelpLocation(HelpTopics.DECOMPILER, "ActionOverrideSignature"));
|
||||||
|
this.initialSignature = signature;
|
||||||
|
this.initialConvention = conv;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPrototypeString() {
|
||||||
|
return initialSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCallingConventionName() {
|
||||||
|
return initialConvention;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean applyChanges() throws CancelledException {
|
||||||
|
return parseFunctionDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean parseFunctionDefinition() {
|
||||||
|
|
||||||
|
functionDefinition = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
functionDefinition = parseSignature();
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionDefinition == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericCallingConvention convention =
|
||||||
|
GenericCallingConvention.guessFromName(getCallingConvention());
|
||||||
|
functionDefinition.setGenericCallingConvention(convention);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionDefinition getFunctionDefinition() {
|
||||||
|
return functionDefinition;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user