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.

After changing a search option, you will need to perform another search to use the new options.

@@ -198,7 +198,12 @@ +

Control (Universal only) - Controls how the PDB is applied to the Program

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