GP-42 fix result dialog, age text field ui

This commit is contained in:
dev747368 2021-05-13 16:14:32 -04:00
parent 3eb23e0c72
commit 084d2f1735
4 changed files with 103 additions and 49 deletions

View file

@ -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);

View file

@ -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);
} }
} }

View file

@ -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();
}
}
} }

View file

@ -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;