Isolate variable action

This commit is contained in:
caheckman 2020-01-16 12:25:19 -05:00
parent c0dfa509ee
commit b0fb7b287d
4 changed files with 121 additions and 3 deletions

View file

@ -70,6 +70,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
private DockingAction lockLocalAction;
private DockingAction renameVarAction;
private DockingAction retypeVarAction;
private DockingAction isolateVarAction;
private DockingAction specifyCProtoAction;
private DockingAction overrideSigAction;
private DockingAction deleteSigAction;
@ -778,6 +779,9 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
retypeVarAction = new RetypeVariableAction(tool, controller);
setGroupInfo(retypeVarAction, variableGroup, subGroupPosition++);
isolateVarAction = new IsolateVariableAction(tool, controller);
setGroupInfo(isolateVarAction, variableGroup, subGroupPosition++);
decompilerCreateStructureAction =
new DecompilerStructureVariableAction(owner, tool, controller);
setGroupInfo(decompilerCreateStructureAction, variableGroup, subGroupPosition++);
@ -907,6 +911,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
addLocalAction(removeSecondaryHighlightAction);
addLocalAction(removeAllSecondadryHighlightsAction);
addLocalAction(retypeVarAction);
addLocalAction(isolateVarAction);
addLocalAction(decompilerCreateStructureAction);
tool.addAction(listingCreateStructureAction);
addLocalAction(editDataTypeAction);

View file

@ -0,0 +1,88 @@
/* ###
* 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.decompile.actions;
import docking.action.MenuData;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.component.DecompilerController;
import ghidra.app.decompiler.component.DecompilerPanel;
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Function;
import ghidra.program.model.pcode.*;
import ghidra.util.UndefinedFunction;
public class IsolateVariableAction extends RetypeVariableAction {
public IsolateVariableAction(PluginTool tool, DecompilerController controller) {
super("New Isolated Variable", tool, controller);
setPopupMenuData(new MenuData(new String[] { "New Isolated Variable" }, "Decompile"));
// setKeyBindingData(new KeyBindingData(KeyEvent.VK_L, 0));
}
@Override
protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) {
Function function = controller.getFunction();
if (function instanceof UndefinedFunction) {
return false;
}
DecompilerPanel decompilerPanel = controller.getDecompilerPanel();
ClangToken tokenAtCursor = decompilerPanel.getTokenAtCursor();
if (tokenAtCursor == null) {
return false;
}
HighVariable variable = tokenAtCursor.getHighVariable();
if (!(variable instanceof HighLocal)) {
return false;
}
HighSymbol highSymbol = variable.getSymbol();
if (highSymbol == null) {
return false;
}
if (highSymbol.isIsolated()) {
return false;
}
Varnode vn = tokenAtCursor.getVarnode();
if (vn == null) {
return false;
}
short mergeGroup = vn.getMergeGroup();
boolean mergeSplit = false;
for (Varnode var : variable.getInstances()) {
if (var.getMergeGroup() != mergeGroup) {
mergeSplit = true;
break;
}
}
if (!mergeSplit) {
return false;
}
return true;
}
@Override
protected void decompilerActionPerformed(DecompilerActionContext context) {
DecompilerPanel decompilerPanel = controller.getDecompilerPanel();
final ClangToken tokenAtCursor = decompilerPanel.getTokenAtCursor();
HighVariable variable = tokenAtCursor.getHighVariable();
HighSymbol highSymbol = variable.getSymbol();
highSymbol.setTypeLock(true);
retypeSymbol(highSymbol, tokenAtCursor.getVarnode(), highSymbol.getDataType());
}
}

View file

@ -38,9 +38,15 @@ import ghidra.util.data.DataTypeParser.AllowedDataTypes;
import ghidra.util.exception.*;
public class RetypeVariableAction extends AbstractDecompilerAction {
private final DecompilerController controller;
protected final DecompilerController controller;
private final PluginTool tool;
protected RetypeVariableAction(String name, PluginTool tool, DecompilerController controller) {
super(name);
this.tool = tool;
this.controller = controller;
}
public RetypeVariableAction(PluginTool tool, DecompilerController controller) {
super("Retype Variable");
this.tool = tool;
@ -124,7 +130,7 @@ public class RetypeVariableAction extends AbstractDecompilerAction {
return chooserDialog.getUserChosenDataType();
}
private void retypeSymbol(HighSymbol highSymbol, Varnode exactSpot, DataType dt) {
protected void retypeSymbol(HighSymbol highSymbol, Varnode exactSpot, DataType dt) {
HighFunction hfunction = highSymbol.getHighFunction();
boolean commitRequired = checkFullCommit(highSymbol, hfunction);

View file

@ -262,6 +262,16 @@ public class HighSymbol {
return namelock;
}
/**
* If this returns true, the decompiler will not speculatively merge this with
* other variables.
* Currently, being isolated is equivalent to being typelocked.
* @return true if this will not be merged with other variables
*/
public boolean isIsolated() {
return typelock;
}
/**
* @return true if the symbol's value is considered read-only (by the decompiler)
*/
@ -323,6 +333,9 @@ public class HighSymbol {
if (isVolatile) {
SpecXmlUtils.encodeBooleanAttribute(buf, "volatile", true);
}
if (isIsolated()) {
SpecXmlUtils.encodeBooleanAttribute(buf, "merge", false);
}
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "cat", category);
if (categoryIndex >= 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(buf, "index", categoryIndex);
@ -356,6 +369,12 @@ public class HighSymbol {
if ((namelockstr != null) && (SpecXmlUtils.decodeBoolean(namelockstr))) {
namelock = true;
}
// isolate = false;
// String isolatestr = symel.getAttribute("merge");
// if ((isolatestr != null) && !SpecXmlUtils.decodeBoolean(isolatestr)) {
// isolate = true;
// }
name = symel.getAttribute("name");
categoryIndex = -1;
category = -1;