Merge remote-tracking branch 'origin/GP-984_dev747368_simplify_loadpdb_gui--SQUASHED' into Ghidra_10.0

This commit is contained in:
ghidra1 2021-06-04 08:28:41 -04:00
commit 21b3fbf8ea
15 changed files with 151 additions and 225 deletions

View File

@ -16,13 +16,14 @@ src/main/help/help/shared/redo.png||GHIDRA||||END|
src/main/help/help/shared/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/help/help/shared/tip.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/shared/undo.png||GHIDRA||||END| src/main/help/help/shared/undo.png||GHIDRA||||END|
src/main/help/help/shared/warning.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/help/help/shared/warning.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/topics/Pdb/LoadPDBNew.html||GHIDRA||||END| src/main/help/help/topics/Pdb/LoadPDB.html||GHIDRA||||END|
src/main/help/help/topics/Pdb/PDB.htm||GHIDRA||||END| src/main/help/help/topics/Pdb/PDB.htm||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/Plus2.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/Plus2.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/SymbolServerConfig_AddButtonMenu.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/SymbolServerConfig_AddButtonMenu.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/SymbolServerConfig_Configured.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/SymbolServerConfig_Screenshot.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/SymbolServerConfig_Screenshot.png||GHIDRA||||END|
src/main/help/help/topics/Pdb/images/disk.png||FAMFAMFAM Icons - CC 2.5||||END| src/main/help/help/topics/Pdb/images/disk.png||FAMFAMFAM Icons - CC 2.5||||END|
src/main/help/help/topics/Pdb/images/down.png||GHIDRA||||END| src/main/help/help/topics/Pdb/images/down.png||GHIDRA||||END|

View File

@ -51,7 +51,7 @@
<tocroot> <tocroot>
<tocref id="Program Annotation"> <tocref id="Program Annotation">
<tocdef id="PDB" sortgroup="q" text="PDB" target="help/topics/Pdb/PDB.htm" > <tocdef id="PDB" sortgroup="q" text="PDB" target="help/topics/Pdb/PDB.htm" >
<tocdef id="LoadPDBNew" sortgroup="a" text="Load PDB File" target="help/topics/Pdb/LoadPDBNew.html" /> <tocdef id="LoadPDB" sortgroup="a" text="Load PDB File" target="help/topics/Pdb/LoadPDB.html" />
<tocdef id="README_PDB" sortgroup="b" text="PDB Parser (README_PDB)" target="docs/README_PDB.html" /> <tocdef id="README_PDB" sortgroup="b" text="PDB Parser (README_PDB)" target="docs/README_PDB.html" />
</tocdef> </tocdef>
</tocref> </tocref>

View File

@ -33,7 +33,7 @@
<LI><CODE><FONT COLOR="BLUE">myprogram.pdb</FONT>/<FONT COLOR="RED">012345670123012301230123456789AB</FONT><FONT COLOR="GREEN">1</FONT>/<FONT COLOR="BLUE">myprogram.pdb</FONT></CODE>.</LI> <LI><CODE><FONT COLOR="BLUE">myprogram.pdb</FONT>/<FONT COLOR="RED">012345670123012301230123456789AB</FONT><FONT COLOR="GREEN">1</FONT>/<FONT COLOR="BLUE">myprogram.pdb</FONT></CODE>.</LI>
<LI><CODE><FONT COLOR="BLUE">myprogram.pdb</FONT></CODE> is the name of the file and the name of the initial subdirectory off the root of the server.</LI> <LI><CODE><FONT COLOR="BLUE">myprogram.pdb</FONT></CODE> is the name of the file and the name of the initial subdirectory off the root of the server.</LI>
<LI><CODE><FONT COLOR="RED">012345670123012301230123456789AB</FONT></CODE> is the 32 character hexadecimal value (made up for this example) of the GUID <LI><CODE><FONT COLOR="RED">012345670123012301230123456789AB</FONT></CODE> is the 32 character hexadecimal value (made up for this example) of the GUID
"012345678-0123-0123-0123-0123456789AB" of the PDB file.</LI> "01234567-0123-0123-0123-0123456789AB" of the PDB file.</LI>
<UL><LI>This value might instead be a 8 character hexadecimal value of the ID of the symbol file if it was created by an older version of the tool chain.</LI></UL> <UL><LI>This value might instead be a 8 character hexadecimal value of the ID of the symbol file if it was created by an older version of the tool chain.</LI></UL>
<LI><CODE><FONT COLOR="GREEN">1</FONT></CODE> is the hexadecimal value of the 'age' (build number) of the PDB file. Note: most PDB files will have an age value of 1.</LI> <LI><CODE><FONT COLOR="GREEN">1</FONT></CODE> is the hexadecimal value of the 'age' (build number) of the PDB file. Note: most PDB files will have an age value of 1.</LI>
</UL> </UL>
@ -56,14 +56,8 @@
</UL> </UL>
<LI><A name="Unorganized_SymbolDirectory"></A>Unorganized directories:</LI> <LI><A name="Unorganized_SymbolDirectory"></A>Unorganized directories:</LI>
<UL> <UL>
<LI>Symbol files are are found by matching the leading part of the filename found in the unorganized directory with the sought-after symbol <LI>Symbol files are matched by their filename and the GUID / ID / age values extracted from
file's name.</LI> the information inside the PDB symbol file.</LI>
<UL>
<LI><CODE>helloworld.pdb</CODE> and <CODE>hellokitty.pdb</CODE> would both be found as possible matches when searching for
<CODE>hello.pdb</CODE>.</LI>
<LI>During searches, each possible matching PDB symbol file will be opened and partially parsed to extract its GUID and age values to determine if
it matches the user's full search criteria.</LI>
</UL>
</UL> </UL>
</UL> </UL>
</BLOCKQUOTE> </BLOCKQUOTE>
@ -88,16 +82,10 @@
which PDB file to choose.</LI> which PDB file to choose.</LI>
<LI>If needed, click the <B>Advanced</B> button: <LI>If needed, click the <B>Advanced</B> button:
<BLOCKQUOTE><IMG border="0" src="images/LoadPdb_Advanced_NeedsConfig.png"></BLOCKQUOTE></LI> <BLOCKQUOTE><IMG border="0" src="images/LoadPdb_Advanced_NeedsConfig.png"></BLOCKQUOTE></LI>
<LI>The <b>Local Symbol Storage</b> location is required to enable searching. If missing, set it to a directory where Ghidra can store PDB files.</LI> <LI>The <b>Local Symbol Storage</b> location (in the <A href="#Symbol_Server_Config">Symbol Server Config</A> screen) is required
<UL> to enable searching. If missing, click the <B>Config...</B> button.</LI>
<LI>For example, <CODE>/home/your_id/Symbols</CODE> or <CODE>C:\Users\your_name\Symbols</CODE>.</LI>
<LI>If the location is a new empty directory, the user will be prompted to initialize the directory as a Microsoft symbol storage directory.</LI>
</UL>
<LI><A href="#SymbolServerConfig_Add">Add</A> additional search locations by clicking the <img border="0" src="images/Plus2.png"> button.
The Microsoft symbol server and <b>Program's Import Location</b> are good defaults.</LI>
<LI>Save any changes to the configuration by clicking the <img border="0" src="images/disk.png"> button.</LI>
<LI>Set <A href="#PDB_Search_Search_Options">search options</A> as needed.</LI> <LI>Set <A href="#PDB_Search_Search_Options">search options</A> as needed.</LI>
<LI>Click the <b>Search</b> button to search the configured locations.</LI> <LI>Click the <b>Search Local</b> or <b>Search All</b> button to search the configured locations.</LI>
<BLOCKQUOTE><IMG border="0" src="images/LoadPdb_Advanced_Screenshot.png"></BLOCKQUOTE></LI> <BLOCKQUOTE><IMG border="0" src="images/LoadPdb_Advanced_Screenshot.png"></BLOCKQUOTE></LI>
<LI>The <b>Local Symbol Storage</b> location is searched first, followed by any locations listed in the <LI>The <b>Local Symbol Storage</b> location is searched first, followed by any locations listed in the
<b>Additional Search Paths</b> list, in listed order.</LI> <b>Additional Search Paths</b> list, in listed order.</LI>
@ -111,7 +99,7 @@
<H3><A name="Symbol_Server_Config"></A>Symbol Server Config</H3> <H3><A name="Symbol_Server_Config"></A>Symbol Server Config</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<P>Allows the user to configure the location where PDB symbol files are stored and additional locations to search for <P>Allows the user to configure the location where PDB symbol files are stored and additional locations to search for
existing PDB files. This is also available in the <b>Load PDB File</b>, <b>Advanced</b> screen.</P> existing PDB files.</P>
<H4>Steps:</H4> <H4>Steps:</H4>
<UL> <UL>
<LI>Invoke <b>Edit &rarr; Symbol Server Config</b> <LI>Invoke <b>Edit &rarr; Symbol Server Config</b>
@ -125,6 +113,7 @@
<LI><a href="#SymbolServerConfig_Add">Add</a> additional search locations by clicking the <img border="0" src="images/Plus2.png"> button.</LI> <LI><a href="#SymbolServerConfig_Add">Add</a> additional search locations by clicking the <img border="0" src="images/Plus2.png"> button.</LI>
<LI>Save any changes to the configuration by clicking the <img border="0" src="images/disk.png"> button.</LI> <LI>Save any changes to the configuration by clicking the <img border="0" src="images/disk.png"> button.</LI>
<LI>Search locations can be disabled by toggling the <b>enabled</b> checkbox at the beginning of the row.</LI> <LI>Search locations can be disabled by toggling the <b>enabled</b> checkbox at the beginning of the row.</LI>
<LI>A typical configuration: <BLOCKQUOTE><IMG border="0" src="images/SymbolServerConfig_Configured.png"></BLOCKQUOTE></LI>
</UL> </UL>
<H4><A name="SymbolServerConfig_Add"></A><img border="0" src="images/Plus2.png">&nbsp;(Add)</H4> <H4><A name="SymbolServerConfig_Add"></A><img border="0" src="images/Plus2.png">&nbsp;(Add)</H4>

View File

@ -37,7 +37,7 @@
<BLOCKQUOTE> <BLOCKQUOTE>
<P>PDB files can be loaded in two ways:</P> <P>PDB files can be loaded in two ways:</P>
<UL> <UL>
<LI><B>File &rarr; <a href="LoadPDBNew.html#Load_PDB_File">Load PDB File</a></B></LI> <LI><B>File &rarr; <a href="LoadPDB.html#Load_PDB_File">Load PDB File</a></B></LI>
<LI>PDB Analyzer via <B>Analysis &rarr; <LI>PDB Analyzer via <B>Analysis &rarr;
<A HREF="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analyze">Auto Analyze</A></B> or <A HREF="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Auto_Analyze">Auto Analyze</A></B> or
<B>Analysis &rarr; <A HREF="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Analyze_One_Shot">One Shot</A></B>. <B>Analysis &rarr; <A HREF="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm#Analyze_One_Shot">One Shot</A></B>.
@ -124,7 +124,7 @@
<P class="relatedtopic">Related Topics:</P> <P class="relatedtopic">Related Topics:</P>
<UL> <UL>
<LI><A href="LoadPDBNew.html">Load PDB File</A></LI> <LI><A href="LoadPDB.html">Load PDB File</A></LI>
<LI><A href="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm">Auto Analysis</A></LI> <LI><A href="help/topics/AutoAnalysisPlugin/AutoAnalysis.htm">Auto Analysis</A></LI>
</UL> </UL>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -204,26 +204,22 @@ public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStor
List<SymbolFileLocation> matches = new ArrayList<>(); List<SymbolFileLocation> matches = new ArrayList<>();
// search for exact matches using the built-in logic in AbstractSymbolServer
if (storageLevel != 0) { if (storageLevel != 0) {
// search for exact matches using the built-in logic in AbstractSymbolServer
matches.addAll(super.find(symbolFileInfo, options, monitor)); matches.addAll(super.find(symbolFileInfo, options, monitor));
}
if (storageLevel == 0 || options.contains(FindOption.ANY_AGE) || if (options.contains(FindOption.ANY_AGE) || options.contains(FindOption.ANY_ID)) {
options.contains(FindOption.ANY_ID)) { try {
try {
if (storageLevel == 0) {
searchLevel0(rootDir, this, symbolFileInfo, options, matches, monitor);
}
else {
searchLevelN(symbolFileInfo, options, matches, monitor); searchLevelN(symbolFileInfo, options, matches, monitor);
} }
catch (IOException ioe) {
Msg.warn(this,
"Error searching for " + symbolFileInfo.getName() + " in " + rootDir, ioe);
}
} }
catch (IOException ioe) { }
Msg.warn(this, "Error searching for " + symbolFileInfo.getName() + " in " + rootDir, else {
ioe); searchLevel0(rootDir, this, symbolFileInfo, options, matches, monitor);
}
} }
return matches; return matches;
@ -232,18 +228,14 @@ public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStor
static void searchLevel0(File rootDir, SymbolStore symbolStore, SymbolFileInfo symbolFileInfo, static void searchLevel0(File rootDir, SymbolStore symbolStore, SymbolFileInfo symbolFileInfo,
Set<FindOption> options, List<SymbolFileLocation> matches, TaskMonitor monitor) { Set<FindOption> options, List<SymbolFileLocation> matches, TaskMonitor monitor) {
// if its a "0 level" bag-of-files, we have to open each Pdb to find its UID and File f = new File(rootDir, symbolFileInfo.getName());
// AGE (after filtering for similar filenames as requested pdb file) if (!f.isFile()) {
for (File f : list(rootDir, return;
ff -> ff.isFile() && isFilenameStartsWithMatch(symbolFileInfo, ff))) { }
if (monitor.isCancelled()) { SymbolFileInfo fileInfo = SymbolFileInfo.fromFile(f, monitor);
break; if (fileInfo != null) {
} if (hasSymbolFileInfoMatch(symbolFileInfo, fileInfo, options)) {
SymbolFileInfo fileInfo = SymbolFileInfo.fromFile(f, monitor); matches.add(new SymbolFileLocation(f.getName(), symbolStore, fileInfo));
if (fileInfo != null) {
if (hasSymbolFileInfoMatch(symbolFileInfo, fileInfo, options)) {
matches.add(new SymbolFileLocation(f.getName(), symbolStore, fileInfo));
}
} }
} }
} }
@ -402,24 +394,6 @@ public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStor
return files != null ? files : new File[] {}; return files != null ? files : new File[] {};
} }
static boolean isFilenameStartsWithMatch(SymbolFileInfo symbolFileInfo, File file) {
String symbolFilenameNoExtension = FilenameUtils.getBaseName(symbolFileInfo.getName());
String fileNoExtension = FilenameUtils.getBaseName(file.getName());
// use case-insensitive compare since these are PDB files, which
// come from a Windows env
if (!fileNoExtension.toLowerCase().startsWith(symbolFilenameNoExtension.toLowerCase())) {
return false;
}
// match on ext ("pdb"), compressed ext ("pd_")
String symbolFilenameExtension =
FilenameUtils.getExtension(symbolFileInfo.getName()).toLowerCase();
String fileExtension = FilenameUtils.getExtension(file.getName()).toLowerCase();
return fileExtension.equals(symbolFilenameExtension) ||
fileExtension.equals(makeCompressedExtension(symbolFilenameExtension));
}
static boolean hasSymbolFileInfoMatch(SymbolFileInfo symbolFileInfo, static boolean hasSymbolFileInfoMatch(SymbolFileInfo symbolFileInfo,
SymbolFileInfo otherSymbolFileInfo, Set<FindOption> options) { SymbolFileInfo otherSymbolFileInfo, Set<FindOption> options) {
boolean idMatches = boolean idMatches =

View File

@ -15,9 +15,8 @@
*/ */
package pdb.symbolserver; package pdb.symbolserver;
import java.util.*;
import java.io.*; import java.io.*;
import java.util.*;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -25,8 +24,6 @@ import ghidra.util.task.TaskMonitor;
* A Pdb symbol server / symbol store, similar to the {@link LocalSymbolStore}, * A Pdb symbol server / symbol store, similar to the {@link LocalSymbolStore},
* but limited to searching just the single directory that the original executable is located in. * but limited to searching just the single directory that the original executable is located in.
* <p> * <p>
* Matches symbol files that have a similar name to the requested symbol file (but the identifier
* info - guid/id & age must still match as per the find options specified).
* *
*/ */
public class SameDirSymbolStore implements SymbolStore { public class SameDirSymbolStore implements SymbolStore {
@ -105,8 +102,8 @@ public class SameDirSymbolStore implements SymbolStore {
@Override @Override
public String getDescriptiveName() { public String getDescriptiveName() {
return String.format(PROGRAMS_IMPORT_LOCATION_DESCRIPTION_STR + " - %s", return PROGRAMS_IMPORT_LOCATION_DESCRIPTION_STR +
isValid() ? rootDir.getPath() : "unspecified"); (isValid() ? " - " + rootDir.getPath() : "");
} }
@Override @Override

View File

@ -15,23 +15,25 @@
*/ */
package pdb.symbolserver.ui; package pdb.symbolserver.ui;
import java.util.List;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import docking.widgets.OptionDialog; import pdb.symbolserver.*;
import pdb.symbolserver.SymbolServerInstanceCreatorRegistry;
import pdb.symbolserver.SymbolServerService;
/** /**
* Dialog that allows the user to configure the Pdb search locations and symbol directory * Dialog that allows the user to configure the Pdb search locations and symbol directory
*/ */
public class ConfigPdbDialog extends DialogComponentProvider { public class ConfigPdbDialog extends DialogComponentProvider {
public static void showSymbolServerConfig() { public static boolean showSymbolServerConfig() {
ConfigPdbDialog choosePdbDialog = new ConfigPdbDialog(); ConfigPdbDialog choosePdbDialog = new ConfigPdbDialog();
DockingWindowManager.showDialog(choosePdbDialog); DockingWindowManager.showDialog(choosePdbDialog);
return choosePdbDialog.wasSuccess;
} }
private SymbolServerPanel symbolServerConfigPanel; private SymbolServerPanel symbolServerConfigPanel;
private boolean wasSuccess;
public ConfigPdbDialog() { public ConfigPdbDialog() {
super("Configure Symbol Server Search", true, false, true, false); super("Configure Symbol Server Search", true, false, true, false);
@ -46,12 +48,10 @@ public class ConfigPdbDialog extends DialogComponentProvider {
@Override @Override
protected void okCallback() { protected void okCallback() {
if (symbolServerConfigPanel.isConfigChanged() && if (symbolServerConfigPanel.isConfigChanged()) {
OptionDialog.showYesNoDialog(getComponent(),
"Save Configuration",
"Symbol server configuration changed. Save?") == OptionDialog.YES_OPTION) {
symbolServerConfigPanel.saveConfig(); symbolServerConfigPanel.saveConfig();
} }
wasSuccess = true;
close(); close();
} }
@ -76,4 +76,23 @@ public class ConfigPdbDialog extends DialogComponentProvider {
addCancelButton(); addCancelButton();
setDefaultButton(cancelButton); setDefaultButton(cancelButton);
} }
/**
* Screen shot usage only
*/
public void pushAddLocationButton() {
symbolServerConfigPanel.pushAddLocationButton();
}
/**
* Screen shot only
*
* @param fakeDirectoryText fake text to display in the storage directory text field
* @param symbolServers list of symbol servers to force set
*/
public void setSymbolServerService(String fakeDirectoryText,
List<SymbolServer> symbolServers) {
symbolServerConfigPanel.setSymbolServers(symbolServers);
symbolServerConfigPanel.setSymbolStorageDirectoryTextOnly(fakeDirectoryText);
}
} }

View File

@ -107,10 +107,10 @@ public class LoadPdbDialog extends DialogComponentProvider {
private List<Supplier<StatusText>> statusTextSuppliers = new ArrayList<>(); private List<Supplier<StatusText>> statusTextSuppliers = new ArrayList<>();
private Set<FindOption> lastSearchOptions; private Set<FindOption> lastSearchOptions;
private boolean searchCanceled; private boolean searchCanceled;
private boolean hasShownAdvanced;
private Program program; private Program program;
private SymbolServerPanel symbolServerConfigPanel;
private SymbolFilePanel symbolFilePanel; private SymbolFilePanel symbolFilePanel;
private JTextField programNameTextField; private JTextField programNameTextField;
@ -123,6 +123,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
private HintTextField pdbLocationTextField; private HintTextField pdbLocationTextField;
private GIconLabel exactMatchIconLabel; private GIconLabel exactMatchIconLabel;
private JButton configButton;
private JToggleButton advancedToggleButton; private JToggleButton advancedToggleButton;
private GhidraFileChooser chooser; private GhidraFileChooser chooser;
@ -153,14 +154,17 @@ public class LoadPdbDialog extends DialogComponentProvider {
if (programSymbolFileInfo == null) { if (programSymbolFileInfo == null) {
programSymbolFileInfo = SymbolFileInfo.unknown("missing"); programSymbolFileInfo = SymbolFileInfo.unknown("missing");
} }
this.symbolServerInstanceCreatorContext = updateSymbolServerServiceInstanceFromPreferences();
SymbolServerInstanceCreatorRegistry.getInstance().getContext(program);
this.symbolServerService =
PdbPlugin.getSymbolServerService(symbolServerInstanceCreatorContext);
build(); build();
} }
private void updateSymbolServerServiceInstanceFromPreferences() {
symbolServerInstanceCreatorContext =
SymbolServerInstanceCreatorRegistry.getInstance().getContext(program);
symbolServerService =
PdbPlugin.getSymbolServerService(symbolServerInstanceCreatorContext);
}
@Override @Override
protected void dialogShown() { protected void dialogShown() {
pdbPathTextField.setText(programSymbolFileInfo.getPath()); pdbPathTextField.setText(programSymbolFileInfo.getPath());
@ -169,32 +173,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
programNameTextField.setText(program.getName()); programNameTextField.setText(program.getName());
cancelButton.requestFocusInWindow(); cancelButton.requestFocusInWindow();
executeMonitoredRunnable("Search for PDB using built-in locations", true, true, 0, searchForPdbs(false);
this::doInitialDefaultSearch);
}
private void doInitialDefaultSearch(TaskMonitor monitor) {
try {
List<SymbolFileLocation> results =
symbolServerService.find(programSymbolFileInfo, FindOption.NO_OPTIONS, monitor);
if (!results.isEmpty()) {
SymbolFileLocation symbolFileLocation =
symbolServerService.getLocalSymbolFileLocation(results.get(0), monitor);
File symbolFile = getLocalSymbolFile(symbolFileLocation);
Swing.runLater(() -> {
setSearchResults(results, null);
setPdbLocationValue(symbolFileLocation, symbolFile);
setSelectedPdbFile(symbolFileLocation);
selectRowByLocation(symbolFileLocation);
updateStatusText();
updateButtonEnablement();
updateParserOptionEnablement(true);
});
}
}
catch (CancelledException | IOException e) {
// ignore
}
} }
@Override @Override
@ -212,33 +191,9 @@ public class LoadPdbDialog extends DialogComponentProvider {
symbolFilePanel.setFindOptions(options); symbolFilePanel.setFindOptions(options);
} }
/**
* For screenshot use only
*
* @param pathStr path of symbol storage directory
*/
public void setSymbolStorageDirectoryTextOnly(String pathStr) {
symbolServerConfigPanel.setSymbolStorageDirectoryTextOnly(pathStr);
}
/**
* For screenshot use only
*
* @param symbolServers list of symbol servers
*/
public void setSymbolServers(List<SymbolServer> symbolServers) {
symbolServerConfigPanel.setSymbolServers(symbolServers);
}
/**
* For screenshot use only
*/
public void pushAddLocationBution() {
symbolServerConfigPanel.pushAddLocationButton();
}
private void setSelectedPdbFile(SymbolFileLocation symbolFileLocation) { private void setSelectedPdbFile(SymbolFileLocation symbolFileLocation) {
this.selectedSymbolFile = symbolFileLocation; this.selectedSymbolFile = symbolFileLocation;
setPdbLocationValue(symbolFileLocation, getLocalSymbolFile(symbolFileLocation));
} }
/** /**
@ -247,6 +202,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
* Public only for screenshot usage, treat as private otherwise. * Public only for screenshot usage, treat as private otherwise.
* *
* @param results list of {@link SymbolFileLocation}s to add to results * @param results list of {@link SymbolFileLocation}s to add to results
* @param findOptions the options used to search
*/ */
public void setSearchResults(List<SymbolFileLocation> results, Set<FindOption> findOptions) { public void setSearchResults(List<SymbolFileLocation> results, Set<FindOption> findOptions) {
lastSearchOptions = findOptions; lastSearchOptions = findOptions;
@ -304,13 +260,11 @@ public class LoadPdbDialog extends DialogComponentProvider {
private void updateButtonEnablement() { private void updateButtonEnablement() {
boolean hasLocation = selectedSymbolFile != null; boolean hasLocation = selectedSymbolFile != null;
boolean hasGoodService = symbolServerService.isValid();
loadPdbButton.setEnabled(hasLocation); loadPdbButton.setEnabled(hasLocation);
} configButton.setIcon(hasGoodService ? null : MATCH_BAD_ICON);
configButton.setToolTipText(hasGoodService ? null : "Missing configuration");
private void setSymbolServerService(SymbolServerService symbolServerService) { symbolFilePanel.setEnablement(hasGoodService);
this.symbolServerService = symbolServerService;
symbolFilePanel.setEnablement(symbolServerService != null);
updateStatusText();
} }
private SymbolFileInfo getCurrentSymbolFileInfo() { private SymbolFileInfo getCurrentSymbolFileInfo() {
@ -322,9 +276,6 @@ public class LoadPdbDialog extends DialogComponentProvider {
} }
private void searchForPdbs(boolean allowRemote) { private void searchForPdbs(boolean allowRemote) {
if (symbolServerService == null || !symbolServerService.isValid()) {
return;
}
if (pdbAgeTextField.getText().isBlank() || if (pdbAgeTextField.getText().isBlank() ||
pdbAgeTextField.getValue() > NumericUtilities.MAX_UNSIGNED_INT32_AS_LONG) { 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");
@ -347,11 +298,12 @@ public class LoadPdbDialog extends DialogComponentProvider {
symbolServerService.find(symbolFileInfo, findOptions, monitor); symbolServerService.find(symbolFileInfo, findOptions, monitor);
Swing.runLater(() -> { Swing.runLater(() -> {
setSearchResults(results, findOptions); setSearchResults(results, findOptions);
if (results.size() == 1) { if (!results.isEmpty()) {
selectRowByLocation(results.get(0)); selectRowByLocation(results.get(0));
} }
updateStatusText(); updateStatusText();
updateButtonEnablement(); updateButtonEnablement();
updateParserOptionEnablement(true);
}); });
} }
catch (CancelledException e1) { catch (CancelledException e1) {
@ -364,17 +316,15 @@ public class LoadPdbDialog extends DialogComponentProvider {
private void build() { private void build() {
buildSymbolFilePanel(); buildSymbolFilePanel();
buildSSConfigPanel();
buildPdbLocationPanel(); buildPdbLocationPanel();
buildProgramPdbPanel(); buildProgramPdbPanel();
buildParserOptionsPanel(); buildParserOptionsPanel();
setHelpLocation(new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "Load PDB File")); setHelpLocation(new HelpLocation(PdbPlugin.PDB_PLUGIN_HELP_TOPIC, "Load PDB File"));
addStatusTextSupplier(() -> lastSearchOptions != null && advancedToggleButton.isSelected() addStatusTextSupplier(() -> lastSearchOptions != null && advancedToggleButton.isSelected()
? symbolServerConfigPanel.getSymbolServerWarnings() ? SymbolServerPanel.getSymbolServerWarnings(symbolServerService.getSymbolServers())
: null); : null);
addStatusTextSupplier(this::getSelectedPdbNoticeText); addStatusTextSupplier(this::getSelectedPdbNoticeText);
addStatusTextSupplier(this::getConfigChangedWarning);
addStatusTextSupplier(this::getAllowRemoteWarning); addStatusTextSupplier(this::getAllowRemoteWarning);
addStatusTextSupplier(this::getFoundCountInfo); addStatusTextSupplier(this::getFoundCountInfo);
@ -386,11 +336,6 @@ public class LoadPdbDialog extends DialogComponentProvider {
// later dialogShow() will be called // later dialogShow() will be called
} }
private void buildSSConfigPanel() {
symbolServerConfigPanel =
new SymbolServerPanel(this::setSymbolServerService, symbolServerInstanceCreatorContext);
}
private void buildSymbolFilePanel() { private void buildSymbolFilePanel() {
// panel will be added in layoutAdvanced() // panel will be added in layoutAdvanced()
symbolFilePanel = new SymbolFilePanel(this::searchForPdbs); symbolFilePanel = new SymbolFilePanel(this::searchForPdbs);
@ -398,7 +343,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
symbolFilePanel.getTable() symbolFilePanel.getTable()
.getSelectionModel() .getSelectionModel()
.addListSelectionListener(e -> updateSelectedRow()); .addListSelectionListener(e -> updateSelectedRow());
symbolFilePanel.addMouseListener(new GMouseListenerAdapter() { symbolFilePanel.getTable().addMouseListener(new GMouseListenerAdapter() {
@Override @Override
public void doubleClickTriggered(MouseEvent e) { public void doubleClickTriggered(MouseEvent e) {
if (loadPdbButton.isEnabled()) { if (loadPdbButton.isEnabled()) {
@ -618,6 +563,17 @@ public class LoadPdbDialog extends DialogComponentProvider {
addCancelButton(); addCancelButton();
setDefaultButton(cancelButton); setDefaultButton(cancelButton);
configButton = new JButton("Config...");
configButton.addActionListener(e -> {
if (ConfigPdbDialog.showSymbolServerConfig()) {
updateSymbolServerServiceInstanceFromPreferences();
updateButtonEnablement();
updateStatusText();
searchForPdbs(false);
}
});
addButton(configButton);
advancedToggleButton = new JToggleButton("Advanced >>"); advancedToggleButton = new JToggleButton("Advanced >>");
advancedToggleButton.addActionListener(e -> toggleAdvancedSearch()); advancedToggleButton.addActionListener(e -> toggleAdvancedSearch());
buttonPanel.add(advancedToggleButton); buttonPanel.add(advancedToggleButton);
@ -625,7 +581,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
private void prepareSelectedSymbolFileAndClose(TaskMonitor monitor) { private void prepareSelectedSymbolFileAndClose(TaskMonitor monitor) {
try { try {
if (selectedSymbolFile != null && symbolServerService != null) { if (selectedSymbolFile != null) {
selectedSymbolFile = selectedSymbolFile =
symbolServerService.getLocalSymbolFileLocation(selectedSymbolFile, monitor); symbolServerService.getLocalSymbolFileLocation(selectedSymbolFile, monitor);
} }
@ -640,17 +596,8 @@ public class LoadPdbDialog extends DialogComponentProvider {
} }
} }
private StatusText getConfigChangedWarning() {
return advancedToggleButton.isSelected() && symbolServerConfigPanel.isConfigChanged()
? new StatusText(
"Symbol Server Search Config Changed. Click \"Save Configuration\" button to save.",
MessageType.INFO, false)
: null;
}
private StatusText getAllowRemoteWarning() { private StatusText getAllowRemoteWarning() {
int remoteSymbolServerCount = int remoteSymbolServerCount = symbolServerService.getRemoteSymbolServerCount();
symbolServerService != null ? symbolServerService.getRemoteSymbolServerCount() : 0;
return lastSearchOptions != null && advancedToggleButton.isSelected() && return lastSearchOptions != null && advancedToggleButton.isSelected() &&
remoteSymbolServerCount != 0 && !lastSearchOptions.contains(FindOption.ALLOW_REMOTE) remoteSymbolServerCount != 0 && !lastSearchOptions.contains(FindOption.ALLOW_REMOTE)
? new StatusText( ? new StatusText(
@ -681,31 +628,21 @@ public class LoadPdbDialog extends DialogComponentProvider {
overridePdbAgeCheckBox.setVisible(isAdvanced); overridePdbAgeCheckBox.setVisible(isAdvanced);
overridePdbPathCheckBox.setVisible(isAdvanced); overridePdbPathCheckBox.setVisible(isAdvanced);
overridePdbUniqueIdCheckBox.setVisible(isAdvanced); overridePdbUniqueIdCheckBox.setVisible(isAdvanced);
setPdbLocationValue(null, null);
if (isAdvanced) { if (isAdvanced) {
if (symbolServerService == null || !symbolServerService.isValid()) {
setSelectedPdbFile(null);
}
layoutAdvanced(); layoutAdvanced();
} }
else { else {
if (selectedSymbolFile != null) {
File localSymbolFile = getLocalSymbolFile(selectedSymbolFile);
if (localSymbolFile != null) {
setPdbLocationValue(selectedSymbolFile, localSymbolFile);
}
}
else {
setSelectedPdbFile(null);
}
layoutSimple(); layoutSimple();
} }
updateStatusText(); updateStatusText();
updateButtonEnablement(); updateButtonEnablement();
updateParserOptionEnablement(false); updateParserOptionEnablement(false);
repack(); if (isAdvanced && !hasShownAdvanced) {
hasShownAdvanced = true;
repack();
}
} }
private void layoutSimple() { private void layoutSimple() {
@ -720,21 +657,17 @@ public class LoadPdbDialog extends DialogComponentProvider {
overrideWorkPanel(panel); overrideWorkPanel(panel);
} }
private void overrideWorkPanel(JComponent workComp) { private void overrideWorkPanel(JComponent newWorkComp) {
if (this.workComp != null && this.workComp.getParent() != null) { if (this.workComp != null && this.workComp.getParent() != null) {
this.workComp.getParent().remove(this.workComp); this.workComp.getParent().remove(this.workComp);
} }
this.workComp = workComp; this.workComp = newWorkComp;
addWorkPanel(workComp); addWorkPanel(newWorkComp);
} }
private void layoutAdvanced() { private void layoutAdvanced() {
Box topPanel = Box.createHorizontalBox();
topPanel.add(programPdbPanel);
topPanel.add(symbolServerConfigPanel);
JPanel mainPanel = new JPanel(new BorderLayout()); JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(topPanel, BorderLayout.NORTH); mainPanel.add(programPdbPanel, BorderLayout.NORTH);
mainPanel.add(symbolFilePanel, BorderLayout.CENTER); mainPanel.add(symbolFilePanel, BorderLayout.CENTER);
mainPanel.add(parserOptionsPanel, BorderLayout.SOUTH); mainPanel.add(parserOptionsPanel, BorderLayout.SOUTH);

View File

@ -117,7 +117,7 @@ class SymbolFilePanel extends JPanel {
private JPanel buildWelcomePanel() { private JPanel buildWelcomePanel() {
welcomePanel = new JPanel(); welcomePanel = new JPanel();
welcomePanel.add(new GHtmlLabel( welcomePanel.add(new GHtmlLabel(
"<html><br><center><font color=red>Local Symbol Storage location must be set first!")); "<html><br><center><font color=red>Configuration must be set first!"));
welcomePanel.setPreferredSize(tablePanel.getPreferredSize()); welcomePanel.setPreferredSize(tablePanel.getPreferredSize());
return welcomePanel; return welcomePanel;

View File

@ -52,7 +52,7 @@ import utilities.util.FileUtilities;
class SymbolServerPanel extends JPanel { class SymbolServerPanel extends JPanel {
private static final String MS_SYMBOLSERVER_ENVVAR = "_NT_SYMBOL_PATH"; private static final String MS_SYMBOLSERVER_ENVVAR = "_NT_SYMBOL_PATH";
private List<WellKnownSymbolServerLocation> knownSymbolServers = private static List<WellKnownSymbolServerLocation> knownSymbolServers =
WellKnownSymbolServerLocation.loadAll(); WellKnownSymbolServerLocation.loadAll();
private SymbolStore localSymbolStore; private SymbolStore localSymbolStore;
@ -297,23 +297,6 @@ class SymbolServerPanel extends JPanel {
updateLayout(hasLocalSymbolStore); updateLayout(hasLocalSymbolStore);
} }
StatusText getSymbolServerWarnings() {
Map<String, String> warningsByLocation = new HashMap<>();
for (WellKnownSymbolServerLocation ssloc : knownSymbolServers) {
if (ssloc.getWarning() != null && !ssloc.getWarning().isBlank()) {
warningsByLocation.put(ssloc.getLocation(), ssloc.getWarning());
}
}
String warning = tableModel.getDataSource()
.stream()
.map(row -> warningsByLocation.get(row.getSymbolServer().getName()))
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.joining("<br>\n"));
return !warning.isEmpty() ? new StatusText(warning, MessageType.WARNING, false) : null;
}
private void setSymbolStorageLocation(File symbolStorageDir, boolean allowGUIPrompt) { private void setSymbolStorageLocation(File symbolStorageDir, boolean allowGUIPrompt) {
if (symbolStorageDir == null) { if (symbolStorageDir == null) {
return; return;
@ -601,5 +584,22 @@ class SymbolServerPanel extends JPanel {
return button; return button;
} }
static StatusText getSymbolServerWarnings(List<SymbolServer> symbolServers) {
Map<String, String> warningsByLocation = new HashMap<>();
for (WellKnownSymbolServerLocation ssloc : knownSymbolServers) {
if (ssloc.getWarning() != null && !ssloc.getWarning().isBlank()) {
warningsByLocation.put(ssloc.getLocation(), ssloc.getWarning());
}
}
String warning = symbolServers
.stream()
.map(symbolServer -> warningsByLocation.get(symbolServer.getName()))
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.joining("<br>\n"));
return !warning.isEmpty() ? new StatusText(warning, MessageType.WARNING, false) : null;
}
} }

View File

@ -69,11 +69,30 @@ public class PdbScreenShots extends GhidraScreenShotGenerator {
ConfigPdbDialog configPdbDialog = new ConfigPdbDialog(); ConfigPdbDialog configPdbDialog = new ConfigPdbDialog();
showDialogWithoutBlocking(tool, configPdbDialog); showDialogWithoutBlocking(tool, configPdbDialog);
waitForSwing(); waitForSwing();
captureDialog(ConfigPdbDialog.class); captureDialog(ConfigPdbDialog.class, 410, 280);
} }
@Test @Test
public void testLoadPdb_Initial_Screenshot() throws IOException { public void testSymbolServerConfig_Configured() throws IOException {
File localSymbolStore1Root = new File(temporaryDir, "symbols");
LocalSymbolStore.create(localSymbolStore1Root, 1);
LocalSymbolStore localSymbolStore1 = new LocalSymbolStore(localSymbolStore1Root);
SameDirSymbolStore sameDirSymbolStore = new SameDirSymbolStore(null);
List<SymbolServer> symbolServers = List.of(sameDirSymbolStore,
new HttpSymbolServer(URI.create("https://msdl.microsoft.com/download/symbols/")));
SymbolServerService symbolServerService =
new SymbolServerService(localSymbolStore1, symbolServers);
PdbPlugin.saveSymbolServerServiceConfig(symbolServerService);
ConfigPdbDialog configPdbDialog = new ConfigPdbDialog();
configPdbDialog.setSymbolServerService("/home/user/symbols", symbolServers);
showDialogWithoutBlocking(tool, configPdbDialog);
waitForSwing();
captureDialog(ConfigPdbDialog.class, 410, 280);
}
@Test
public void testLoadPdb_Initial_Screenshot() {
LoadPdbDialog loadPdbDialog = new LoadPdbDialog(program); LoadPdbDialog loadPdbDialog = new LoadPdbDialog(program);
showDialogWithoutBlocking(tool, loadPdbDialog); showDialogWithoutBlocking(tool, loadPdbDialog);
captureDialog(loadPdbDialog); captureDialog(loadPdbDialog);
@ -84,32 +103,30 @@ public class PdbScreenShots extends GhidraScreenShotGenerator {
public void testSymbolServerConfig_AddButtonMenu() throws IOException { public void testSymbolServerConfig_AddButtonMenu() throws IOException {
File localSymbolStore1Root = new File(temporaryDir, "symbols"); File localSymbolStore1Root = new File(temporaryDir, "symbols");
LocalSymbolStore.create(localSymbolStore1Root, 1); LocalSymbolStore.create(localSymbolStore1Root, 1);
LocalSymbolStore localSymbolStore1 = LocalSymbolStore localSymbolStore1 = new LocalSymbolStore(localSymbolStore1Root);
new LocalSymbolStoreWithFakePath(localSymbolStore1Root, "/home/user/symbols");
SymbolServerService symbolServerService = SymbolServerService symbolServerService =
new SymbolServerService(localSymbolStore1, List.of()); new SymbolServerService(localSymbolStore1, List.of());
PdbPlugin.saveSymbolServerServiceConfig(symbolServerService); PdbPlugin.saveSymbolServerServiceConfig(symbolServerService);
LoadPdbDialog choosePdbDialog = new LoadPdbDialog(program); ConfigPdbDialog configPdbDialog = new ConfigPdbDialog();
showDialogWithoutBlocking(tool, choosePdbDialog); showDialogWithoutBlocking(tool, configPdbDialog);
waitForSwing(); waitForSwing();
pressButtonByText(choosePdbDialog, "Advanced >>");
runSwing(() -> { runSwing(() -> {
choosePdbDialog.pushAddLocationBution(); configPdbDialog.pushAddLocationButton();
}); });
waitForSwing(); waitForSwing();
captureMenu(); captureMenu();
} }
@Test @Test
public void testLoadPdb_Advanced_NeedsConfig() throws IOException { public void testLoadPdb_Advanced_NeedsConfig() {
PdbPlugin.saveSymbolServerServiceConfig(null); PdbPlugin.saveSymbolServerServiceConfig(null);
LoadPdbDialog choosePdbDialog = new LoadPdbDialog(program); LoadPdbDialog choosePdbDialog = new LoadPdbDialog(program);
showDialogWithoutBlocking(tool, choosePdbDialog); showDialogWithoutBlocking(tool, choosePdbDialog);
waitForSwing(); waitForSwing();
pressButtonByText(choosePdbDialog, "Advanced >>"); pressButtonByText(choosePdbDialog, "Advanced >>");
waitForSwing(); waitForSwing();
captureDialog(LoadPdbDialog.class); captureDialog(LoadPdbDialog.class, 600, 500);
pressButtonByText(choosePdbDialog, "Cancel"); pressButtonByText(choosePdbDialog, "Cancel");
} }
@ -140,19 +157,15 @@ public class PdbScreenShots extends GhidraScreenShotGenerator {
new SymbolFileLocation("HelloWorld.pdb/" + GUID1_STR + "2/HelloWorld.pdb", new SymbolFileLocation("HelloWorld.pdb/" + GUID1_STR + "2/HelloWorld.pdb",
localSymbolStore1, SymbolFileInfo.fromValues("HelloWorld.pdb", GUID1_STR, 2)), localSymbolStore1, SymbolFileInfo.fromValues("HelloWorld.pdb", GUID1_STR, 2)),
new SymbolFileLocation("HelloWorld.pdb", sameDirSymbolStoreWithFakePath, new SymbolFileLocation("HelloWorld.pdb", sameDirSymbolStoreWithFakePath,
SymbolFileInfo.fromValues("HelloWorld.pdb", GUID1_STR, 1)), SymbolFileInfo.fromValues("HelloWorld.pdb", GUID1_STR, 1)));
new SymbolFileLocation("HelloWorld_ver2.pdb", sameDirSymbolStoreWithFakePath,
SymbolFileInfo.fromValues("HelloWorld.pdb", GUID1_STR, 2)));
Set<FindOption> findOptions = FindOption.of(FindOption.ALLOW_REMOTE, FindOption.ANY_AGE); Set<FindOption> findOptions = FindOption.of(FindOption.ALLOW_REMOTE, FindOption.ANY_AGE);
runSwing(() -> { runSwing(() -> {
loadPdbDialog.setSearchOptions(findOptions); loadPdbDialog.setSearchOptions(findOptions);
loadPdbDialog.setSymbolServers(symbolServers);
loadPdbDialog.setSymbolStorageDirectoryTextOnly("/home/user/symbols");
loadPdbDialog.setSearchResults(symbolFileLocations, findOptions); loadPdbDialog.setSearchResults(symbolFileLocations, findOptions);
loadPdbDialog.selectRowByLocation(symbolFileLocations.get(0)); loadPdbDialog.selectRowByLocation(symbolFileLocations.get(0));
}); });
waitForSwing(); waitForSwing();
captureDialog(LoadPdbDialog.class); captureDialog(LoadPdbDialog.class, 600, 600);
pressButtonByText(loadPdbDialog, "Cancel"); pressButtonByText(loadPdbDialog, "Cancel");
} }