diff --git a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/LoadPDBNew.html b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/LoadPDBNew.html
index 9da6f81bd7..f60a94d9f5 100644
--- a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/LoadPDBNew.html
+++ b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/LoadPDBNew.html
@@ -184,7 +184,7 @@
change the search criteria, they are not persisted to your program's metadata.
- PDB Name Checkbox - this checkbox allows entering a custom value for the desired PDB file name.
- - PDB Unique Id Checkbox - this checkbox allows entering a custom GUID or ID value.
+ - PDB Unique ID Checkbox - this checkbox allows entering a custom GUID or ID value.
- PDB Age Checkbox - this checkbox allows entering a custom age value.
After changing a search option, you will need to perform another search to use the new options.
@@ -198,7 +198,12 @@
- Universal - Platform-independent PDB analyzer (No PDB.XML support).
- MSDIA - Legacy PDB Analyzer. Requires MS DIA-SDK for raw PDB processing (Windows only), or preprocessed PDB.XML file.
- - Control - Process All, Data Types Only, Public Symbols Only.
+
+ Control (Universal only) - Controls how the PDB is applied to the Program
+
+ - Process All: Applies Data Types and Public, Global, and Module Symbols.
+ - Data Types Only: Applies Data Types and Typedefs found in the Global Symbols.
+ - Public Symbols Only: Applies only Public symbols to the program. It ignores Global symbols and Module symbols.
diff --git a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png
index 5815e5b51a..949d45f8ba 100644
Binary files a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png and b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_NeedsConfig.png differ
diff --git a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png
index 2768ba23e4..74072b1047 100644
Binary files a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png and b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Advanced_Screenshot.png differ
diff --git a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png
index b9b5b155b0..3c89aaaf55 100644
Binary files a/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png and b/Ghidra/Features/PDB/src/main/help/help/topics/Pdb/images/LoadPdb_Initial_Screenshot.png differ
diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/LocalSymbolStore.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/LocalSymbolStore.java
index 9d991e0112..159aa9c1e4 100644
--- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/LocalSymbolStore.java
+++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/LocalSymbolStore.java
@@ -15,9 +15,8 @@
*/
package pdb.symbolserver;
-import java.util.*;
-
import java.io.*;
+import java.util.*;
import org.apache.commons.io.FilenameUtils;
@@ -33,6 +32,8 @@ import utilities.util.FileUtilities;
*/
public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStore {
private static final String ADMIN_DIRNAME = "000admin"; // per MS custom
+ private static final Set ALREADY_WARNED_ABOUT =
+ Collections.synchronizedSet(new HashSet<>());
/**
* Predicate that returns true if the location string is a LocalSymbolStore path
@@ -152,9 +153,49 @@ public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStor
if (pingMeFile.isFile() && adminDir.isDirectory()) {
return super.detectStorageLevel(monitor);
}
+ return doHackyStorageLevelDetection(monitor);
+ }
+
+ private int doHackyStorageLevelDetection(TaskMonitor monitor) {
+ // dig through the files in the rootDir and see if there is anything
+ // that looks like a level1 or level2 directory.
+ if (containsPdbSymbolDirsWithFiles(rootDir)) {
+ if (ALREADY_WARNED_ABOUT.add(rootDir)) {
+ Msg.warn(this,
+ "Symbol directory missing control files, guessing storage scheme as level 1: " +
+ rootDir);
+ }
+ return 1;
+ }
+ File[] possibleLevel2SymbolDirs =
+ list(rootDir, f -> f.isDirectory() && f.getName().length() == 2);
+ for (File dir : possibleLevel2SymbolDirs) {
+ if (containsPdbSymbolDirsWithFiles(dir)) {
+ if (ALREADY_WARNED_ABOUT.add(rootDir)) {
+ Msg.warn(this,
+ "Symbol directory missing control files, guessing storage scheme as level 2: " +
+ rootDir);
+ }
+ return 2;
+ }
+ }
return 0;
}
+ private boolean containsPdbSymbolDirsWithFiles(File testDir) {
+ File[] possibleLevel1SymbolDirs =
+ list(testDir, f -> f.isDirectory() && f.getName().toLowerCase().endsWith(".pdb"));
+ for (File dir : possibleLevel1SymbolDirs) {
+ if (list(dir, f -> f.isDirectory() &&
+ SymbolFileInfo.fromSubdirectoryPath("doesntmatter", f.getName()) != null &&
+ new File(f, dir.getName()).isFile()).length > 0) {
+ Msg.debug(this, "Detected symbol file directory: " + dir);
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public List find(SymbolFileInfo symbolFileInfo, Set options,
TaskMonitor monitor) {
@@ -296,6 +337,12 @@ public class LocalSymbolStore extends AbstractSymbolServer implements SymbolStor
Msg.info(this, logPrefix() + ": File already exists: " + destinationFile);
return relativeDestinationFilename;
}
+ if (destinationFile.isDirectory()) {
+ Msg.error(this, logPrefix() + ": File's location already exists and is a directory: " +
+ destinationFile);
+ Msg.error(this, logPrefix() + ": Possible symbol storage directory misconfiguration!");
+ return relativeDestinationFilename;
+ }
File destinationFileTmp = new File(rootDir, relativeDestinationFilename + ".tmp");
destinationFileTmp.delete();
diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java
index ee0c1a001b..97f1d99638 100644
--- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java
+++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/LoadPdbDialog.java
@@ -331,7 +331,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
}
SymbolFileInfo symbolFileInfo = getCurrentSymbolFileInfo();
if (symbolFileInfo == null) {
- Msg.showWarn(this, null, "Bad PDB GUID/Id",
+ Msg.showWarn(this, null, "Bad PDB GUID/ID",
"Invalid PDB GUID / UID value: " + pdbUniqueIdTextField.getText());
return;
}
@@ -441,14 +441,14 @@ public class LoadPdbDialog extends DialogComponentProvider {
pdbUniqueIdTextField = new BetterNonEditableTextField(36);
pdbUniqueIdTextField.setEditable(false);
pdbUniqueIdTextField.setToolTipText(
- "PDB GUID - either 36 or 32 hexadecimal characters:
" +
- " '012345678-0123-0123-0123-0123456789ABC' or '0123456780123012301230123456789ABC', or
" +
- "PDB Signature Id - 8 hexadecimal character Id:
" +
+ "PDB GUID - 32 hexadecimal characters:
" +
+ " '012345678-0123-0123-0123-0123456789ABC' (with or without dashes) or
" +
+ "PDB Signature ID - 8 hexadecimal characters:
" +
" '11223344'");
overridePdbUniqueIdCheckBox = new GCheckBox();
overridePdbUniqueIdCheckBox.setVisible(false);
- overridePdbUniqueIdCheckBox.setToolTipText("Override PDB unique id (when searching).");
+ overridePdbUniqueIdCheckBox.setToolTipText("Override PDB Unique ID (when searching).");
overridePdbUniqueIdCheckBox.addItemListener(e -> {
pdbUniqueIdTextField.setEditable(overridePdbUniqueIdCheckBox.isSelected());
if (overridePdbUniqueIdCheckBox.isSelected()) {
@@ -494,7 +494,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
join(null, new GLabel("PDB Name:", SwingConstants.RIGHT), overridePdbPathCheckBox));
programPdbPanel.add(pdbPathTextField);
- programPdbPanel.add(join(null, new GLabel("PDB Unique Id:", SwingConstants.RIGHT),
+ programPdbPanel.add(join(null, new GLabel("PDB Unique ID:", SwingConstants.RIGHT),
overridePdbUniqueIdCheckBox));
programPdbPanel.add(pdbUniqueIdTextField);
@@ -574,6 +574,7 @@ public class LoadPdbDialog extends DialogComponentProvider {
radioButtons.add(msdiaParserButton);
applicatorControlCombo = new GComboBox<>(PdbApplicatorControl.values());
+ applicatorControlCombo.setToolTipText("Selects which subsets of information to parse.");
applicatorControlCombo.setSelectedItem(PdbApplicatorControl.ALL);
parserOptionsPanel = new JPanel(new PairLayout(5, 5));
diff --git a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java
index 17d932adf2..985ffc1da6 100644
--- a/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java
+++ b/Ghidra/Features/PDB/src/main/java/pdb/symbolserver/ui/SymbolServerPanel.java
@@ -266,6 +266,8 @@ class SymbolServerPanel extends JPanel {
private JPanel buildSymbolStorageLocationPanel() {
symbolStorageLocationTextField = new HintTextField(" Required ");
symbolStorageLocationTextField.setEditable(false);
+ symbolStorageLocationTextField
+ .setToolTipText("User-specified directory where PDB files are stored. Required.");
chooseSymbolStorageLocationButton =
ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE);
@@ -273,8 +275,8 @@ class SymbolServerPanel extends JPanel {
symbolStorageLocationPanel = new JPanel(new PairLayout(5, 5));
GLabel symbolStorageLocLabel = new GLabel("Local Symbol Storage:", SwingConstants.RIGHT);
- symbolStorageLocLabel
- .setToolTipText("User-specified directory where PDB files are stored. Required.");
+ symbolStorageLocLabel.setToolTipText(symbolStorageLocationTextField.getToolTipText());
+
symbolStorageLocationPanel.add(symbolStorageLocLabel);
symbolStorageLocationPanel.add(LoadPdbDialog.join(null, symbolStorageLocationTextField,
chooseSymbolStorageLocationButton));