mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-42 fix result dialog, age text field ui
This commit is contained in:
parent
3eb23e0c72
commit
084d2f1735
4 changed files with 103 additions and 49 deletions
|
@ -19,8 +19,6 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
import docking.DockingWindowManager;
|
|
||||||
import docking.widgets.dialogs.MultiLineMessageDialog;
|
|
||||||
import ghidra.app.plugin.core.analysis.*;
|
import ghidra.app.plugin.core.analysis.*;
|
||||||
import ghidra.app.plugin.core.datamgr.archive.DuplicateIdException;
|
import ghidra.app.plugin.core.datamgr.archive.DuplicateIdException;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
|
@ -32,7 +30,6 @@ import ghidra.app.util.pdb.pdbapplicator.*;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.*;
|
import ghidra.util.task.*;
|
||||||
|
|
||||||
|
@ -43,6 +40,8 @@ class LoadPdbTask extends Task {
|
||||||
private final boolean useMsDiaParser;
|
private final boolean useMsDiaParser;
|
||||||
private final PdbApplicatorControl control; // PDB Universal Parser only
|
private final PdbApplicatorControl control; // PDB Universal Parser only
|
||||||
private boolean debugLogging;
|
private boolean debugLogging;
|
||||||
|
private String resultMessages;
|
||||||
|
private Exception resultException;
|
||||||
|
|
||||||
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
|
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
|
||||||
boolean debugLogging, DataTypeManagerService service) {
|
boolean debugLogging, DataTypeManagerService service) {
|
||||||
|
@ -98,39 +97,27 @@ class LoadPdbTask extends Task {
|
||||||
try {
|
try {
|
||||||
AutoAnalysisManager.getAnalysisManager(program).scheduleWorker(worker, null, true,
|
AutoAnalysisManager.getAnalysisManager(program).scheduleWorker(worker, null, true,
|
||||||
wrappedMonitor);
|
wrappedMonitor);
|
||||||
if (log.hasMessages()) {
|
|
||||||
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
|
|
||||||
"There were warnings/errors loading the PDB file.", log.toString(),
|
|
||||||
MultiLineMessageDialog.WARNING_MESSAGE, false);
|
|
||||||
DockingWindowManager.showDialog(null, dialog);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (InterruptedException | CancelledException e1) {
|
catch (InterruptedException | CancelledException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException e) {
|
catch (InvocationTargetException e) {
|
||||||
String message;
|
resultException = e;
|
||||||
|
}
|
||||||
Throwable t = e.getCause();
|
if (log.hasMessages()) {
|
||||||
|
resultMessages = log.toString();
|
||||||
if (t == null) {
|
|
||||||
message = "Unknown cause";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
message = t.getMessage();
|
|
||||||
|
|
||||||
if (message == null) {
|
|
||||||
message = t.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message = "Error processing PDB file: " + pdbFile + ".\n" + message;
|
|
||||||
|
|
||||||
Msg.showError(getClass(), null, "Load PDB Failed", message, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getResultMessages() {
|
||||||
|
return resultMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
Exception getResultException() {
|
||||||
|
return resultException;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean parseWithMsDiaParser(MessageLog log, TaskMonitor monitor)
|
private boolean parseWithMsDiaParser(MessageLog log, TaskMonitor monitor)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
PdbParser parser = new PdbParser(pdbFile, program, service, true, true, monitor);
|
PdbParser parser = new PdbParser(pdbFile, program, service, true, true, monitor);
|
||||||
|
|
|
@ -17,14 +17,17 @@ package pdb;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
|
import docking.DockingWindowManager;
|
||||||
import docking.action.builder.ActionBuilder;
|
import docking.action.builder.ActionBuilder;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
|
import docking.widgets.dialogs.MultiLineMessageDialog;
|
||||||
import ghidra.app.CorePluginPackage;
|
import ghidra.app.CorePluginPackage;
|
||||||
import ghidra.app.context.ProgramActionContext;
|
import ghidra.app.context.ProgramActionContext;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
|
@ -118,12 +121,14 @@ public class PdbPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File pdbFile = null;
|
||||||
try {
|
try {
|
||||||
LoadPdbResults loadPdbResults = LoadPdbDialog.choosePdbForProgram(program);
|
LoadPdbResults loadPdbResults = LoadPdbDialog.choosePdbForProgram(program);
|
||||||
if (loadPdbResults == null) {
|
if (loadPdbResults == null) {
|
||||||
tool.setStatusInfo("Loading PDB was cancelled.");
|
tool.setStatusInfo("Loading PDB was cancelled.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pdbFile = loadPdbResults.pdbFile;
|
||||||
|
|
||||||
tool.setStatusInfo("");
|
tool.setStatusInfo("");
|
||||||
|
|
||||||
|
@ -138,16 +143,39 @@ public class PdbPlugin extends Plugin {
|
||||||
// note: We intentionally use a 0-delay here. Our underlying task may show modal
|
// note: We intentionally use a 0-delay here. Our underlying task may show modal
|
||||||
// dialog prompts. We want the task progress dialog to be showing before any
|
// dialog prompts. We want the task progress dialog to be showing before any
|
||||||
// prompts appear.
|
// prompts appear.
|
||||||
LoadPdbTask loadPdbTask = new LoadPdbTask(program, loadPdbResults.pdbFile,
|
LoadPdbTask loadPdbTask =
|
||||||
loadPdbResults.useMsDiaParser, loadPdbResults.control,
|
new LoadPdbTask(program, pdbFile, loadPdbResults.useMsDiaParser,
|
||||||
loadPdbResults.debugLogging, dataTypeManagerService);
|
loadPdbResults.control, loadPdbResults.debugLogging, dataTypeManagerService);
|
||||||
TaskBuilder.withTask(loadPdbTask)
|
TaskBuilder.withTask(loadPdbTask)
|
||||||
.setStatusTextAlignment(SwingConstants.LEADING)
|
.setStatusTextAlignment(SwingConstants.LEADING)
|
||||||
.setLaunchDelay(0);
|
.setLaunchDelay(0);
|
||||||
new TaskLauncher(loadPdbTask, null, 0);
|
new TaskLauncher(loadPdbTask, null, 0);
|
||||||
|
|
||||||
|
// Check for error messages & exceptions and handle them here
|
||||||
|
// (previously handled by the task, but dialog parenting issues in a modal
|
||||||
|
// task cause timing issues)
|
||||||
|
if (loadPdbTask.getResultException() != null) {
|
||||||
|
throw loadPdbTask.getResultException();
|
||||||
|
}
|
||||||
|
else if (loadPdbTask.getResultMessages() != null) {
|
||||||
|
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
|
||||||
|
"There were warnings/errors loading PDB file: " + pdbFile,
|
||||||
|
loadPdbTask.getResultMessages(),
|
||||||
|
MultiLineMessageDialog.WARNING_MESSAGE, false);
|
||||||
|
DockingWindowManager.showDialog(null, dialog);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception pe) {
|
catch (Exception e) {
|
||||||
Msg.showError(getClass(), null, "Error Loading PDB", pe.getMessage(), pe);
|
String message = null;
|
||||||
|
if (e instanceof InvocationTargetException && e.getCause() != null) {
|
||||||
|
message =
|
||||||
|
Objects.requireNonNullElse(e.getCause().getMessage(), e.getCause().toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = Objects.requireNonNullElse(e.getMessage(), e.toString());
|
||||||
|
}
|
||||||
|
Msg.showError(this, null, "Error Loading PDB",
|
||||||
|
"Error processing PDB file: " + pdbFile + "\n" + message, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ import docking.widgets.filechooser.GhidraFileChooser;
|
||||||
import docking.widgets.filechooser.GhidraFileChooserMode;
|
import docking.widgets.filechooser.GhidraFileChooserMode;
|
||||||
import docking.widgets.label.GIconLabel;
|
import docking.widgets.label.GIconLabel;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
|
import docking.widgets.textfield.HexOrDecimalInput;
|
||||||
import docking.widgets.textfield.HintTextField;
|
import docking.widgets.textfield.HintTextField;
|
||||||
import docking.widgets.textfield.IntegerTextField;
|
|
||||||
import ghidra.app.util.bin.format.pdb.PdbParser;
|
import ghidra.app.util.bin.format.pdb.PdbParser;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
|
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
|
||||||
import ghidra.framework.preferences.Preferences;
|
import ghidra.framework.preferences.Preferences;
|
||||||
|
@ -92,7 +92,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
LoadPdbResults results = new LoadPdbResults();
|
LoadPdbResults results = new LoadPdbResults();
|
||||||
results.pdbFile = pdbFile;
|
results.pdbFile = pdbFile;
|
||||||
results.control =
|
results.control =
|
||||||
(PdbApplicatorControl) choosePdbDlg.restrictionsCombo.getSelectedItem();
|
(PdbApplicatorControl) choosePdbDlg.applicatorControlCombo.getSelectedItem();
|
||||||
results.useMsDiaParser = choosePdbDlg.msdiaParserButton.isSelected();
|
results.useMsDiaParser = choosePdbDlg.msdiaParserButton.isSelected();
|
||||||
results.debugLogging = choosePdbDlg.debugLoggingCheckbox.isSelected();
|
results.debugLogging = choosePdbDlg.debugLoggingCheckbox.isSelected();
|
||||||
return results;
|
return results;
|
||||||
|
@ -119,7 +119,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
private GCheckBox overridePdbPathCheckBox;
|
private GCheckBox overridePdbPathCheckBox;
|
||||||
private JTextField pdbUniqueIdTextField;
|
private JTextField pdbUniqueIdTextField;
|
||||||
private GCheckBox overridePdbUniqueIdCheckBox;
|
private GCheckBox overridePdbUniqueIdCheckBox;
|
||||||
private IntegerTextField pdbAgeTextField;
|
private HexOrDecimalInput pdbAgeTextField;
|
||||||
private GCheckBox overridePdbAgeCheckBox;
|
private GCheckBox overridePdbAgeCheckBox;
|
||||||
private HintTextField pdbLocationTextField;
|
private HintTextField pdbLocationTextField;
|
||||||
private GIconLabel exactMatchIconLabel;
|
private GIconLabel exactMatchIconLabel;
|
||||||
|
@ -138,7 +138,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
private JPanel parserOptionsPanel;
|
private JPanel parserOptionsPanel;
|
||||||
private JRadioButton universalParserButton;
|
private JRadioButton universalParserButton;
|
||||||
private JRadioButton msdiaParserButton;
|
private JRadioButton msdiaParserButton;
|
||||||
private GComboBox<PdbApplicatorControl> restrictionsCombo;
|
private GComboBox<PdbApplicatorControl> applicatorControlCombo;
|
||||||
private GCheckBox debugLoggingCheckbox;
|
private GCheckBox debugLoggingCheckbox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -327,7 +327,8 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
if (symbolServerService == null || !symbolServerService.isValid()) {
|
if (symbolServerService == null || !symbolServerService.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pdbAgeTextField.getText().isBlank()) {
|
if (pdbAgeTextField.getText().isBlank() ||
|
||||||
|
pdbAgeTextField.getValue() > NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG) {
|
||||||
Msg.showWarn(this, null, "Bad PDB Age", "Invalid PDB Age value");
|
Msg.showWarn(this, null, "Bad PDB Age", "Invalid PDB Age value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +391,8 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildSymbolFilePanel() {
|
private void buildSymbolFilePanel() {
|
||||||
symbolFilePanel = new SymbolFilePanel(this::searchForPdbs); // panel will be added in layoutAdvanced()
|
// panel will be added in layoutAdvanced()
|
||||||
|
symbolFilePanel = new SymbolFilePanel(this::searchForPdbs);
|
||||||
|
|
||||||
symbolFilePanel.getTable()
|
symbolFilePanel.getTable()
|
||||||
.getSelectionModel()
|
.getSelectionModel()
|
||||||
|
@ -464,9 +466,8 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC,
|
new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC,
|
||||||
SymbolFilePanel.SEARCH_OPTIONS_HELP_ANCHOR));
|
SymbolFilePanel.SEARCH_OPTIONS_HELP_ANCHOR));
|
||||||
|
|
||||||
pdbAgeTextField = new IntegerTextField(8);
|
pdbAgeTextField = new BetterNonEditableHexTextField(8);
|
||||||
pdbAgeTextField.setAllowNegativeValues(false);
|
pdbAgeTextField.setAllowNegative(false);
|
||||||
pdbAgeTextField.setShowNumberMode(true);
|
|
||||||
pdbAgeTextField.setHexMode();
|
pdbAgeTextField.setHexMode();
|
||||||
pdbAgeTextField.setEditable(false);
|
pdbAgeTextField.setEditable(false);
|
||||||
|
|
||||||
|
@ -502,7 +503,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
programPdbPanel.add(
|
programPdbPanel.add(
|
||||||
join(null, new GLabel("PDB Age:", SwingConstants.RIGHT), overridePdbAgeCheckBox));
|
join(null, new GLabel("PDB Age:", SwingConstants.RIGHT), overridePdbAgeCheckBox));
|
||||||
programPdbPanel.add(join(pdbAgeTextField.getComponent(), new JPanel(), null));
|
programPdbPanel.add(join(pdbAgeTextField, new JPanel(), null));
|
||||||
|
|
||||||
return programPdbPanel;
|
return programPdbPanel;
|
||||||
}
|
}
|
||||||
|
@ -547,7 +548,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
if (universalParserButton.isSelected() && !universalParserButton.isEnabled()) {
|
if (universalParserButton.isSelected() && !universalParserButton.isEnabled()) {
|
||||||
universalParserButton.setSelected(false);
|
universalParserButton.setSelected(false);
|
||||||
}
|
}
|
||||||
restrictionsCombo.setEnabled(universalParserButton.isSelected());
|
applicatorControlCombo.setEnabled(universalParserButton.isSelected());
|
||||||
debugLoggingCheckbox.setEnabled(universalParserButton.isSelected());
|
debugLoggingCheckbox.setEnabled(universalParserButton.isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,8 +574,8 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
radioButtons.add(universalParserButton);
|
radioButtons.add(universalParserButton);
|
||||||
radioButtons.add(msdiaParserButton);
|
radioButtons.add(msdiaParserButton);
|
||||||
|
|
||||||
restrictionsCombo = new GComboBox<>(PdbApplicatorControl.values());
|
applicatorControlCombo = new GComboBox<>(PdbApplicatorControl.values());
|
||||||
restrictionsCombo.setSelectedItem(PdbApplicatorControl.ALL);
|
applicatorControlCombo.setSelectedItem(PdbApplicatorControl.ALL);
|
||||||
|
|
||||||
debugLoggingCheckbox = new GCheckBox();
|
debugLoggingCheckbox = new GCheckBox();
|
||||||
debugLoggingCheckbox.setToolTipText(
|
debugLoggingCheckbox.setToolTipText(
|
||||||
|
@ -591,7 +592,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
parserOptionsPanel.add(radioButtons);
|
parserOptionsPanel.add(radioButtons);
|
||||||
|
|
||||||
parserOptionsPanel.add(new GLabel("Control:"));
|
parserOptionsPanel.add(new GLabel("Control:"));
|
||||||
parserOptionsPanel.add(restrictionsCombo);
|
parserOptionsPanel.add(applicatorControlCombo);
|
||||||
|
|
||||||
parserOptionsPanel.add(new GLabel("[Dev] PDB Reader/Applicator Debug Logging:"));
|
parserOptionsPanel.add(new GLabel("[Dev] PDB Reader/Applicator Debug Logging:"));
|
||||||
parserOptionsPanel.add(debugLoggingCheckbox);
|
parserOptionsPanel.add(debugLoggingCheckbox);
|
||||||
|
@ -928,7 +929,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
@Override
|
@Override
|
||||||
public Color getBackground() {
|
public Color getBackground() {
|
||||||
Container parent = getParent();
|
Container parent = getParent();
|
||||||
if (parent != null && isEditable() == false) {
|
if (parent != null && !isEditable()) {
|
||||||
Color bg = parent.getBackground();
|
Color bg = parent.getBackground();
|
||||||
// mint a new Color object to avoid it being
|
// mint a new Color object to avoid it being
|
||||||
// ignored because the parent handed us a DerivedColor
|
// ignored because the parent handed us a DerivedColor
|
||||||
|
@ -939,4 +940,23 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class BetterNonEditableHexTextField extends HexOrDecimalInput {
|
||||||
|
|
||||||
|
BetterNonEditableHexTextField(int columns) {
|
||||||
|
super(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getBackground() {
|
||||||
|
Container parent = getParent();
|
||||||
|
if (parent != null && !isEditable()) {
|
||||||
|
Color bg = parent.getBackground();
|
||||||
|
// mint a new Color object to avoid it being
|
||||||
|
// ignored because the parent handed us a DerivedColor
|
||||||
|
// instance
|
||||||
|
return new Color(bg.getRGB());
|
||||||
|
}
|
||||||
|
return super.getBackground();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,16 @@ public class HexOrDecimalInput extends JTextField {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HexOrDecimalInput(int columns) {
|
||||||
|
super(columns);
|
||||||
|
init(null);
|
||||||
|
}
|
||||||
|
|
||||||
public HexOrDecimalInput(Long initialValue) {
|
public HexOrDecimalInput(Long initialValue) {
|
||||||
super();
|
init(initialValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Long initialValue) {
|
||||||
currentValue = initialValue;
|
currentValue = initialValue;
|
||||||
setDocument(new MyDocument());
|
setDocument(new MyDocument());
|
||||||
updateText();
|
updateText();
|
||||||
|
@ -55,6 +63,17 @@ public class HexOrDecimalInput extends JTextField {
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getIntValue() {
|
||||||
|
if (currentValue == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return currentValue.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(int newValue) {
|
||||||
|
setValue((long) newValue);
|
||||||
|
}
|
||||||
|
|
||||||
public void setValue(Long newValue) {
|
public void setValue(Long newValue) {
|
||||||
if (!allowsNegative && newValue != null && newValue.longValue() < 0) {
|
if (!allowsNegative && newValue != null && newValue.longValue() < 0) {
|
||||||
currentValue = null;
|
currentValue = null;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue