diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimes.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimes.java index e1f08c4352..b32cff7388 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimes.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimes.java @@ -19,6 +19,7 @@ import java.util.*; import ghidra.framework.options.*; import ghidra.program.model.listing.Program; +import ghidra.util.StringUtilities; /** * StoredAnalyzerTimes provides a custom option container for @@ -29,6 +30,7 @@ public class StoredAnalyzerTimes implements CustomOption { public static final String OPTIONS_LIST = Program.PROGRAM_INFO + ".Analysis Times"; public static final String OPTION_NAME = "Times"; + // all times maintained in milliseconds private Map taskTimes = new HashMap<>(); private Long totalTime; private String[] names; @@ -80,7 +82,7 @@ public class StoredAnalyzerTimes implements CustomOption { /** * Add the specified time corresponding to the specified analysis taskName * @param taskName analysis task name - * @param t time increment + * @param t time increment in milliseconds */ public void addTime(String taskName, long t) { long cumulativeTime = taskTimes.getOrDefault(taskName, 0L) + t; @@ -92,7 +94,7 @@ public class StoredAnalyzerTimes implements CustomOption { /** * Get the accumulated time for the specified analysis taskName * @param taskName analysis task name - * @return accumulated task time or null if entry not found + * @return accumulated task time in milliseconds or null if entry not found */ public Long getTime(String taskName) { return taskTimes.get(taskName); @@ -100,7 +102,8 @@ public class StoredAnalyzerTimes implements CustomOption { /** * Get the total accumulated task time for all task entries - * @return total accumuated task time + * in milliseconds + * @return total accumuated task time in milliseconds */ public long getTotalTime() { if (totalTime == null) { @@ -113,6 +116,11 @@ public class StoredAnalyzerTimes implements CustomOption { return totalTime; } + @Override + public String toString() { + return formatTimeMS(getTotalTime()) + " seconds"; + } + /** * Get all task names for which time entries exist * @return array of task names @@ -167,4 +175,11 @@ public class StoredAnalyzerTimes implements CustomOption { options.putObject(StoredAnalyzerTimes.OPTION_NAME, times); } + static String formatTimeMS(long timeMS) { + String str = Long.toUnsignedString(timeMS / 1000L); + str += "."; + str += StringUtilities.pad(Long.toUnsignedString(timeMS % 1000L), '0', 3); + return str; + } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java index b8ccc8142d..488fa252c7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/StoredAnalyzerTimesPropertyEditor.java @@ -22,7 +22,6 @@ import javax.swing.*; import docking.widgets.label.GDLabel; import ghidra.framework.options.CustomOptionsEditor; -import ghidra.util.StringUtilities; import ghidra.util.layout.PairLayout; /** @@ -102,7 +101,7 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport continue; } - JTextField valueField = new JTextField(formatTimeMS(timeMS)); + JTextField valueField = new JTextField(StoredAnalyzerTimes.formatTimeMS(timeMS)); valueField.setEditable(false); valueField.setHorizontalAlignment(SwingConstants.RIGHT); panel.add(valueField); @@ -112,7 +111,8 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport label.setFont(label.getFont().deriveFont(Font.BOLD)); panel.add(label); - JTextField valueField = new JTextField(formatTimeMS(times.getTotalTime())); + JTextField valueField = + new JTextField(StoredAnalyzerTimes.formatTimeMS(times.getTotalTime())); valueField.setEditable(false); valueField.setHorizontalAlignment(SwingConstants.RIGHT); valueField.setBorder(BorderFactory.createLineBorder(Color.black, 2)); @@ -121,11 +121,6 @@ public class StoredAnalyzerTimesPropertyEditor extends PropertyEditorSupport return panel; } - private String formatTimeMS(long timeMS) { - String str = Long.toUnsignedString(timeMS / 1000L); - str += "."; - str += StringUtilities.pad(Long.toUnsignedString(timeMS % 1000L), '0', 3); - return str; - } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java index 0b3d15d481..b5ac32c59c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/AbstractPeDebugLoader.java @@ -121,7 +121,7 @@ abstract class AbstractPeDebugLoader extends AbstractLibrarySupportLoader { proplist.setString(PdbParserConstants.PDB_VERSION, Conv.toString(magic)); proplist.setString(PdbParserConstants.PDB_SIGNATURE, Conv.toHexString(sig)); - proplist.setString(PdbParserConstants.PDB_AGE, Conv.toHexString(age)); + proplist.setString(PdbParserConstants.PDB_AGE, Integer.toHexString(age)); proplist.setString(PdbParserConstants.PDB_FILE, name); /* DebugDirectory dd = dcv.getDebugDirectory(); @@ -147,7 +147,7 @@ abstract class AbstractPeDebugLoader extends AbstractLibrarySupportLoader { proplist.setString(PdbParserConstants.PDB_VERSION, Conv.toString(magic)); proplist.setString(PdbParserConstants.PDB_GUID, guid.toString()); - proplist.setString(PdbParserConstants.PDB_AGE, Conv.toHexString(age)); + proplist.setString(PdbParserConstants.PDB_AGE, Integer.toHexString(age)); proplist.setString(PdbParserConstants.PDB_FILE, name); /* DebugDirectory dd = dcv.getDebugDirectory(); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbAnalyzer.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbAnalyzer.java index 606df12f48..04a3547573 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbAnalyzer.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbAnalyzer.java @@ -24,6 +24,7 @@ import ghidra.app.util.bin.format.pdb.*; import ghidra.app.util.importer.MessageLog; import ghidra.app.util.opinion.PeLoader; import ghidra.app.util.pdb.PdbLocator; +import ghidra.framework.options.OptionType; import ghidra.framework.options.Options; import ghidra.framework.preferences.Preferences; import ghidra.program.model.address.AddressSetView; @@ -48,10 +49,8 @@ public class PdbAnalyzer extends AbstractAnalyzer { private static final String SYMBOLPATH_OPTION_NAME = "Symbol Repository Path"; private static final String SYMBOLPATH_OPTION_DESCRIPTION = "Directory path to root of Microsoft Symbol Repository Directory"; - private static final String SYMBOLPATH_OPTION_DEFAULT_VALUE = - PdbLocator.DEFAULT_SYMBOLS_DIR.getAbsolutePath(); - private String symbolsRepositoryPath = SYMBOLPATH_OPTION_DEFAULT_VALUE; + private File symbolsRepositoryDir = PdbLocator.DEFAULT_SYMBOLS_DIR; //============================================================================================== // Include the PE-Header-Specified PDB path for searching for appropriate PDB file. @@ -62,6 +61,9 @@ public class PdbAnalyzer extends AbstractAnalyzer { private boolean includePeSpecifiedPdbPath = false; + // only try once per transaction due to extensive error logging which may get duplicated + private long lastTransactionId = -1; + //============================================================================================== public PdbAnalyzer() { super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER); @@ -73,7 +75,24 @@ public class PdbAnalyzer extends AbstractAnalyzer { @Override public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) { + // Only run once per transaction - avoid message duplication + long txId = program.getCurrentTransaction().getID(); + if (txId == lastTransactionId) { + return false; + } + lastTransactionId = txId; + + // Only run if restricted set corresponds to entire program + if (!set.contains(program.getMemory())) { + return false; + } + if (PdbParser.isAlreadyLoaded(program)) { + if (!PdbUniversalAnalyzer.isEnabled(program)) { // yield to other analyzer complaining + Msg.info(this, "Skipping PDB analysis since it has previouslu run."); + Msg.info(this, ">> Clear 'PDB Loaded' program property or use Load PDB action if " + + "additional PDB processing required."); + } return true; } @@ -105,7 +124,7 @@ public class PdbAnalyzer extends AbstractAnalyzer { try { - pdb = PdbParser.findPDB(program, includePeSpecifiedPdbPath, symbolsRepositoryPath); + pdb = PdbParser.findPDB(program, includePeSpecifiedPdbPath, symbolsRepositoryDir); if (pdb == null) { @@ -191,18 +210,15 @@ public class PdbAnalyzer extends AbstractAnalyzer { String pdbStorageLocation = Preferences.getProperty(PdbParser.PDB_STORAGE_PROPERTY, null, true); + if (pdbStorageLocation != null) { File pdbDirectory = new File(pdbStorageLocation); - if (pdbDirectory.isDirectory()) { - options.registerOption(SYMBOLPATH_OPTION_NAME, pdbStorageLocation, null, - SYMBOLPATH_OPTION_DESCRIPTION); + symbolsRepositoryDir = pdbDirectory; } } - else { - options.registerOption(SYMBOLPATH_OPTION_NAME, SYMBOLPATH_OPTION_DEFAULT_VALUE, null, - SYMBOLPATH_OPTION_DESCRIPTION); - } + options.registerOption(SYMBOLPATH_OPTION_NAME, OptionType.FILE_TYPE, symbolsRepositoryDir, + null, SYMBOLPATH_OPTION_DESCRIPTION); options.registerOption(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath, null, OPTION_DESCRIPTION_INCLUDE_PE_PDB_PATH); @@ -210,19 +226,16 @@ public class PdbAnalyzer extends AbstractAnalyzer { @Override public void optionsChanged(Options options, Program program) { - String symbolPath = - options.getString(SYMBOLPATH_OPTION_NAME, SYMBOLPATH_OPTION_DEFAULT_VALUE); - setSymbolsRepositoryPath(symbolPath); + + symbolsRepositoryDir = + options.getFile(SYMBOLPATH_OPTION_NAME, PdbLocator.DEFAULT_SYMBOLS_DIR); - Preferences.setProperty(PdbParser.PDB_STORAGE_PROPERTY, symbolPath); + Preferences.setProperty(PdbParser.PDB_STORAGE_PROPERTY, + symbolsRepositoryDir != null ? symbolsRepositoryDir.getAbsolutePath() : null); Preferences.store(); includePeSpecifiedPdbPath = options.getBoolean(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath); } - public void setSymbolsRepositoryPath(String symbolPath) { - symbolsRepositoryPath = symbolPath; - } - } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java index f708826374..71448bcefc 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java @@ -199,6 +199,9 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer { private PdbReaderOptions pdbReaderOptions; private PdbApplicatorOptions pdbApplicatorOptions; + // only try once per transaction due to extensive error logging which may get duplicated + private long lastTransactionId = -1; + //============================================================================================== //============================================================================================== public PdbUniversalAnalyzer() { @@ -221,6 +224,18 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer { public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) throws CancelledException { + // Only run once per transaction - avoid message duplication + long txId = program.getCurrentTransaction().getID(); + if (txId == lastTransactionId) { + return false; + } + lastTransactionId = txId; + + // Only run if restricted set corresponds to entire program + if (!set.contains(program.getMemory())) { + return false; + } + // NOTE: Legacy PDB Analyzer currently yields to this analyzer if both are enabled // if (PdbAnalyzer.isEnabled(program)) { // log.appendMsg(getName(), @@ -246,9 +261,10 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer { Msg.info(this, ">> Clear 'PDB Loaded' program property or use Load PDB action if " + "additional PDB processing required."); + return true; } - if (programAttributes.isPdbLoaded() || - failMissingFilename(programAttributes, log) || + + if (failMissingFilename(programAttributes, log) || failMissingAttributes(programAttributes, log)) { return true; } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParser.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParser.java index 0d0349f3a7..7e4e66dd5b 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParser.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb/PdbParser.java @@ -29,6 +29,7 @@ import ghidra.app.util.NamespaceUtils; import ghidra.app.util.SymbolPath; import ghidra.app.util.importer.LibrarySearchPathManager; import ghidra.app.util.importer.MessageLog; +import ghidra.app.util.pdb.PdbLocator; import ghidra.app.util.pdb.PdbProgramAttributes; import ghidra.framework.*; import ghidra.framework.options.Options; @@ -53,7 +54,6 @@ public class PdbParser { private static final String README_FILENAME = Application.getInstallationDirectory() + "\\docs\\README_PDB.html"; - public final static File SPECIAL_PDB_LOCATION = new File("C:/WINDOWS/Symbols"); public final static String PDB_STORAGE_PROPERTY = "PDB Storage Directory"; static final String STRUCTURE_KIND = "Structure"; @@ -1070,12 +1070,12 @@ public class PdbParser { * * @param program program for which to find a matching PDB * @param includePeSpecifiedPdbPath to also check the PE-header-specified PDB path - * @param symbolsRepositoryPath location where downloaded symbols are stored + * @param symbolsRepositoryDir location where downloaded symbols are stored * @return matching PDB for program, or null */ public static File findPDB(Program program, boolean includePeSpecifiedPdbPath, - String symbolsRepositoryPath) { - return findPDB(getPdbAttributes(program), includePeSpecifiedPdbPath, symbolsRepositoryPath, + File symbolsRepositoryDir) { + return findPDB(getPdbAttributes(program), includePeSpecifiedPdbPath, symbolsRepositoryDir, null); } @@ -1085,12 +1085,12 @@ public class PdbParser { * * @param pdbAttributes PDB attributes associated with the program * @param includePeSpecifiedPdbPath to also check the PE-header-specified PDB path - * @param symbolsRepositoryPath location of the local symbols repository (can be null) + * @param symbolsRepositoryDir location of the local symbols repository (can be null) * @param fileType type of file to search for (can be null) * @return matching PDB file (or null, if not found) */ public static File findPDB(PdbProgramAttributes pdbAttributes, - boolean includePeSpecifiedPdbPath, String symbolsRepositoryPath, PdbFileType fileType) { + boolean includePeSpecifiedPdbPath, File symbolsRepositoryDir, PdbFileType fileType) { // Store potential names of PDB files and potential locations of those files, // so that all possible combinations can be searched. @@ -1107,7 +1107,7 @@ public class PdbParser { guidSubdirPaths.add(File.separator + potentialName + File.separator + guidAgeString); } - return checkPathsForPdb(symbolsRepositoryPath, guidSubdirPaths, potentialPdbNames, fileType, + return checkPathsForPdb(symbolsRepositoryDir, guidSubdirPaths, potentialPdbNames, fileType, pdbAttributes, includePeSpecifiedPdbPath); } @@ -1128,7 +1128,7 @@ public class PdbParser { * symbolsRepositoryPath, then look for .pdb.xml file, then .pdb.xml file in other * directories. * - * @param symbolsRepositoryPath location of the local symbols repository (can be null) + * @param symbolsRepositoryDir location of the local symbols repository (can be null) * @param guidSubdirPaths subdirectory paths (that include the PDB's GUID) that may contain * a matching PDB * @param potentialPdbNames all potential filenames for the PDB file(s) that match the program @@ -1136,13 +1136,13 @@ public class PdbParser { * @param pdbAttributes PDB attributes associated with the program * @return matching PDB file, if found (else null) */ - private static File checkPathsForPdb(String symbolsRepositoryPath, Set guidSubdirPaths, + private static File checkPathsForPdb(File symbolsRepositoryDir, Set guidSubdirPaths, List potentialPdbNames, PdbFileType fileType, PdbProgramAttributes pdbAttributes, boolean includePeSpecifiedPdbPath) { File foundPdb = null; Set symbolsRepoPaths = - getSymbolsRepositoryPaths(symbolsRepositoryPath, guidSubdirPaths); + getSymbolsRepositoryPaths(symbolsRepositoryDir, guidSubdirPaths); Set predefinedPaths = getPredefinedPaths(guidSubdirPaths, pdbAttributes, includePeSpecifiedPdbPath); boolean fileTypeSpecified = (fileType != null); @@ -1169,7 +1169,7 @@ public class PdbParser { checkForXml = onWindows ? false : true; // Start by searching in symbolsRepositoryPath, if available. - if (symbolsRepositoryPath != null) { + if (!symbolsRepoPaths.isEmpty()) { foundPdb = checkSpecificPathsForPdb(symbolsRepoPaths, potentialPdbNames, checkForXml); } @@ -1195,26 +1195,23 @@ public class PdbParser { return foundPdb; } - private static Set getSymbolsRepositoryPaths(String symbolsRepositoryPath, + private static Set getSymbolsRepositoryPaths(File symbolsRepositoryDir, Set guidSubdirPaths) { Set symbolsRepoPaths = new LinkedHashSet<>(); // Collect sub-directories of the symbol repository that exist - File symRepoFile; - - if (symbolsRepositoryPath != null && - (symRepoFile = new File(symbolsRepositoryPath)).isDirectory()) { + if (symbolsRepositoryDir != null && symbolsRepositoryDir.isDirectory()) { for (String guidSubdir : guidSubdirPaths) { - File testDir = new File(symRepoFile, guidSubdir); + File testDir = new File(symbolsRepositoryDir, guidSubdir); if (testDir.isDirectory()) { symbolsRepoPaths.add(testDir); } } // Check outer folder last - symbolsRepoPaths.add(symRepoFile); + symbolsRepoPaths.add(symbolsRepositoryDir); } return symbolsRepoPaths; @@ -1227,7 +1224,8 @@ public class PdbParser { Set predefinedPaths = new LinkedHashSet<>(); getPathsFromAttributes(pdbAttributes, includePeSpecifiedPdbPath, predefinedPaths); - getWindowsPaths(guidSubdirPaths, predefinedPaths); + getSymbolPaths(PdbLocator.DEFAULT_SYMBOLS_DIR, guidSubdirPaths, predefinedPaths); + getSymbolPaths(PdbLocator.WINDOWS_SYMBOLS_DIR, guidSubdirPaths, predefinedPaths); getLibraryPaths(guidSubdirPaths, predefinedPaths); return predefinedPaths; @@ -1253,19 +1251,21 @@ public class PdbParser { } } - private static void getWindowsPaths(Set guidSubdirPaths, Set predefinedPaths) { + private static void getSymbolPaths(File symbolsDir, Set guidSubdirPaths, + Set predefinedPaths) { // Don't have to call .exists(), since .isDirectory() does that already - if (onWindows && SPECIAL_PDB_LOCATION.isDirectory()) { - predefinedPaths.add(SPECIAL_PDB_LOCATION); + if (symbolsDir == null || !symbolsDir.isDirectory()) { + return; + } + predefinedPaths.add(symbolsDir); - // Check alternate locations - String specialPdbPath = SPECIAL_PDB_LOCATION.getAbsolutePath(); + // Check alternate locations + String specialPdbPath = symbolsDir.getAbsolutePath(); - for (String guidSubdir : guidSubdirPaths) { - File testDir = new File(specialPdbPath + guidSubdir); - if (testDir.isDirectory()) { - predefinedPaths.add(testDir); - } + for (String guidSubdir : guidSubdirPaths) { + File testDir = new File(specialPdbPath + guidSubdir); + if (testDir.isDirectory()) { + predefinedPaths.add(testDir); } } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbLocator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbLocator.java index da70c57f41..54433e81bc 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbLocator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbLocator.java @@ -76,15 +76,17 @@ public class PdbLocator { private static final File USER_HOME = new File(System.getProperty("user.home")); public static final File DEFAULT_SYMBOLS_DIR = onWindows ? new File("C:\\Symbols") : new File(USER_HOME, "Symbols"); + public final static File WINDOWS_SYMBOLS_DIR = + onWindows ? new File("C:/WINDOWS/Symbols") : null; - private File symbolsRepositoryPath; + private File symbolsRepositoryDir; /** * Only holds identifies in PDBs up until a matching one was found--nothing beyond that. */ private Map identifiersByFilePath = new HashMap<>(); - public PdbLocator(File symbolsRepositoryPath) { - this.symbolsRepositoryPath = symbolsRepositoryPath; + public PdbLocator(File symbolsRepositoryDir) { + this.symbolsRepositoryDir = symbolsRepositoryDir; } //============================================================================================== @@ -219,7 +221,7 @@ public class PdbLocator { try { List orderedListOfExistingFileNames = findPDB(new PdbProgramAttributes(program), - includePeSpecifiedPdbPath, symbolsRepositoryPath.getAbsolutePath()); + includePeSpecifiedPdbPath, symbolsRepositoryDir); if (orderedListOfExistingFileNames.isEmpty()) { String pdbName = program.getOptions(Program.PROGRAM_INFO) @@ -371,7 +373,7 @@ public class PdbLocator { Integer signature = (attributes.getPdbSignature() == null) ? null : Integer.valueOf(attributes.getPdbSignature()); return formatPdbIdentifiers(attributes.getPdbFile(), signature, - Integer.valueOf(attributes.getPdbAge()), attributes.getPdbGuid()); + Integer.valueOf(attributes.getPdbAge(), 16), attributes.getPdbGuid()); } private StringBuilder formatPdbIdentifiers(String file, PdbIdentifiers identifiers) { @@ -386,8 +388,8 @@ public class PdbLocator { if (signature != null) { builder.append(String.format("; Signature: 0X%08X", signature)); } - builder.append("; Age: "); - builder.append(age); + builder.append("; Age: 0x"); + builder.append(Integer.toHexString(age)); if (guidString != null) { builder.append("; GUID: "); builder.append(guidString); @@ -404,12 +406,12 @@ public class PdbLocator { * @param pdbAttributes PDB attributes associated with the program. * @param includePeSpecifiedPdbPath {@code true} if looking for PDB in PE-Header-Specified * path location, which may be unsafe security-wise. - * @param symbolsRepositoryPathIn Location of the local symbols repository (can be null). + * @param symbolsRepositoryDir Location of the local symbols repository (can be null). * @return matching PDB file (or null, if not found). * @throws PdbException if there was a problem with the PDB attributes. */ - private List findPDB(PdbProgramAttributes pdbAttributes, - boolean includePeSpecifiedPdbPath, String symbolsRepositoryPathIn) throws PdbException { + private static List findPDB(PdbProgramAttributes pdbAttributes, + boolean includePeSpecifiedPdbPath, File symbolsRepositoryDir) throws PdbException { // Store potential names of PDB files and potential locations of those files, // so that all possible combinations can be searched. @@ -428,7 +430,7 @@ public class PdbLocator { guidSubdirPaths.add(File.separator + potentialName + File.separator + guidAgeString); } - return checkPathsForPdb(symbolsRepositoryPathIn, guidSubdirPaths, potentialPdbNames, + return checkPathsForPdb(symbolsRepositoryDir, guidSubdirPaths, potentialPdbNames, pdbAttributes, includePeSpecifiedPdbPath); } @@ -450,7 +452,7 @@ public class PdbLocator { * symbolsRepositoryPath, then look for .pdb.xml file, then .pdb.xml file in other * directories. * - * @param symbolsRepositoryPath location of the local symbols repository (can be null) + * @param symbolsRepositoryDir location of the local symbols repository (can be null) * @param guidSubdirPaths subdirectory paths (that include the PDB's GUID) that may contain * a matching PDB * @param potentialPdbNames all potential filenames for the PDB file(s) that match the program @@ -460,19 +462,19 @@ public class PdbLocator { * enabled unless binary source is trusted and PDB file path is reasonable for this system. * @return matching PDB file, if found (else null) */ - private static List checkPathsForPdb(String symbolsRepositoryPath, + private static List checkPathsForPdb(File symbolsRepositoryDir, Set guidSubdirPaths, List potentialPdbNames, PdbProgramAttributes pdbAttributes, boolean includePeSpecifiedPdbPath) { Set symbolsRepoPaths = - getSymbolsRepositoryPaths(symbolsRepositoryPath, guidSubdirPaths); + getSymbolsRepositoryPaths(symbolsRepositoryDir, guidSubdirPaths); Set predefinedPaths = getPredefinedPaths(guidSubdirPaths, pdbAttributes, includePeSpecifiedPdbPath); - // Start by searching in symbolsRepositoryPath, if available. + // Start by searching in symbolsRepositoryDir, if available. List orderedListOfExistingFileNames = new ArrayList<>(); - if (symbolsRepositoryPath != null) { + if (!symbolsRepoPaths.isEmpty()) { orderedListOfExistingFileNames .addAll(checkSpecificPathsForPdb(symbolsRepoPaths, potentialPdbNames)); } @@ -494,26 +496,23 @@ public class PdbLocator { } //============================================================================================== - private static Set getSymbolsRepositoryPaths(String symbolsRepositoryPath, + private static Set getSymbolsRepositoryPaths(File symbolsRepositoryDir, Set guidSubdirPaths) { Set symbolsRepoPaths = new LinkedHashSet<>(); // Collect sub-directories of the symbol repository that exist - File symRepoFile; - - if (symbolsRepositoryPath != null && - (symRepoFile = new File(symbolsRepositoryPath)).isDirectory()) { + if (symbolsRepositoryDir != null && symbolsRepositoryDir.isDirectory()) { for (String guidSubdir : guidSubdirPaths) { - File testDir = new File(symRepoFile, guidSubdir); + File testDir = new File(symbolsRepositoryDir, guidSubdir); if (testDir.isDirectory()) { symbolsRepoPaths.add(testDir); } } // Check outer folder last - symbolsRepoPaths.add(symRepoFile); + symbolsRepoPaths.add(symbolsRepositoryDir); } return symbolsRepoPaths; @@ -527,7 +526,8 @@ public class PdbLocator { Set predefinedPaths = new LinkedHashSet<>(); getPathsFromAttributes(pdbAttributes, includePeSpecifiedPdbPath, predefinedPaths); - getWindowsPaths(guidSubdirPaths, predefinedPaths); + getSymbolPaths(DEFAULT_SYMBOLS_DIR, guidSubdirPaths, predefinedPaths); + getSymbolPaths(WINDOWS_SYMBOLS_DIR, guidSubdirPaths, predefinedPaths); getLibraryPaths(guidSubdirPaths, predefinedPaths); return predefinedPaths; @@ -566,20 +566,22 @@ public class PdbLocator { *
  • C:\MySymbols\symbols\ext *

    */ - private static void getWindowsPaths(Set guidSubdirPaths, Set predefinedPaths) { + private static void getSymbolPaths(File symbolsDir, Set guidSubdirPaths, + Set predefinedPaths) { // TODO: Need to provide better control of symbol directory preference // instead of only using default - if (DEFAULT_SYMBOLS_DIR.isDirectory()) { - predefinedPaths.add(DEFAULT_SYMBOLS_DIR); + if (symbolsDir == null || !symbolsDir.isDirectory()) { + return; + } + predefinedPaths.add(symbolsDir); - // Check alternate locations - String specialPdbPath = DEFAULT_SYMBOLS_DIR.getAbsolutePath(); + // Check alternate locations + String specialPdbPath = symbolsDir.getAbsolutePath(); - for (String guidSubdir : guidSubdirPaths) { - File testDir = new File(specialPdbPath + guidSubdir); - if (testDir.isDirectory()) { - predefinedPaths.add(testDir); - } + for (String guidSubdir : guidSubdirPaths) { + File testDir = new File(specialPdbPath + guidSubdir); + if (testDir.isDirectory()) { + predefinedPaths.add(testDir); } } } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbProgramAttributes.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbProgramAttributes.java index 23803c0a13..f8f7502f00 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbProgramAttributes.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/PdbProgramAttributes.java @@ -28,7 +28,7 @@ import ghidra.program.model.listing.Program; */ public class PdbProgramAttributes { - private String pdbAge; + private String pdbAge; // hex format private String pdbGuid; private String pdbSignature; @@ -78,6 +78,10 @@ public class PdbProgramAttributes { createGuidAgeString(); } + /** + * PDB Age as a hex value + * @return PDB Age as a hex value + */ public String getPdbAge() { return pdbAge; } diff --git a/Ghidra/Features/PDB/src/main/java/pdb/PdbSymbolServerPlugin.java b/Ghidra/Features/PDB/src/main/java/pdb/PdbSymbolServerPlugin.java index b4b5ba903e..c4630e629a 100644 --- a/Ghidra/Features/PDB/src/main/java/pdb/PdbSymbolServerPlugin.java +++ b/Ghidra/Features/PDB/src/main/java/pdb/PdbSymbolServerPlugin.java @@ -217,8 +217,7 @@ public class PdbSymbolServerPlugin extends Plugin { localDir = askForLocalStorageLocation(); // 3. See if PDB can be found locally - File pdbFile = PdbParser.findPDB(pdbAttributes, includePePdbPath, - localDir.getAbsolutePath(), fileType); + File pdbFile = PdbParser.findPDB(pdbAttributes, includePePdbPath, localDir, fileType); // 4. If not found locally, ask if it should be retrieved if (pdbFile != null && pdbFile.getName().endsWith(fileType.toString())) { diff --git a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/PdbParserTest.java b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/PdbParserTest.java index 0eb4c79ff9..9e82411e99 100644 --- a/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/PdbParserTest.java +++ b/Ghidra/Features/PDB/src/test/java/ghidra/app/util/bin/format/pdb/PdbParserTest.java @@ -44,7 +44,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { private static String notepadGUID = "36cfd5f9-888c-4483-b522-b9db242d8478"; // Note: this is in hex. Code should translate it to decimal when creating GUID/Age folder name - private static String notepadAge = "00000021"; + private static String notepadAge = "21"; // Name of subfolder that stores the actual PDB file private static String guidAgeCombo = "36CFD5F9888C4483B522B9DB242D847833"; @@ -54,8 +54,8 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { private Program testProgram; //private static String guidAgeCombo = PdbParserNEW.getGuidAgeString(notepadGUID, notepadAge); - // Default repo path that is hard-coded into the PDB analyzer settings - private static String defaultSymbolsRepoPath = "C:/Symbols"; + // Bogus symbol repository directory or null directory should not break anything + private static final File noSuchSymbolsRepoDir = null; private String pdbFilename, pdbXmlFilename; private String exeFolderName = "exe", pdbXmlFolderName = "pdb_xml", @@ -269,28 +269,24 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { assertNotNull(pdbFile); expectedDir1 = new File(fileLocation, pdbFilename); expectedDir2 = new File(expectedDir1, guidAgeCombo); - assertEquals(expectedDir2.getAbsolutePath(), - pdbFile.getParentFile().getAbsolutePath()); + assertEquals(expectedDir2, pdbFile.getParentFile()); break; case SAME_AS_EXE_NO_SUBDIR: assertNotNull(pdbFile); - assertEquals(fileLocation.getAbsolutePath(), - pdbFile.getParentFile().getAbsolutePath()); + assertEquals(fileLocation, pdbFile.getParentFile()); break; case SYMBOLS_SUBDIR: assertNotNull(pdbFile); expectedDir1 = new File(symbolsFolder, pdbFilename); expectedDir2 = new File(expectedDir1, guidAgeCombo); - assertEquals(expectedDir2.getAbsolutePath(), - pdbFile.getParentFile().getAbsolutePath()); + assertEquals(expectedDir2, pdbFile.getParentFile()); break; case SYMBOLS_NO_SUBDIR: assertNotNull(pdbFile); - assertEquals(symbolsFolder.getAbsolutePath(), - pdbFile.getParentFile().getAbsolutePath()); + assertEquals(symbolsFolder, pdbFile.getParentFile()); break; default: @@ -300,14 +296,12 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { switch (pdbXmlLoc) { case SAME_AS_PDB: assertNotNull(pdbXmlFile); - assertEquals(pdbXmlFile.getParentFile().getAbsolutePath(), - pdbFile.getParentFile().getAbsolutePath()); + assertEquals(pdbXmlFile.getParentFile(), pdbFile.getParentFile()); break; case OWN_DIR: assertNotNull(pdbXmlFile); - assertEquals(pdbXmlFile.getParentFile().getAbsolutePath(), - pdbXmlDir.getAbsolutePath()); + assertEquals(pdbXmlFile.getParentFile(), pdbXmlDir); break; case NONE: @@ -338,7 +332,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = null; createdFiles = createFiles(PdbLocation.SYMBOLS_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); // Should not find anything since repo is set to an invalid path assertNull(pdb); @@ -360,10 +354,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -382,15 +376,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -409,10 +403,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); - assertEquals(pdb.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdb, pdb); } @@ -431,15 +425,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -458,10 +452,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_NO_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -479,7 +473,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_NO_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); // Should not find anything since repo is set to an invalid path assertNull(pdb); @@ -500,15 +494,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_NO_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -527,10 +521,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_NO_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, symbolsFolder); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -549,15 +543,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SYMBOLS_NO_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -576,10 +570,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -597,7 +591,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); // Should not find anything since repo is set to an invalid path assertNull(pdb); @@ -618,15 +612,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -645,10 +639,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -667,15 +661,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlFile.getParentFile()); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -697,10 +691,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -719,10 +713,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -744,10 +738,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } @@ -769,15 +763,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -796,15 +790,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.SAME_AS_PDB); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParent()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -823,10 +817,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } /** @@ -844,10 +838,10 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile().getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbFile.getParentFile()); assertNotNull(pdb); - assertEquals(pdbFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbFile, pdb); } /** @@ -868,15 +862,15 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.SAME_AS_EXE_NO_SUBDIR, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } @@ -895,7 +889,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.NONE, PdbXmlLocation.NONE); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); assertNull(pdb); } @@ -915,7 +909,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.NONE, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, defaultSymbolsRepoPath); + File pdb = PdbParser.findPDB(testProgram, false, noSuchSymbolsRepoDir); assertNull(pdb); } @@ -935,22 +929,22 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createdFiles = createFiles(PdbLocation.NONE, PdbXmlLocation.OWN_DIR); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); assertNotNull(pdb); if (PdbParser.onWindows) { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } else { - assertEquals(pdbXmlFile.getAbsolutePath(), pdb.getAbsolutePath()); + assertEquals(pdbXmlFile, pdb); } } private void createDirectory(File directory) { directory.mkdir(); if (!directory.isDirectory()) { - fail("Should have created directory: " + directory.getAbsolutePath()); + fail("Should have created directory: " + directory); } } @@ -961,7 +955,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { createSuccess = file.createNewFile(); if (!createSuccess) { - fail("Failed creation of file: " + file.getAbsolutePath()); + fail("Failed creation of file: " + file); } } catch (IOException ioe) { @@ -1002,7 +996,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { xmlBuffWriter.close(); } catch (IOException ioe) { - fail("IOException writing to temporary file (" + pdbXmlFile.getAbsolutePath() + "). " + + fail("IOException writing to temporary file (" + pdbXmlFile + "). " + ioe.toString()); } @@ -1015,7 +1009,7 @@ public class PdbParserTest extends AbstractGhidraHeadlessIntegrationTest { buildPdbXml(); - File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir.getAbsolutePath()); + File pdb = PdbParser.findPDB(testProgram, false, pdbXmlDir); AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(testProgram); DataTypeManagerService dataTypeManagerService = mgr.getDataTypeManagerService(); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java index 7f6491057d..531691d803 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,4 +31,14 @@ public interface CustomOption { */ public void writeState(SaveState saveState); + /** + * CustomOption should implement this method to provide a formatted + * string value of this option value. The returned value will + * be used in support of the {@link Options#getValueAsString(String)} + * and {@link Options#getDefaultValueAsString(String)}. + * @return option value as string + */ + @Override + public String toString(); + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java index 1d9acbbe2e..0fa93e57b0 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DataTypeArchiveDB.java @@ -540,18 +540,18 @@ public class DataTypeArchiveDB extends DomainObjectAdapterDB Options propList = getOptions(Program.PROGRAM_INFO); List propNames = propList.getOptionNames(); Collections.sort(propNames); - for (String name : propNames) { - metadata.put(name, propList.getValueAsString(name)); + for (String propName : propNames) { + if (propName.indexOf(Options.DELIMITER) >= 0) { + continue; // ignore second tier options + } + String valueAsString = propList.getValueAsString(propName); + if (valueAsString != null) { + metadata.put(propName, propList.getValueAsString(propName)); + } } return metadata; } -// private static String getString(Object obj) { -// if (obj != null) { -// return obj.toString(); -// } -// return null; -// } @Override protected void updateMetadata() throws IOException { getMetadata(); // updates metadata map diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java index b9f75b8e03..d38fa24f97 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ProgramDB.java @@ -2360,7 +2360,13 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM List propNames = propList.getOptionNames(); Collections.sort(propNames); for (String propName : propNames) { - metadata.put(propName, propList.getValueAsString(propName)); + if (propName.indexOf(Options.DELIMITER) >= 0) { + continue; // ignore second tier options + } + String valueAsString = propList.getValueAsString(propName); + if (valueAsString != null) { + metadata.put(propName, propList.getValueAsString(propName)); + } } return metadata; }