mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2835 addressing code review comments
This commit is contained in:
parent
88b7734608
commit
74040472fb
9 changed files with 118 additions and 104 deletions
|
@ -113,7 +113,8 @@ public class FindFunctionsRFExampleScript extends GhidraScript {
|
||||||
|
|
||||||
//show the true function starts most similar to one of the false positives
|
//show the true function starts most similar to one of the false positives
|
||||||
if (!falsePositives.isEmpty()) {
|
if (!falsePositives.isEmpty()) {
|
||||||
SimilarStartsFinder finder = new SimilarStartsFinder(currentProgram, best);
|
SimilarStartsFinder finder =
|
||||||
|
new SimilarStartsFinder(currentProgram, currentProgram, best);
|
||||||
List<SimilarStartRowObject> neighbors =
|
List<SimilarStartRowObject> neighbors =
|
||||||
finder.getSimilarFunctionStarts(falsePositives.get(0).getKey(), 10);
|
finder.getSimilarFunctionStarts(falsePositives.get(0).getKey(), 10);
|
||||||
printf("\nClosest function starts to false positive at %s :\n",
|
printf("\nClosest function starts to false positive at %s :\n",
|
||||||
|
|
|
@ -181,8 +181,8 @@
|
||||||
is measured using <b>random forest proximity</b>. Given a potential start <i>p</i> and
|
is measured using <b>random forest proximity</b>. Given a potential start <i>p</i> and
|
||||||
a known start <i>s</i>, the similarity of <i>p</i> and <i>s</i> is the proportion of trees
|
a known start <i>s</i>, the similarity of <i>p</i> and <i>s</i> is the proportion of trees
|
||||||
which end up in the same leaf node when processing <i>p</i> and <i>s</i>. </P>
|
which end up in the same leaf node when processing <i>p</i> and <i>s</i>. </P>
|
||||||
<P> For convenience, the potential start is also displayed as a row in the table. In
|
<P> For convenience, the potential start is displayed in a table with a single row directly
|
||||||
the Address column, its address is surrounded by asterisks.</P>
|
above the similar starts table.</P>
|
||||||
|
|
||||||
<H2><A name="DebugModelTable"></A> Debug Model Table </H2>
|
<H2><A name="DebugModelTable"></A> Debug Model Table </H2>
|
||||||
<P> This table has the same format as the <A href="#FunctionStartTable">Potential Functions Table</A>
|
<P> This table has the same format as the <A href="#FunctionStartTable">Potential Functions Table</A>
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package ghidra.machinelearning.functionfinding;
|
package ghidra.machinelearning.functionfinding;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.LongStream;
|
import java.util.stream.LongStream;
|
||||||
|
@ -35,13 +34,12 @@ import docking.widgets.table.threaded.GThreadedTablePanel;
|
||||||
import docking.widgets.textfield.IntegerTextField;
|
import docking.widgets.textfield.IntegerTextField;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.framework.main.DataTreeDialog;
|
import ghidra.framework.main.DataTreeDialog;
|
||||||
|
import ghidra.framework.model.DomainFile;
|
||||||
import ghidra.framework.preferences.Preferences;
|
import ghidra.framework.preferences.Preferences;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
|
||||||
import ghidra.util.exception.VersionException;
|
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
import ghidra.util.table.SelectionNavigationAction;
|
import ghidra.util.table.SelectionNavigationAction;
|
||||||
import ghidra.util.table.actions.MakeProgramSelectionAction;
|
import ghidra.util.table.actions.MakeProgramSelectionAction;
|
||||||
|
@ -145,7 +143,6 @@ public class FunctionStartRFParamsDialog extends DialogComponentProvider {
|
||||||
private RandomForestTableModel tableModel;
|
private RandomForestTableModel tableModel;
|
||||||
private Program trainingSource;
|
private Program trainingSource;
|
||||||
private FunctionStartRFParams params;
|
private FunctionStartRFParams params;
|
||||||
private Set<Program> openPrograms;
|
|
||||||
private Vector<Long> moduli = new Vector<>(Arrays.asList(new Long[] { 4l, 8l, 16l, 32l }));
|
private Vector<Long> moduli = new Vector<>(Arrays.asList(new Long[] { 4l, 8l, 16l, 32l }));
|
||||||
private GComboBox<Long> modBox;
|
private GComboBox<Long> modBox;
|
||||||
private JButton trainButton;
|
private JButton trainButton;
|
||||||
|
@ -164,7 +161,6 @@ public class FunctionStartRFParamsDialog extends DialogComponentProvider {
|
||||||
true, true);
|
true, true);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
rowObjects = new ArrayList<>();
|
rowObjects = new ArrayList<>();
|
||||||
openPrograms = new HashSet<>();
|
|
||||||
trainingSource = plugin.getCurrentProgram();
|
trainingSource = plugin.getCurrentProgram();
|
||||||
JPanel panel = createPanel();
|
JPanel panel = createPanel();
|
||||||
addWorkPanel(panel);
|
addWorkPanel(panel);
|
||||||
|
@ -487,24 +483,37 @@ public class FunctionStartRFParamsDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchOtherProgram(RandomForestRowObject modelRow) {
|
private void searchOtherProgram(RandomForestRowObject modelRow) {
|
||||||
Program p = selectProgram();
|
DataTreeDialog dtd = new DataTreeDialog(null, "Select Program", DataTreeDialog.OPEN, f -> {
|
||||||
if (p == null) {
|
Class<?> c = f.getDomainObjectClass();
|
||||||
|
return Program.class.isAssignableFrom(c);
|
||||||
|
});
|
||||||
|
dtd.show();
|
||||||
|
DomainFile dFile = dtd.getDomainFile();
|
||||||
|
if (dFile == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ProgramManager pm = plugin.getTool().getService(ProgramManager.class);
|
ProgramManager pm = plugin.getTool().getService(ProgramManager.class);
|
||||||
pm.openProgram(p, ProgramManager.OPEN_VISIBLE);
|
Program p = pm.openProgram(dFile, DomainFile.DEFAULT_VERSION, ProgramManager.OPEN_VISIBLE);
|
||||||
|
if (p == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isProgramCompatible(p)) {
|
||||||
|
Msg.showWarn(this, null, "Incompatible Program", p.getName() +
|
||||||
|
" is not compatible with training source program " + trainingSource.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
searchProgram(p, modelRow);
|
searchProgram(p, modelRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showTestErrors(RandomForestRowObject modelRow) {
|
private void showTestErrors(RandomForestRowObject modelRow) {
|
||||||
FunctionStartTableProvider provider = new FunctionStartTableProvider(plugin, trainingSource,
|
FunctionStartTableProvider provider = new FunctionStartTableProvider(plugin, trainingSource,
|
||||||
modelRow.getTestErrors(), modelRow, true);
|
modelRow.getTestErrors(), modelRow, true);
|
||||||
addGeneralActions(provider);
|
addGeneralActions(provider, trainingSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchProgram(Program prog, RandomForestRowObject modelRow) {
|
private void searchProgram(Program targetProgram, RandomForestRowObject modelRow) {
|
||||||
GetAddressesToClassifyTask getTask =
|
GetAddressesToClassifyTask getTask =
|
||||||
new GetAddressesToClassifyTask(prog, plugin.getMinUndefinedRangeSize());
|
new GetAddressesToClassifyTask(targetProgram, plugin.getMinUndefinedRangeSize());
|
||||||
//don't want to use the dialog's progress bar
|
//don't want to use the dialog's progress bar
|
||||||
TaskLauncher.launchModal("Gathering Addresses To Classify", getTask);
|
TaskLauncher.launchModal("Gathering Addresses To Classify", getTask);
|
||||||
if (getTask.isCancelled()) {
|
if (getTask.isCancelled()) {
|
||||||
|
@ -518,25 +527,25 @@ public class FunctionStartRFParamsDialog extends DialogComponentProvider {
|
||||||
execNonFunc = getTask.getAddressesToClassify();
|
execNonFunc = getTask.getAddressesToClassify();
|
||||||
}
|
}
|
||||||
FunctionStartTableProvider provider =
|
FunctionStartTableProvider provider =
|
||||||
new FunctionStartTableProvider(plugin, prog, execNonFunc, modelRow, false);
|
new FunctionStartTableProvider(plugin, targetProgram, execNonFunc, modelRow, false);
|
||||||
addGeneralActions(provider);
|
addGeneralActions(provider, targetProgram);
|
||||||
DisassembleFunctionStartsAction disassembleAction = null;
|
DisassembleFunctionStartsAction disassembleAction = null;
|
||||||
if (params.isRestrictedByContext()) {
|
if (params.isRestrictedByContext()) {
|
||||||
disassembleAction = new DisassembleAndApplyContextAction(plugin, prog,
|
disassembleAction = new DisassembleAndApplyContextAction(plugin, targetProgram,
|
||||||
provider.getTable(), provider.getTableModel());
|
provider.getTable(), provider.getTableModel());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
disassembleAction = new DisassembleFunctionStartsAction(plugin, prog,
|
disassembleAction = new DisassembleFunctionStartsAction(plugin, targetProgram,
|
||||||
provider.getTable(), provider.getTableModel());
|
provider.getTable(), provider.getTableModel());
|
||||||
}
|
}
|
||||||
plugin.getTool().addLocalAction(provider, disassembleAction);
|
plugin.getTool().addLocalAction(provider, disassembleAction);
|
||||||
CreateFunctionsAction createActions =
|
CreateFunctionsAction createActions = new CreateFunctionsAction(plugin, targetProgram,
|
||||||
new CreateFunctionsAction(plugin, prog, provider.getTable(), provider.getTableModel());
|
provider.getTable(), provider.getTableModel());
|
||||||
plugin.getTool().addLocalAction(provider, createActions);
|
plugin.getTool().addLocalAction(provider, createActions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addGeneralActions(FunctionStartTableProvider provider) {
|
private void addGeneralActions(FunctionStartTableProvider provider, Program targetProgram) {
|
||||||
plugin.addProvider(provider);
|
plugin.addProvider(provider);
|
||||||
DockingAction programSelectAction =
|
DockingAction programSelectAction =
|
||||||
new MakeProgramSelectionAction(plugin, provider.getTable());
|
new MakeProgramSelectionAction(plugin, provider.getTable());
|
||||||
|
@ -545,35 +554,11 @@ public class FunctionStartRFParamsDialog extends DialogComponentProvider {
|
||||||
DockingAction selectNavigationAction =
|
DockingAction selectNavigationAction =
|
||||||
new SelectionNavigationAction(plugin, provider.getTable());
|
new SelectionNavigationAction(plugin, provider.getTable());
|
||||||
plugin.getTool().addLocalAction(provider, selectNavigationAction);
|
plugin.getTool().addLocalAction(provider, selectNavigationAction);
|
||||||
ShowSimilarStartsAction similarStarts = new ShowSimilarStartsAction(plugin,
|
ShowSimilarStartsAction similarStarts = new ShowSimilarStartsAction(plugin, trainingSource,
|
||||||
plugin.getCurrentProgram(), provider.getTable(), provider.getTableModel());
|
targetProgram, provider.getTable(), provider.getTableModel());
|
||||||
plugin.getTool().addLocalAction(provider, similarStarts);
|
plugin.getTool().addLocalAction(provider, similarStarts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Program selectProgram() {
|
|
||||||
DataTreeDialog dtd = new DataTreeDialog(null, "Select Program", DataTreeDialog.OPEN, f -> {
|
|
||||||
Class<?> c = f.getDomainObjectClass();
|
|
||||||
return Program.class.isAssignableFrom(c);
|
|
||||||
});
|
|
||||||
dtd.show();
|
|
||||||
if (dtd.wasCancelled()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Program otherProgram = null;
|
|
||||||
try {
|
|
||||||
otherProgram = (Program) dtd.getDomainFile()
|
|
||||||
.getDomainObject(plugin, true, true, getTaskMonitorComponent());
|
|
||||||
openPrograms.add(otherProgram);
|
|
||||||
}
|
|
||||||
catch (VersionException | CancelledException | IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (isProgramCompatible(otherProgram)) {
|
|
||||||
return otherProgram;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//checks whether otherProgram contains any specified context registers
|
//checks whether otherProgram contains any specified context registers
|
||||||
//at some point might be worth adding more restrictions
|
//at some point might be worth adding more restrictions
|
||||||
private boolean isProgramCompatible(Program otherProgram) {
|
private boolean isProgramCompatible(Program otherProgram) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import ghidra.app.events.ProgramLocationPluginEvent;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.ProgramPlugin;
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.framework.options.OptionsChangeListener;
|
import ghidra.framework.options.OptionsChangeListener;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.framework.plugintool.PluginInfo;
|
import ghidra.framework.plugintool.PluginInfo;
|
||||||
|
@ -43,12 +44,12 @@ import ghidra.util.bean.opteditor.OptionsVetoException;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@PluginInfo(
|
@PluginInfo(
|
||||||
status = PluginStatus.UNSTABLE,
|
status = PluginStatus.RELEASED,
|
||||||
packageName = MiscellaneousPluginPackage.NAME,
|
packageName = MiscellaneousPluginPackage.NAME,
|
||||||
category = PluginCategoryNames.ANALYSIS,
|
category = PluginCategoryNames.ANALYSIS,
|
||||||
shortDescription = "Function Finder",
|
shortDescription = "Function Finder",
|
||||||
description = "Trains a random forest model to find function starts.",
|
description = "Trains a random forest model to find function starts.",
|
||||||
servicesRequired = { GoToService.class},
|
servicesRequired = { GoToService.class, ProgramManager.class},
|
||||||
eventsProduced = { ProgramLocationPluginEvent.class },
|
eventsProduced = { ProgramLocationPluginEvent.class },
|
||||||
eventsConsumed = { ProgramClosedPluginEvent.class}
|
eventsConsumed = { ProgramClosedPluginEvent.class}
|
||||||
)
|
)
|
||||||
|
@ -212,10 +213,6 @@ public class RandomForestFunctionFinderPlugin extends ProgramPlugin
|
||||||
if (paramsDialog == null) {
|
if (paramsDialog == null) {
|
||||||
paramsDialog = new FunctionStartRFParamsDialog(this);
|
paramsDialog = new FunctionStartRFParamsDialog(this);
|
||||||
}
|
}
|
||||||
if (!paramsDialog.getTrainingSource().equals(this.getCurrentProgram())) {
|
|
||||||
paramsDialog.dismissCallback();
|
|
||||||
paramsDialog = new FunctionStartRFParamsDialog(this);
|
|
||||||
}
|
|
||||||
tool.showDialog(paramsDialog, c.getComponentProvider());
|
tool.showDialog(paramsDialog, c.getComponentProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,14 @@ import ghidra.util.table.GhidraTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link DockingAction} for showing the most similar function starts in the training
|
* A {@link DockingAction} for showing the most similar function starts in the training
|
||||||
* set to a possible function start
|
* set to a possible function start
|
||||||
*/
|
*/
|
||||||
public class ShowSimilarStartsAction extends DockingAction {
|
public class ShowSimilarStartsAction extends DockingAction {
|
||||||
private static final String MENU_TEXT = "Show Similar Function Starts";
|
private static final String MENU_TEXT = "Show Similar Function Starts";
|
||||||
private static final String ACTION_NAME = "ShowSimilarStartsAction";
|
private static final String ACTION_NAME = "ShowSimilarStartsAction";
|
||||||
private static final int NUM_NEIGHBORS = 10;
|
private static final int NUM_NEIGHBORS = 10;
|
||||||
private Program program;
|
private Program trainingSource;
|
||||||
|
private Program targetProgram;
|
||||||
private FunctionStartTableModel model;
|
private FunctionStartTableModel model;
|
||||||
private GhidraTable table;
|
private GhidraTable table;
|
||||||
private RandomForestRowObject modelAndParams;
|
private RandomForestRowObject modelAndParams;
|
||||||
|
@ -43,20 +44,22 @@ public class ShowSimilarStartsAction extends DockingAction {
|
||||||
/**
|
/**
|
||||||
* Constructs an action display similar function starts
|
* Constructs an action display similar function starts
|
||||||
* @param plugin plugin
|
* @param plugin plugin
|
||||||
* @param program source program
|
* @param trainingSource source of training data
|
||||||
|
* @param targetProgram program being searched
|
||||||
* @param table table
|
* @param table table
|
||||||
* @param model table with action
|
* @param model table with action
|
||||||
*/
|
*/
|
||||||
public ShowSimilarStartsAction(RandomForestFunctionFinderPlugin plugin, Program program,
|
public ShowSimilarStartsAction(RandomForestFunctionFinderPlugin plugin, Program trainingSource,
|
||||||
GhidraTable table, FunctionStartTableModel model) {
|
Program targetProgram, GhidraTable table, FunctionStartTableModel model) {
|
||||||
super(ACTION_NAME, plugin.getName());
|
super(ACTION_NAME, plugin.getName());
|
||||||
this.program = program;
|
this.trainingSource = trainingSource;
|
||||||
|
this.targetProgram = targetProgram;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.table = table;
|
this.table = table;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.modelAndParams = model.getRandomForestRowObject();
|
this.modelAndParams = model.getRandomForestRowObject();
|
||||||
init();
|
init();
|
||||||
finder = new SimilarStartsFinder(program, modelAndParams);
|
finder = new SimilarStartsFinder(trainingSource, targetProgram, modelAndParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,8 +77,8 @@ public class ShowSimilarStartsAction extends DockingAction {
|
||||||
Address potential = model.getAddress(table.getSelectedRow());
|
Address potential = model.getAddress(table.getSelectedRow());
|
||||||
List<SimilarStartRowObject> closeNeighbors =
|
List<SimilarStartRowObject> closeNeighbors =
|
||||||
finder.getSimilarFunctionStarts(potential, NUM_NEIGHBORS);
|
finder.getSimilarFunctionStarts(potential, NUM_NEIGHBORS);
|
||||||
SimilarStartsTableProvider provider = new SimilarStartsTableProvider(plugin, program,
|
SimilarStartsTableProvider provider = new SimilarStartsTableProvider(plugin, trainingSource,
|
||||||
potential, closeNeighbors, modelAndParams);
|
targetProgram, potential, closeNeighbors, modelAndParams);
|
||||||
plugin.addProvider(provider);
|
plugin.addProvider(provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,13 @@ import ghidra.program.model.listing.Program;
|
||||||
* function starts, this class is used to find the function starts in the training set
|
* function starts, this class is used to find the function starts in the training set
|
||||||
* most similar to {@code S}. Here "similar" is defined in terms of proximity in a
|
* most similar to {@code S}. Here "similar" is defined in terms of proximity in a
|
||||||
* random forest (i.e., proportion of trees which agree on two feature vectors).
|
* random forest (i.e., proportion of trees which agree on two feature vectors).
|
||||||
|
* Note that {@code S} may or may not be in the training source program.
|
||||||
*/
|
*/
|
||||||
public class SimilarStartsFinder {
|
public class SimilarStartsFinder {
|
||||||
|
|
||||||
private RandomForestRowObject modelAndParams;
|
private RandomForestRowObject modelAndParams;
|
||||||
private Program program;
|
private Program trainingSource;
|
||||||
|
private Program targetProgram;
|
||||||
private int preBytes;
|
private int preBytes;
|
||||||
private int initialBytes;
|
private int initialBytes;
|
||||||
private boolean includeBitFeatures;
|
private boolean includeBitFeatures;
|
||||||
|
@ -48,11 +50,14 @@ public class SimilarStartsFinder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SimilarStartsFinder} for the given program and model
|
* Creates a {@link SimilarStartsFinder} for the given program and model
|
||||||
* @param program program
|
* @param trainingSource source of training data
|
||||||
|
* @param targetProgram program being searched
|
||||||
* @param modelAndParams model and params
|
* @param modelAndParams model and params
|
||||||
*/
|
*/
|
||||||
public SimilarStartsFinder(Program program, RandomForestRowObject modelAndParams) {
|
public SimilarStartsFinder(Program trainingSource, Program targetProgram,
|
||||||
this.program = program;
|
RandomForestRowObject modelAndParams) {
|
||||||
|
this.trainingSource = trainingSource;
|
||||||
|
this.targetProgram = targetProgram;
|
||||||
this.modelAndParams = modelAndParams;
|
this.modelAndParams = modelAndParams;
|
||||||
preBytes = modelAndParams.getNumPreBytes();
|
preBytes = modelAndParams.getNumPreBytes();
|
||||||
initialBytes = modelAndParams.getNumInitialBytes();
|
initialBytes = modelAndParams.getNumInitialBytes();
|
||||||
|
@ -69,7 +74,7 @@ public class SimilarStartsFinder {
|
||||||
* @return similar starts (in descending order)
|
* @return similar starts (in descending order)
|
||||||
*/
|
*/
|
||||||
public List<SimilarStartRowObject> getSimilarFunctionStarts(Address potential, int numStarts) {
|
public List<SimilarStartRowObject> getSimilarFunctionStarts(Address potential, int numStarts) {
|
||||||
List<Node<Label>> leafNodes = getLeafNodes(potential);
|
List<Node<Label>> leafNodes = getLeafNodes(potential, targetProgram);
|
||||||
List<SimilarStartRowObject> neighbors = new ArrayList<>(startsToLeafList.size());
|
List<SimilarStartRowObject> neighbors = new ArrayList<>(startsToLeafList.size());
|
||||||
for (Entry<Address, List<Node<Label>>> entry : startsToLeafList.entrySet()) {
|
for (Entry<Address, List<Node<Label>>> entry : startsToLeafList.entrySet()) {
|
||||||
Address start = entry.getKey();
|
Address start = entry.getKey();
|
||||||
|
@ -99,7 +104,7 @@ public class SimilarStartsFinder {
|
||||||
AddressIterator addrIter = knownStarts.getAddresses(true);
|
AddressIterator addrIter = knownStarts.getAddresses(true);
|
||||||
while (addrIter.hasNext()) {
|
while (addrIter.hasNext()) {
|
||||||
Address start = addrIter.next();
|
Address start = addrIter.next();
|
||||||
List<Node<Label>> nodeList = getLeafNodes(start);
|
List<Node<Label>> nodeList = getLeafNodes(start, trainingSource);
|
||||||
startsToLeafList.put(start, nodeList);
|
startsToLeafList.put(start, nodeList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,10 +112,11 @@ public class SimilarStartsFinder {
|
||||||
/**
|
/**
|
||||||
* Creates a feature vector for {@code addr}, runs it down each tree in the forest,
|
* Creates a feature vector for {@code addr}, runs it down each tree in the forest,
|
||||||
* and records the leaf node reached.
|
* and records the leaf node reached.
|
||||||
* @param addr potential function start
|
* @param addr (potential) function start
|
||||||
|
* @param program program containing {@code addr}
|
||||||
* @return list of leaf nodes
|
* @return list of leaf nodes
|
||||||
*/
|
*/
|
||||||
List<Node<Label>> getLeafNodes(Address addr) {
|
List<Node<Label>> getLeafNodes(Address addr, Program program) {
|
||||||
List<Node<Label>> leafNodes = new ArrayList<>(randomForest.getNumModels());
|
List<Node<Label>> leafNodes = new ArrayList<>(randomForest.getNumModels());
|
||||||
List<Feature> potentialFeatureVector = ModelTrainingUtils.getFeatureVector(program, addr,
|
List<Feature> potentialFeatureVector = ModelTrainingUtils.getFeatureVector(program, addr,
|
||||||
preBytes, initialBytes, includeBitFeatures);
|
preBytes, initialBytes, includeBitFeatures);
|
||||||
|
|
|
@ -41,7 +41,6 @@ import ghidra.util.task.TaskMonitor;
|
||||||
*/
|
*/
|
||||||
public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStartRowObject> {
|
public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStartRowObject> {
|
||||||
|
|
||||||
private Address potentialStart;
|
|
||||||
private List<SimilarStartRowObject> rows;
|
private List<SimilarStartRowObject> rows;
|
||||||
private RandomForestRowObject randomForestRow;
|
private RandomForestRowObject randomForestRow;
|
||||||
|
|
||||||
|
@ -50,14 +49,12 @@ public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStart
|
||||||
* a potential function start
|
* a potential function start
|
||||||
* @param plugin owning program
|
* @param plugin owning program
|
||||||
* @param program program
|
* @param program program
|
||||||
* @param potentialStart address of potential start
|
|
||||||
* @param rows similar function starts
|
* @param rows similar function starts
|
||||||
* @param randomForestRow model and params
|
* @param randomForestRow model and params
|
||||||
*/
|
*/
|
||||||
public SimilarStartsTableModel(PluginTool plugin, Program program, Address potentialStart,
|
public SimilarStartsTableModel(PluginTool plugin, Program program,
|
||||||
List<SimilarStartRowObject> rows, RandomForestRowObject randomForestRow) {
|
List<SimilarStartRowObject> rows, RandomForestRowObject randomForestRow) {
|
||||||
super("test", plugin, program, null, false);
|
super("Similar Starts", plugin, program, null, false);
|
||||||
this.potentialStart = potentialStart;
|
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
this.randomForestRow = randomForestRow;
|
this.randomForestRow = randomForestRow;
|
||||||
}
|
}
|
||||||
|
@ -70,10 +67,6 @@ public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStart
|
||||||
@Override
|
@Override
|
||||||
protected void doLoad(Accumulator<SimilarStartRowObject> accumulator, TaskMonitor monitor)
|
protected void doLoad(Accumulator<SimilarStartRowObject> accumulator, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
//add a special row corresponding to the potential function start
|
|
||||||
//want it in the table to facilitate (visual) byte string comparisons
|
|
||||||
accumulator.add(new SimilarStartRowObject(potentialStart,
|
|
||||||
randomForestRow.getRandomForest().getNumModels()));
|
|
||||||
accumulator.addAll(rows);
|
accumulator.addAll(rows);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -99,11 +92,6 @@ public class SimilarStartsTableModel extends AddressBasedTableModel<SimilarStart
|
||||||
public String getValue(SimilarStartRowObject rowObject, Settings settings, Object data,
|
public String getValue(SimilarStartRowObject rowObject, Settings settings, Object data,
|
||||||
ServiceProvider services) throws IllegalArgumentException {
|
ServiceProvider services) throws IllegalArgumentException {
|
||||||
String addrString = rowObject.funcStart().toString();
|
String addrString = rowObject.funcStart().toString();
|
||||||
//address corresponding to the potential start should stand out in the table
|
|
||||||
//so surround it with asterisks
|
|
||||||
if (rowObject.funcStart().equals(potentialStart)) {
|
|
||||||
addrString = "*" + addrString + "*";
|
|
||||||
}
|
|
||||||
return addrString;
|
return addrString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.machinelearning.functionfinding;
|
package ghidra.machinelearning.functionfinding;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -33,29 +33,35 @@ import ghidra.util.table.GhidraThreadedTablePanel;
|
||||||
* set to a potential function start
|
* set to a potential function start
|
||||||
*/
|
*/
|
||||||
public class SimilarStartsTableProvider extends ProgramAssociatedComponentProviderAdapter {
|
public class SimilarStartsTableProvider extends ProgramAssociatedComponentProviderAdapter {
|
||||||
private Program program;
|
private Program trainingSource;
|
||||||
|
private Program targetProgram;
|
||||||
private Address potentialStart;
|
private Address potentialStart;
|
||||||
private List<SimilarStartRowObject> rows;
|
private List<SimilarStartRowObject> rows;
|
||||||
private JComponent component;
|
private JSplitPane component;
|
||||||
private RandomForestRowObject randomForestRow;
|
private RandomForestRowObject randomForestRow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a table provider
|
* Create a table provider
|
||||||
* @param plugin owning plugin
|
* @param plugin owning plugin
|
||||||
* @param program program being search
|
* @param trainingSource source of training data
|
||||||
|
* @param targetProgram program being searched
|
||||||
* @param potentialStart address of potential start
|
* @param potentialStart address of potential start
|
||||||
* @param rows closest potential starts
|
* @param rows closest potential starts
|
||||||
* @param randomForestRow model and params
|
* @param randomForestRow model and params
|
||||||
*/
|
*/
|
||||||
public SimilarStartsTableProvider(RandomForestFunctionFinderPlugin plugin, Program program,
|
public SimilarStartsTableProvider(RandomForestFunctionFinderPlugin plugin,
|
||||||
Address potentialStart, List<SimilarStartRowObject> rows,
|
Program trainingSource, Program targetProgram, Address potentialStart,
|
||||||
RandomForestRowObject randomForestRow) {
|
List<SimilarStartRowObject> rows, RandomForestRowObject randomForestRow) {
|
||||||
super(program.getName() + ": Similar Function Starts", plugin.getName(), program, plugin);
|
super("Potential Start in " + targetProgram.getName(), plugin.getName(), targetProgram,
|
||||||
this.program = program;
|
plugin);
|
||||||
|
this.trainingSource = trainingSource;
|
||||||
|
this.targetProgram = targetProgram;
|
||||||
this.potentialStart = potentialStart;
|
this.potentialStart = potentialStart;
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
this.randomForestRow = randomForestRow;
|
this.randomForestRow = randomForestRow;
|
||||||
this.setSubTitle("Function Starts Similar to " + potentialStart.toString());
|
this.setSubTitle(
|
||||||
|
potentialStart.toString() + " compared to closest known starts in training set (from " +
|
||||||
|
trainingSource.getName() + ")");
|
||||||
build();
|
build();
|
||||||
setHelpLocation(new HelpLocation(plugin.getName(), "SimilarStartsTable"));
|
setHelpLocation(new HelpLocation(plugin.getName(), "SimilarStartsTable"));
|
||||||
}
|
}
|
||||||
|
@ -65,23 +71,51 @@ public class SimilarStartsTableProvider extends ProgramAssociatedComponentProvid
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the main component for this provider.
|
||||||
|
* <P>
|
||||||
|
* The component is a {@code JSplitPanel} with two {@link GhidraTable}s. The upper
|
||||||
|
* table consists of a single row containing the potential function start. The rows
|
||||||
|
* of the lower table contain the function starts in the training source program closest to
|
||||||
|
* the potential function start. Both tables are navigable; note that the potential
|
||||||
|
* function start may or may not be in training source program.
|
||||||
|
*/
|
||||||
private void build() {
|
private void build() {
|
||||||
component = new JPanel(new BorderLayout());
|
SimilarStartsTableModel similarStartsModel =
|
||||||
SimilarStartsTableModel model =
|
new SimilarStartsTableModel(tool, trainingSource, rows, randomForestRow);
|
||||||
new SimilarStartsTableModel(tool, program, potentialStart, rows, randomForestRow);
|
|
||||||
GhidraThreadedTablePanel<SimilarStartRowObject> similarStartsPanel =
|
GhidraThreadedTablePanel<SimilarStartRowObject> similarStartsPanel =
|
||||||
new GhidraThreadedTablePanel<>(model, 1000);
|
new GhidraThreadedTablePanel<>(similarStartsModel, 1000);
|
||||||
GhidraTable similarStartsTable = similarStartsPanel.getTable();
|
GhidraTable similarStartsTable = similarStartsPanel.getTable();
|
||||||
similarStartsTable.setName(
|
similarStartsPanel.setName(
|
||||||
program.getName() + ": Known Starts Similar to " + potentialStart.toString());
|
targetProgram.getName() + ": Known Starts Similar to " + potentialStart.toString());
|
||||||
GoToService goToService = tool.getService(GoToService.class);
|
GoToService goToService = tool.getService(GoToService.class);
|
||||||
if (goToService != null) {
|
if (goToService != null) {
|
||||||
similarStartsTable.installNavigation(goToService, goToService.getDefaultNavigatable());
|
similarStartsTable.installNavigation(goToService, goToService.getDefaultNavigatable());
|
||||||
}
|
}
|
||||||
similarStartsTable.setNavigateOnSelectionEnabled(true);
|
similarStartsTable.setNavigateOnSelectionEnabled(true);
|
||||||
similarStartsTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
similarStartsTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
||||||
similarStartsTable.setPreferredScrollableViewportSize(new Dimension(900, 300));
|
similarStartsTable.setPreferredScrollableViewportSize(new Dimension(700, 200));
|
||||||
component.add(similarStartsPanel, BorderLayout.CENTER);
|
similarStartsTable.setToolTipText("Known Starts in " + trainingSource.getName());
|
||||||
|
|
||||||
|
List<SimilarStartRowObject> singleton = new ArrayList<>();
|
||||||
|
singleton.add(new SimilarStartRowObject(potentialStart,
|
||||||
|
randomForestRow.getRandomForest().getNumModels()));
|
||||||
|
SimilarStartsTableModel potentialStartSingletonModel =
|
||||||
|
new SimilarStartsTableModel(tool, targetProgram, singleton, randomForestRow);
|
||||||
|
GhidraThreadedTablePanel<SimilarStartRowObject> potentialStartPanel =
|
||||||
|
new GhidraThreadedTablePanel<>(potentialStartSingletonModel, 1000);
|
||||||
|
GhidraTable potentialStartTable = potentialStartPanel.getTable();
|
||||||
|
potentialStartTable
|
||||||
|
.setToolTipText("Potential Function Start in " + targetProgram.getName());
|
||||||
|
if (goToService != null) {
|
||||||
|
potentialStartTable.installNavigation(goToService, goToService.getDefaultNavigatable());
|
||||||
|
}
|
||||||
|
potentialStartTable.setNavigateOnSelectionEnabled(true);
|
||||||
|
potentialStartTable.setPreferredScrollableViewportSize(new Dimension(700, 30));
|
||||||
|
potentialStartTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
|
||||||
|
component =
|
||||||
|
new JSplitPane(JSplitPane.VERTICAL_SPLIT, potentialStartPanel, similarStartsPanel);
|
||||||
|
component.setResizeWeight(.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class RandomForestTrainingTaskTest extends AbstractProgramBasedTest {
|
||||||
RandomForestFunctionFinderPlugin.NON_START, 1, 1, true, TaskMonitor.DUMMY));
|
RandomForestFunctionFinderPlugin.NON_START, 1, 1, true, TaskMonitor.DUMMY));
|
||||||
LabelFactory lf = new LabelFactory();
|
LabelFactory lf = new LabelFactory();
|
||||||
ListDataSource<Label> trainingSource =
|
ListDataSource<Label> trainingSource =
|
||||||
new ListDataSource<Label>(trainingData, lf, new SimpleDataSourceProvenance("test", lf));
|
new ListDataSource<>(trainingData, lf, new SimpleDataSourceProvenance("test", lf));
|
||||||
MutableDataset<Label> trainingSet = new MutableDataset<>(trainingSource);
|
MutableDataset<Label> trainingSet = new MutableDataset<>(trainingSource);
|
||||||
|
|
||||||
//create ensemble with two models which always report FUNC_START
|
//create ensemble with two models which always report FUNC_START
|
||||||
|
@ -199,7 +199,7 @@ public class RandomForestTrainingTaskTest extends AbstractProgramBasedTest {
|
||||||
new RandomForestTrainingTask(program, params, x -> rows.add(x), 100);
|
new RandomForestTrainingTask(program, params, x -> rows.add(x), 100);
|
||||||
TaskLauncher.launchModal("test", task);
|
TaskLauncher.launchModal("test", task);
|
||||||
assertEquals(1, rows.size());
|
assertEquals(1, rows.size());
|
||||||
SimilarStartsFinder finder = new SimilarStartsFinder(program, rows.get(0));
|
SimilarStartsFinder finder = new SimilarStartsFinder(program, program, rows.get(0));
|
||||||
Address entryAddr = program.getSymbolTable().getSymbols("entry").next().getAddress();
|
Address entryAddr = program.getSymbolTable().getSymbols("entry").next().getAddress();
|
||||||
List<SimilarStartRowObject> res = finder.getSimilarFunctionStarts(entryAddr, 7);
|
List<SimilarStartRowObject> res = finder.getSimilarFunctionStarts(entryAddr, 7);
|
||||||
//just verify that the number of elements is correct, each element is a function start,
|
//just verify that the number of elements is correct, each element is a function start,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue