GP-911 - Improve PDB reader/applicator options

This commit is contained in:
ghizard 2021-05-12 14:47:57 -04:00
parent 5234839b24
commit b510852b83
11 changed files with 409 additions and 366 deletions

View file

@ -27,12 +27,12 @@ import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.PeLoader; import ghidra.app.util.opinion.PeLoader;
import ghidra.app.util.pdb.PdbLocator; import ghidra.app.util.pdb.PdbLocator;
import ghidra.app.util.pdb.PdbProgramAttributes; import ghidra.app.util.pdb.PdbProgramAttributes;
import ghidra.app.util.pdb.pdbapplicator.*; import ghidra.app.util.pdb.pdbapplicator.PdbApplicator;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorOptions;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.options.OptionType; import ghidra.framework.options.OptionType;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.program.model.address.AddressSetView; import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.data.CharsetInfo;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
@ -92,105 +92,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
"If checked, specifically searching for PDB in PE-Header-Specified Location."; "If checked, specifically searching for PDB in PE-Header-Specified Location.";
private boolean includePeSpecifiedPdbPath = false; private boolean includePeSpecifiedPdbPath = false;
//==============================================================================================
// Logging options
//==============================================================================================
// Perform logging of PDB information for debugging/development.
// NOTE: This logging mechanism is not intended to live the full life of this tool, but to
// aid in getting feedback from the field during its early development.
private static final String OPTION_NAME_PDB_READER_ANALYZER_LOGGING =
"[PDB Reader/Analyzer Debug Logging]";
private static final String OPTION_DESCRIPTION_PDB_READER_ANALYZER_LOGGING =
"If checked, logs information to the pdb.analyzer.log file for debug/development.";
private boolean pdbLogging = false;
//==============================================================================================
// PdbReader options
//==============================================================================================
// Sets the one-byte Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-specific Charset.
private static final String OPTION_NAME_ONE_BYTE_CHARSET_NAME = "PDB One-Byte Charset Name";
private static final String OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME =
"Charset used for processing of one-byte (or multi) encoded Strings: " +
PdbReaderOptions.getOneByteCharsetNames();
private String oneByteCharsetName = CharsetInfo.UTF8;
// Sets the wchar_t Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-program-specific Charset.
private static final String OPTION_NAME_WCHAR_CHARSET_NAME = "PDB Wchar_t Charset Name";
private static final String OPTION_DESCRIPTION_WCHAR_CHARSET_NAME =
"Charset used for processing of wchar_t encoded Strings: " +
PdbReaderOptions.getTwoByteCharsetNames();
private String wideCharCharsetName = CharsetInfo.UTF16;
//==============================================================================================
// PdbApplicator options
//==============================================================================================
// Applicator Restrictions.
private static final String OPTION_NAME_PROCESSING_RESTRICTIONS = "Processing Restrictions";
private static final String OPTION_DESCRIPTION_PROCESSING_RESTRICTIONS =
"Restrictions on applicator processing.";
private static PdbApplicatorRestrictions restrictions;
// Apply Code Block Comments.
private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"Apply Code Scope Block Comments";
private static final String OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
"If checked, pre/post-comments will be applied when code scope blocks are specified.";
private boolean applyCodeScopeBlockComments;
// Apply Instruction Labels information.
private static final String OPTION_NAME_APPLY_INSTRUCTION_LABELS = "Apply Instruction Labels";
private static final String OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS =
"If checked, labels associated with instructions will be applied.";
private boolean applyInstructionLabels;
// Attempt to map address using existing mangled symbols.
private static final String OPTION_NAME_ADDRESS_REMAP = "Address Remap Using Existing Symbols";
private static final String OPTION_DESCRIPTION_ADDRESS_REMAP =
"If checked, attempts to remap address to those matching existing public symbols.";
private boolean remapAddressUsingExistingPublicMangledSymbols;
// Allow a mangled symbol to be demoted from being a primary symbol if another symbol and
// associated explicit data type will be laid down at the location. This option exists
// because we expect the PDB explicit data type will be more accurate than trying to
// have the demangler lay down the data type.
private static final String OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY =
"Allow demote mangled symbol from primary";
private static final String OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY =
"If checked, allows a mangled symbol to be demoted from primary if a possibly " +
"better data type can be laid down with a nonmangled symbol.";
private boolean allowDemotePrimaryMangledSymbol;
// Apply Function Variables
private static final String OPTION_NAME_APPLY_FUNCTION_VARIABLES = "Apply Function Variables";
private static final String OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES =
"If checked, attempts to apply function parameters and local variables for program functions.";
private boolean applyFunctionVariables;
// Sets the composite layout.
// Legacy
// - similar to existing DIA-based PDB Analyzer, only placing current composite direct
// members (none from parent classes.
// Warning: the remaining experimental layout choices may not be kept and are not guaranteed
// to result in data types that will be compatible with future Ghidra releases:
// Complex with Basic Fallback
// - Performs Complex layout, but if the current class has no parent classes, it will not
// encapsulate the current class's 'direct' members.
// Simple
// - Performs Complex layout, except in rare instances where , so in most cases is the same
// as 'Complex with Basic Fallback' layout.
// Complex
// - Puts all current class members and 'direct' parents' 'direct' components into an
// encapsulating 'direct' container
private static final String OPTION_NAME_COMPOSITE_LAYOUT = "Composite Layout Choice";
private static final String OPTION_DESCRIPTION_COMPOSITE_LAYOUT =
"Legacy layout like original PDB Analyzer. Warning: other choices have no compatibility" +
" guarantee with future Ghidra releases or minor PDB Analyzer changes";
private ObjectOrientedClassLayout compositeLayout;
//============================================================================================== //==============================================================================================
// Additional instance data // Additional instance data
//============================================================================================== //==============================================================================================
@ -256,9 +157,8 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
PdbProgramAttributes programAttributes = new PdbProgramAttributes(program); PdbProgramAttributes programAttributes = new PdbProgramAttributes(program);
if (programAttributes.isPdbLoaded()) { if (programAttributes.isPdbLoaded()) {
Msg.info(this, "Skipping PDB analysis since it has previouslu run."); Msg.info(this, "Skipping PDB analysis since it has previouslu run.");
Msg.info(this, Msg.info(this, ">> Clear 'PDB Loaded' program property or use Load PDB action if " +
">> Clear 'PDB Loaded' program property or use Load PDB action if " + "additional PDB processing required.");
"additional PDB processing required.");
return true; return true;
} }
@ -267,8 +167,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
return true; return true;
} }
setPdbLogging(log);
String pdbFilename; String pdbFilename;
if (doForceLoad) { if (doForceLoad) {
if (!confirmFile(forceLoadFile)) { if (!confirmFile(forceLoadFile)) {
@ -361,53 +259,16 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
options.registerOption(OPTION_NAME_FORCELOAD_FILE, OptionType.FILE_TYPE, options.registerOption(OPTION_NAME_FORCELOAD_FILE, OptionType.FILE_TYPE,
DEFAULT_FORCE_LOAD_FILE, null, OPTION_DESCRIPTION_FORCELOAD_FILE); DEFAULT_FORCE_LOAD_FILE, null, OPTION_DESCRIPTION_FORCELOAD_FILE);
} }
options.registerOption(OPTION_NAME_SYMBOLPATH, OptionType.FILE_TYPE, options.registerOption(OPTION_NAME_SYMBOLPATH, OptionType.FILE_TYPE, symbolsRepositoryDir,
symbolsRepositoryDir, null, OPTION_DESCRIPTION_SYMBOLPATH); null, OPTION_DESCRIPTION_SYMBOLPATH);
options.registerOption(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath, null, options.registerOption(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath, null,
OPTION_DESCRIPTION_INCLUDE_PE_PDB_PATH); OPTION_DESCRIPTION_INCLUDE_PE_PDB_PATH);
// PdbReaderOptions pdbReaderOptions.registerOptions(options);
getPdbReaderOptions(); pdbApplicatorOptions.registerAnalyzerOptions(options);
options.registerOption(OPTION_NAME_PDB_READER_ANALYZER_LOGGING, pdbLogging, null,
OPTION_DESCRIPTION_PDB_READER_ANALYZER_LOGGING);
if (developerMode) {
options.registerOption(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName, null,
OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME);
options.registerOption(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName, null,
OPTION_DESCRIPTION_WCHAR_CHARSET_NAME);
}
// PdbApplicatorOptions pdbReaderOptions.loadOptions(options);
getPdbApplicatorOptions(); pdbApplicatorOptions.loadAnalyzerOptions(options);
if (developerMode) {
options.registerOption(OPTION_NAME_PROCESSING_RESTRICTIONS, restrictions, null,
OPTION_DESCRIPTION_PROCESSING_RESTRICTIONS);
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
applyCodeScopeBlockComments, null,
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
options.registerOption(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels,
null, OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS);
// The remap capability is not completely implemented... do not turn on.
options.registerOption(OPTION_NAME_ADDRESS_REMAP,
remapAddressUsingExistingPublicMangledSymbols, null,
OPTION_DESCRIPTION_ADDRESS_REMAP);
options.registerOption(OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY,
allowDemotePrimaryMangledSymbol, null,
OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY);
// Function params and local implementation is not complete... do not turn on.
options.registerOption(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables,
null, OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES);
// Object-oriented composite layout is fairly far along, but its use will likely not
// be forward compatible with future Ghidra work in this area; i.e., it might leave
// the data type manager in a bad state for future revisions. While the current
// layout mechanism might work, I will likely change it to, instead, create a
// syntactic intermediate representation before creating the final layout. This will
// aid portability between tool chains and versions and yield a standard way of
// data-basing and presenting the information to a user.
options.registerOption(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout, null,
OPTION_DESCRIPTION_COMPOSITE_LAYOUT);
}
} }
@Override @Override
@ -427,33 +288,8 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
includePeSpecifiedPdbPath = includePeSpecifiedPdbPath =
options.getBoolean(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath); options.getBoolean(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath);
// PdbReaderOptions pdbReaderOptions.loadOptions(options);
pdbLogging = options.getBoolean(OPTION_NAME_PDB_READER_ANALYZER_LOGGING, pdbLogging); pdbApplicatorOptions.loadAnalyzerOptions(options);
if (developerMode) {
oneByteCharsetName =
options.getString(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName);
wideCharCharsetName =
options.getString(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName);
}
setPdbReaderOptions();
// PdbApplicatorOptions
if (developerMode) {
restrictions = options.getEnum(OPTION_NAME_PROCESSING_RESTRICTIONS, restrictions);
applyCodeScopeBlockComments = options.getBoolean(
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
applyInstructionLabels =
options.getBoolean(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels);
remapAddressUsingExistingPublicMangledSymbols = options.getBoolean(
OPTION_NAME_ADDRESS_REMAP, remapAddressUsingExistingPublicMangledSymbols);
allowDemotePrimaryMangledSymbol = options.getBoolean(
OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY, allowDemotePrimaryMangledSymbol);
applyFunctionVariables =
options.getBoolean(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables);
compositeLayout = options.getEnum(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout);
}
setPdbApplicatorOptions();
} }
//============================================================================================== //==============================================================================================
@ -497,54 +333,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
return true; return true;
} }
private void setPdbLogging(MessageLog log) {
try {
PdbLog.setEnabled(pdbLogging);
}
catch (IOException e) {
// Probably could not open the file.
if (log != null) {
log.appendMsg(getName(), "IOException when trying to open PDB log file: ");
log.appendException(e);
}
}
}
private void getPdbReaderOptions() {
oneByteCharsetName = pdbReaderOptions.getOneByteCharsetName();
wideCharCharsetName = pdbReaderOptions.getTwoByteCharsetName();
}
private void setPdbReaderOptions() {
pdbReaderOptions.setOneByteCharsetForName(oneByteCharsetName);
pdbReaderOptions.setWideCharCharsetForName(wideCharCharsetName);
}
private void getPdbApplicatorOptions() {
applyCodeScopeBlockComments = PdbApplicatorOptions.DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
restrictions = PdbApplicatorOptions.DEFAULT_RESTRICTIONS;
applyInstructionLabels = PdbApplicatorOptions.DEFAULT_APPLY_INSTRUCTION_LABELS;
remapAddressUsingExistingPublicMangledSymbols =
PdbApplicatorOptions.DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
allowDemotePrimaryMangledSymbol =
PdbApplicatorOptions.DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS;
applyFunctionVariables = PdbApplicatorOptions.DEFAULT_APPLY_FUNCTION_VARIABLES;
compositeLayout = PdbApplicatorOptions.DEFAULT_CLASS_LAYOUT;
}
private void setPdbApplicatorOptions() {
pdbApplicatorOptions.setRestrictions(restrictions);
pdbApplicatorOptions.setApplyCodeScopeBlockComments(applyCodeScopeBlockComments);
pdbApplicatorOptions.setApplyInstructionLabels(applyInstructionLabels);
pdbApplicatorOptions.setRemapAddressUsingExistingPublicSymbols(
remapAddressUsingExistingPublicMangledSymbols);
pdbApplicatorOptions.setAllowDemotePrimaryMangledSymbols(allowDemotePrimaryMangledSymbol);
pdbApplicatorOptions.setApplyFunctionVariables(applyFunctionVariables);
pdbApplicatorOptions.setClassLayout(compositeLayout);
}
private boolean confirmDirectory(File path) { private boolean confirmDirectory(File path) {
return path.isDirectory(); return path.isDirectory();
} }

View file

@ -30,11 +30,9 @@ import ghidra.util.Msg;
*/ */
public class PdbLog { public class PdbLog {
private static File logFile; private static Writer nullWriter;
private static Writer nullWriter = new NullWriter();
private static Writer fileWriter; private static Writer fileWriter;
private static Writer writer = nullWriter; private static boolean enabled = false;
private static boolean enabled;
/** /**
* Enable or disable future messages to be output to the appropriate log resource. This * Enable or disable future messages to be output to the appropriate log resource. This
@ -47,15 +45,6 @@ public class PdbLog {
* @see #message(String, Supplier...) * @see #message(String, Supplier...)
*/ */
public static void setEnabled(boolean enable) throws IOException { public static void setEnabled(boolean enable) throws IOException {
if (fileWriter == null) {
fileWriter = createFileWriter();
}
if (nullWriter == null) {
// Doing this here, even though statically assigned above, just in case dispose() was
// called prematurely.
nullWriter = new NullWriter();
}
writer = enable ? fileWriter : nullWriter;
enabled = enable; enabled = enable;
} }
@ -85,6 +74,7 @@ public class PdbLog {
varArgs[i] = var; varArgs[i] = var;
} }
try { try {
Writer writer = getWriter();
writer.append(String.format(format, varArgs)); writer.append(String.format(format, varArgs));
writer.append("\n"); writer.append("\n");
writer.flush(); writer.flush();
@ -109,6 +99,7 @@ public class PdbLog {
} }
try { try {
Writer writer = getWriter();
writer.append(supplier.get()); writer.append(supplier.get());
writer.append("\n"); writer.append("\n");
writer.flush(); writer.flush();
@ -125,6 +116,7 @@ public class PdbLog {
*/ */
public static void message(String message) { public static void message(String message) {
try { try {
Writer writer = getWriter();
writer.append(message); writer.append(message);
writer.append("\n"); writer.append("\n");
writer.flush(); writer.flush();
@ -187,22 +179,44 @@ public class PdbLog {
} }
/** /**
* Creates a {@link FileWriter} for the log file to which we are planning to write, and * Returns the {@link Writer} for logging.
* deletes existing contents of the log file. * @return a {@link Writer} for for logging.
*/
private static Writer getWriter() throws IOException {
return enabled ? getFileWriter() : getNullWriter();
}
/**
* Returns the {@link FileWriter} for the log file. If the file is already open, it is
* returned. If not already open, it is opened and previous contents are deleted.
* @return a {@link FileWriter} for the log file. * @return a {@link FileWriter} for the log file.
*/ */
private static Writer createFileWriter() throws IOException { private static Writer getFileWriter() throws IOException {
if (fileWriter == null) {
/* /*
* Since we want this logging to be used sparingly and on a case-by-case basis, we * Since we want this logging to be used sparingly and on a case-by-case basis, we
* delete the log at the start of each JVM session. New log writing always uses the * delete the log contents upon initial opening. New log writing always uses the
* same log file name with not date or process ID attributes. * same log file name with not date or process ID attributes.
*/ */
logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log"); File logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log");
if (logFile.exists()) { if (logFile.exists()) {
logFile.delete(); logFile.delete();
}
fileWriter = new FileWriter(logFile);
} }
return new FileWriter(logFile); return fileWriter;
}
/**
* Returns a {@link NullWriter} for the log file when chosen instead of a FileWriter. If
* one already exists, it is returned. Otherwise a new one is created.
* @return a {@link NullWriter} for the log file.
*/
private static Writer getNullWriter() {
if (nullWriter == null) {
nullWriter = new NullWriter();
}
return nullWriter;
} }
private static void handleIOException(IOException exception) { private static void handleIOException(IOException exception) {
@ -215,7 +229,6 @@ public class PdbLog {
// squash // squash
} }
Msg.error(PdbLog.class, "IOException encountered; disabling writer", exception); Msg.error(PdbLog.class, "IOException encountered; disabling writer", exception);
writer = nullWriter;
enabled = false; enabled = false;
} }

View file

@ -15,10 +15,14 @@
*/ */
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List; import java.util.List;
import ghidra.framework.options.Options;
import ghidra.program.model.data.CharsetInfo; import ghidra.program.model.data.CharsetInfo;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
/** /**
* Options used while reading a PDB ({@link AbstractPdb}) that control various aspects. These * Options used while reading a PDB ({@link AbstractPdb}) that control various aspects. These
@ -27,28 +31,103 @@ import ghidra.program.model.data.CharsetInfo;
*/ */
public class PdbReaderOptions extends Exception { public class PdbReaderOptions extends Exception {
private static final String DEFAULT_ONE_BYTE_CHARSET_NAME = CharsetInfo.UTF8; // Developer turn on/off options that are in still in development.
private static final String DEFAULT_TWO_BYTE_CHARSET_NAME = CharsetInfo.UTF16; private static final boolean developerMode = false;
// Perform logging of PDB information for debugging/development.
// NOTE: This logging mechanism is not intended to live the full life of this tool, but to
// aid in getting feedback from the field during its early development.
private static final String OPTION_NAME_PDB_READER_APPLICATOR_LOGGING =
"[Dev] PDB Reader/Applicator Debug Logging";
private static final String OPTION_DESCRIPTION_PDB_READER_APPLICATOR_LOGGING =
"If checked, logs information to the pdb.analyzer.log file for debug/development.";
private static final boolean DEFAULT_PDB_READER_APPLICATOR_LOGGING = false;
private boolean pdbLogging;
// Sets the one-byte Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-specific Charset.
private static final String OPTION_NAME_ONE_BYTE_CHARSET_NAME = "PDB One-Byte Charset Name";
private static final String OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME =
"Charset used for processing of one-byte (or multi) encoded Strings: " +
PdbReaderOptions.getOneByteCharsetNames();
private static final String DEFAULT_ONE_BYTE_CHARSET_NAME = CharsetInfo.UTF8;
private String oneByteCharsetName;
// Sets the wchar_t Charset to be used for PDB processing.
// NOTE: This "Option" is not intended as a permanent part of this analyzer. Should be
// replaced by target-program-specific Charset.
private static final String OPTION_NAME_WCHAR_CHARSET_NAME = "PDB Wchar_t Charset Name";
private static final String OPTION_DESCRIPTION_WCHAR_CHARSET_NAME =
"Charset used for processing of wchar_t encoded Strings: " +
PdbReaderOptions.getTwoByteCharsetNames();
private static final String DEFAULT_TWO_BYTE_CHARSET_NAME = CharsetInfo.UTF16;
private String wideCharCharsetName;
//==============================================================================================
private static List<String> oneByteCharsetNames = private static List<String> oneByteCharsetNames =
CharsetInfo.getInstance().getCharsetNamesWithCharSize(1); CharsetInfo.getInstance().getCharsetNamesWithCharSize(1);
private static List<String> twoByteCharsetNames = private static List<String> twoByteCharsetNames =
CharsetInfo.getInstance().getCharsetNamesWithCharSize(2); CharsetInfo.getInstance().getCharsetNamesWithCharSize(2);
private String oneByteCharsetName;
private String twoByteCharsetName;
private Charset oneByteCharset; private Charset oneByteCharset;
private Charset twoByteCharset; private Charset wideCharset;
/** /**
* Constructor. * Constructor.
*/ */
public PdbReaderOptions() { public PdbReaderOptions() {
setDefaults();
}
public void registerOptions(Options options) {
HelpLocation help = null;
options.registerOption(OPTION_NAME_PDB_READER_APPLICATOR_LOGGING, pdbLogging, null,
OPTION_DESCRIPTION_PDB_READER_APPLICATOR_LOGGING);
if (developerMode) {
options.registerOption(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName, help,
OPTION_DESCRIPTION_ONE_BYTE_CHARSET_NAME);
options.registerOption(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName, help,
OPTION_DESCRIPTION_WCHAR_CHARSET_NAME);
}
}
public void loadOptions(Options options) {
pdbLogging = options.getBoolean(OPTION_NAME_PDB_READER_APPLICATOR_LOGGING, pdbLogging);
setPdbLogging();
if (developerMode) {
oneByteCharsetName =
options.getString(OPTION_NAME_ONE_BYTE_CHARSET_NAME, oneByteCharsetName);
setOneByteCharsetForName(oneByteCharsetName);
wideCharCharsetName =
options.getString(OPTION_NAME_WCHAR_CHARSET_NAME, wideCharCharsetName);
setWideCharCharsetForName(wideCharCharsetName);
}
}
/**
* Set the options to their default values
*/
public void setDefaults() {
pdbLogging = DEFAULT_PDB_READER_APPLICATOR_LOGGING;
setPdbLogging();
oneByteCharsetName = DEFAULT_ONE_BYTE_CHARSET_NAME; oneByteCharsetName = DEFAULT_ONE_BYTE_CHARSET_NAME;
twoByteCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME; wideCharCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME;
setOneByteCharsetForName(oneByteCharsetName); setOneByteCharsetForName(oneByteCharsetName);
setWideCharCharsetForName(twoByteCharsetName); setWideCharCharsetForName(wideCharCharsetName);
}
private void setPdbLogging() {
try {
PdbLog.setEnabled(pdbLogging);
}
catch (IOException e) {
Msg.info(this, "Failure opening PDB log file: ", e);
}
} }
/** /**
@ -90,8 +169,8 @@ public class PdbReaderOptions extends Exception {
if (!twoByteCharsetNames.contains(name)) { if (!twoByteCharsetNames.contains(name)) {
throw new IllegalArgumentException("Unknown TwoByteCharset: " + name); throw new IllegalArgumentException("Unknown TwoByteCharset: " + name);
} }
twoByteCharset = Charset.forName(name); wideCharset = Charset.forName(name);
twoByteCharsetName = name; wideCharCharsetName = name;
return this; return this;
} }
@ -108,7 +187,7 @@ public class PdbReaderOptions extends Exception {
* @return the name of the Charset. * @return the name of the Charset.
*/ */
public String getTwoByteCharsetName() { public String getTwoByteCharsetName() {
return twoByteCharsetName; return wideCharCharsetName;
} }
/** /**
@ -116,7 +195,7 @@ public class PdbReaderOptions extends Exception {
* @return the name of the Wchar Charset. * @return the name of the Wchar Charset.
*/ */
public String getWideCharCharsetName() { public String getWideCharCharsetName() {
return twoByteCharsetName; return wideCharCharsetName;
} }
/** /**
@ -132,7 +211,7 @@ public class PdbReaderOptions extends Exception {
* @return the Charset. * @return the Charset.
*/ */
public Charset getTwoByteCharset() { public Charset getTwoByteCharset() {
return twoByteCharset; return wideCharset;
} }
/** /**
@ -140,7 +219,6 @@ public class PdbReaderOptions extends Exception {
* @return the Wchar Charset. * @return the Wchar Charset.
*/ */
public Charset getWideCharCharset() { public Charset getWideCharCharset() {
return twoByteCharset; return wideCharset;
} }
} }

View file

@ -340,7 +340,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
// TODO: Investigate. We should do this check for some classes somewhere. Should // TODO: Investigate. We should do this check for some classes somewhere. Should
// we do it here. Set breakpoint here to investigate. // we do it here. Set breakpoint here to investigate.
} }
classType.createLayout(applicator.getPdbApplicatorOptions().getClassLayout(), classType.createLayout(applicator.getPdbApplicatorOptions().getCompositeLayout(),
applicator.getVbtManager(), applicator.getCancelOnlyWrappingMonitor()); applicator.getVbtManager(), applicator.getCancelOnlyWrappingMonitor());
} }

View file

@ -15,9 +15,8 @@
*/ */
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
import java.util.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*;
import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.cmd.label.SetLabelPrimaryCmd;
import ghidra.app.util.NamespaceUtils; import ghidra.app.util.NamespaceUtils;
@ -190,19 +189,20 @@ public class PdbApplicator {
initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam, initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, monitorParam, logParam); applicatorOptionsParam, monitorParam, logParam);
switch (applicatorOptions.getRestrictions()) { switch (applicatorOptions.getProcessingControl()) {
case DATA_TYPES_ONLY: case DATA_TYPES_ONLY:
processTypes(); processTypes();
break; break;
case PUBLIC_SYMBOLS_ONLY: case PUBLIC_SYMBOLS_ONLY:
processPublicSymbols(); processPublicSymbols();
break; break;
case NONE: case ALL:
processTypes(); processTypes();
processSymbols(); processSymbols();
break; break;
default: default:
throw new PdbException("Invalid Restriction"); throw new PdbException("PDB: Invalid Application Control: " +
applicatorOptions.getProcessingControl());
} }
if (program != null) { if (program != null) {
@ -346,15 +346,16 @@ public class PdbApplicator {
if (programParam == null) { if (programParam == null) {
if (dataTypeManagerParam == null) { if (dataTypeManagerParam == null) {
throw new PdbException( throw new PdbException(
"programParam and dataTypeManagerParam may not both be null."); "PDB: programParam and dataTypeManagerParam may not both be null.");
} }
if (imageBaseParam == null) { if (imageBaseParam == null) {
throw new PdbException("programParam and imageBaseParam may not both be null.");
}
if (applicatorOptions.getRestrictions() != PdbApplicatorRestrictions.DATA_TYPES_ONLY) {
throw new PdbException( throw new PdbException(
"programParam may not be null for the chosen PdbApplicatorRestrictions: " + "PDB: programParam and imageBaseParam may not both be null.");
applicatorOptions.getRestrictions()); }
if (applicatorOptions.getProcessingControl() != PdbApplicatorControl.DATA_TYPES_ONLY) {
throw new PdbException(
"PDB: programParam may not be null for the chosen Applicator Control: " +
applicatorOptions.getProcessingControl());
} }
} }
monitor = (monitorParam != null) ? monitorParam : TaskMonitor.DUMMY; monitor = (monitorParam != null) ? monitorParam : TaskMonitor.DUMMY;
@ -628,7 +629,7 @@ public class PdbApplicator {
return sectionContribution.getModule(); return sectionContribution.getModule();
} }
} }
throw new PdbException("Module not found for section/offset"); throw new PdbException("PDB: Module not found for section/offset");
} }
//============================================================================================== //==============================================================================================

View file

@ -16,10 +16,12 @@
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
/** /**
* PDB Applicator restrictions of actions performed. Used by {@link PdbApplicatorOptions} * PDB Applicator control for actions performed. Used by {@link PdbApplicatorOptions}
*/ */
public enum PdbApplicatorRestrictions { public enum PdbApplicatorControl {
NONE("None"), DATA_TYPES_ONLY("Data Types Only"), PUBLIC_SYMBOLS_ONLY("Public Symbols Only"); ALL("Process All"),
DATA_TYPES_ONLY("Data Types Only"),
PUBLIC_SYMBOLS_ONLY("Public Symbols Only");
private final String label; private final String label;
@ -28,7 +30,7 @@ public enum PdbApplicatorRestrictions {
return label; return label;
} }
private PdbApplicatorRestrictions(String label) { private PdbApplicatorControl(String label) {
this.label = label; this.label = label;
} }

View file

@ -16,6 +16,8 @@
package ghidra.app.util.pdb.pdbapplicator; package ghidra.app.util.pdb.pdbapplicator;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb; import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
import ghidra.framework.options.Options;
import ghidra.util.HelpLocation;
/** /**
* Options used while using a {@link PdbApplicator} to apply a PDB ({@link AbstractPdb}) to a * Options used while using a {@link PdbApplicator} to apply a PDB ({@link AbstractPdb}) to a
@ -24,54 +26,215 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
*/ */
public class PdbApplicatorOptions { public class PdbApplicatorOptions {
public static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false; // Developer turn on/off options that are in still in development.
public static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = false; private static final boolean developerMode = false;
public static final PdbApplicatorRestrictions DEFAULT_RESTRICTIONS =
PdbApplicatorRestrictions.NONE;
public static final boolean DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS = false;
public static final boolean DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS = true;
// TODO: set the following to true if we come up with a reasonably good solution // Applicator Control.
public static final boolean DEFAULT_APPLY_FUNCTION_VARIABLES = false; private static final String OPTION_NAME_PROCESSING_CONTROL = "Control";
private static final String OPTION_DESCRIPTION_PROCESSING_CONTROL =
"Applicator processing control.";
private static final PdbApplicatorControl DEFAULT_CONTROL = PdbApplicatorControl.ALL;
private PdbApplicatorControl control;
public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT = // Apply Code Block Comments.
ObjectOrientedClassLayout.MEMBERS_ONLY; private static final String OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT = "Apply Code Scope Block Comments";
// ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX; private static final String OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS =
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT = "If checked, pre/post-comments will be applied when code scope blocks are specified.";
// ObjectOrientedClassLayout.SIMPLE_COMPLEX; private static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false;
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.COMPLEX;
//==============================================================================================
private boolean applyCodeScopeBlockComments; private boolean applyCodeScopeBlockComments;
// Apply Instruction Labels information.
// Mechanism to apply instruction labels is not yet implemented-> does nothing
private static final String OPTION_NAME_APPLY_INSTRUCTION_LABELS = "Apply Instruction Labels";
private static final String OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS =
"If checked, labels associated with instructions will be applied.";
private static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = false;
private boolean applyInstructionLabels; private boolean applyInstructionLabels;
private PdbApplicatorRestrictions restrictions;
private boolean remapAddressesUsingExistingPublicSymbols; // Attempt to map address using existing mangled symbols.
private static final String OPTION_NAME_ADDRESS_REMAP = "Address Remap Using Existing Symbols";
private static final String OPTION_DESCRIPTION_ADDRESS_REMAP =
"If checked, attempts to remap address to those matching existing public symbols.";
private static final boolean DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS = false;
private boolean remapAddressUsingExistingPublicMangledSymbols;
// Allow a mangled symbol to be demoted from being a primary symbol if another symbol and
// associated explicit data type will be laid down at the location. This option exists
// because we expect the PDB explicit data type will be more accurate than trying to
// have the demangler lay down the data type.
private static final String OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY =
"Allow demote mangled symbol from primary";
private static final String OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY =
"If checked, allows a mangled symbol to be demoted from primary if a possibly " +
"better data type can be laid down with a nonmangled symbol.";
private static final boolean DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS = true;
private boolean allowDemotePrimaryMangledSymbols; private boolean allowDemotePrimaryMangledSymbols;
private boolean applyFunctionVariables; // investigation. might produce bad results. // Apply Function Variables
// Investigation. might produce bad results.
private static final String OPTION_NAME_APPLY_FUNCTION_VARIABLES = "Apply Function Variables";
private static final String OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES =
"If checked, attempts to apply function parameters and local variables for program functions.";
// TODO: set the following to true if we come up with a reasonably good solution
private static final boolean DEFAULT_APPLY_FUNCTION_VARIABLES = false;
private boolean applyFunctionVariables;
private ObjectOrientedClassLayout classLayout; // Sets the composite layout.
// Legacy
// - similar to existing DIA-based PDB Analyzer, only placing current composite direct
// members (none from parent classes.
// Warning: the remaining experimental layout choices may not be kept and are not guaranteed
// to result in data types that will be compatible with future Ghidra releases:
// Complex with Basic Fallback
// - Performs Complex layout, but if the current class has no parent classes, it will not
// encapsulate the current class's 'direct' members.
// Simple
// - Performs Complex layout, except in rare instances where , so in most cases is the same
// as 'Complex with Basic Fallback' layout.
// Complex
// - Puts all current class members and 'direct' parents' 'direct' components into an
// encapsulating 'direct' container
private static final String OPTION_NAME_COMPOSITE_LAYOUT = "Composite Layout Choice";
private static final String OPTION_DESCRIPTION_COMPOSITE_LAYOUT =
"Legacy layout like original PDB Analyzer. Warning: other choices have no compatibility" +
" guarantee with future Ghidra releases or minor PDB Analyzer changes";
private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
ObjectOrientedClassLayout.MEMBERS_ONLY;
private ObjectOrientedClassLayout compositeLayout;
// private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX;
//private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.SIMPLE_COMPLEX;
//private static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
// ObjectOrientedClassLayout.COMPLEX;
//==============================================================================================
/** /**
* Constructor * Constructor
*/ */
public PdbApplicatorOptions() { public PdbApplicatorOptions() {
restoreDefaults(); setDefaults();
} }
/** /**
* Set the options back to their default values * Register the PdbApplicatorOptions for "Analysis."
* @param options the Options that will have PdbApplicator options registered in.
*/ */
public void restoreDefaults() { public void registerAnalyzerOptions(Options options) {
registerOptions(options, false);
}
/**
* Load the PdbApplicatorOptions for used for "Analysis."
* @param options the Options that have PdbApplicator options registered in.
*/
public void loadAnalyzerOptions(Options options) {
loadOptions(options, false);
}
/**
* Register the PdbApplicatorOptions for "Load PDB."
* @param options the Options that will have PdbApplicator options registered in.
*/
public void registerLoaderOptions(Options options) {
registerOptions(options, true);
}
/**
* Load the PdbApplicatorOptions for used for "Load PDB."
* @param options the Options that have PdbApplicator options registered in.
*/
public void loadLoaderOptions(Options options) {
loadOptions(options, true);
}
private void registerOptions(Options options, boolean enableControl) {
HelpLocation help = null;
if (developerMode || enableControl) {
options.registerOption(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL, help,
OPTION_DESCRIPTION_PROCESSING_CONTROL);
}
// PdbApplicatorOptions
if (developerMode) {
options.registerOption(OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS,
applyCodeScopeBlockComments, help,
OPTION_DESCRIPTION_APPLY_CODE_SCOPE_BLOCK_COMMENTS);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
options.registerOption(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels,
help, OPTION_DESCRIPTION_APPLY_INSTRUCTION_LABELS);
// The remap capability is not completely implemented... do not turn on.
options.registerOption(OPTION_NAME_ADDRESS_REMAP,
remapAddressUsingExistingPublicMangledSymbols, help,
OPTION_DESCRIPTION_ADDRESS_REMAP);
options.registerOption(OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY,
allowDemotePrimaryMangledSymbols, help,
OPTION_DESCRIPTION_ALLOW_DEMOTE_MANGLED_PRIMARY);
// Function params and local implementation is not complete... do not turn on.
options.registerOption(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables,
help, OPTION_DESCRIPTION_APPLY_FUNCTION_VARIABLES);
// Object-oriented composite layout is fairly far along, but its use will likely not
// be forward compatible with future Ghidra work in this area; i.e., it might leave
// the data type manager in a bad state for future revisions. While the current
// layout mechanism might work, I will likely change it to, instead, create a
// syntactic intermediate representation before creating the final layout. This will
// aid portability between tool chains and versions and yield a standard way of
// data-basing and presenting the information to a user.
options.registerOption(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout, help,
OPTION_DESCRIPTION_COMPOSITE_LAYOUT);
}
}
private void loadOptions(Options options, boolean enableControl) {
if (developerMode || enableControl) {
control = options.getEnum(OPTION_NAME_PROCESSING_CONTROL, PdbApplicatorControl.ALL);
}
// PdbApplicatorOptions
if (developerMode) {
applyCodeScopeBlockComments = options.getBoolean(
OPTION_NAME_APPLY_CODE_SCOPE_BLOCK_COMMENTS, applyCodeScopeBlockComments);
// Mechanism to apply instruction labels is not yet implemented-> does nothing
applyInstructionLabels =
options.getBoolean(OPTION_NAME_APPLY_INSTRUCTION_LABELS, applyInstructionLabels);
remapAddressUsingExistingPublicMangledSymbols = options.getBoolean(
OPTION_NAME_ADDRESS_REMAP, remapAddressUsingExistingPublicMangledSymbols);
allowDemotePrimaryMangledSymbols = options.getBoolean(
OPTION_NAME_ALLOW_DEMOTE_MANGLED_PRIMARY, allowDemotePrimaryMangledSymbols);
applyFunctionVariables =
options.getBoolean(OPTION_NAME_APPLY_FUNCTION_VARIABLES, applyFunctionVariables);
compositeLayout = options.getEnum(OPTION_NAME_COMPOSITE_LAYOUT, compositeLayout);
}
}
/**
* Set the options to their default values
*/
public void setDefaults() {
applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS; applyCodeScopeBlockComments = DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS;
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS; applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
restrictions = DEFAULT_RESTRICTIONS; control = DEFAULT_CONTROL;
remapAddressesUsingExistingPublicSymbols = DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS; remapAddressUsingExistingPublicMangledSymbols =
DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
allowDemotePrimaryMangledSymbols = DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS; allowDemotePrimaryMangledSymbols = DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS;
applyFunctionVariables = DEFAULT_APPLY_FUNCTION_VARIABLES; applyFunctionVariables = DEFAULT_APPLY_FUNCTION_VARIABLES;
classLayout = DEFAULT_CLASS_LAYOUT; compositeLayout = DEFAULT_CLASS_LAYOUT;
} }
/** /**
@ -107,19 +270,19 @@ public class PdbApplicatorOptions {
} }
/** /**
* Set processing restrictions for PdbApplicator * Set processing control for PdbApplicator
* @param restrictions the restrictions * @param control the processing control
*/ */
public void setRestrictions(PdbApplicatorRestrictions restrictions) { public void setProcessingControl(PdbApplicatorControl control) {
this.restrictions = restrictions; this.control = control;
} }
/** /**
* Returns the current restrictions on PdbApplicator processing * Returns the current processing control for the PdbApplicator
* @return the restrictions * @return the processing control
*/ */
public PdbApplicatorRestrictions getRestrictions() { public PdbApplicatorControl getProcessingControl() {
return restrictions; return control;
} }
/** /**
@ -128,7 +291,7 @@ public class PdbApplicatorOptions {
* @param enable {@code true} to turn remapAddressesUsingExistingPublicSymbols on * @param enable {@code true} to turn remapAddressesUsingExistingPublicSymbols on
*/ */
public void setRemapAddressUsingExistingPublicSymbols(boolean enable) { public void setRemapAddressUsingExistingPublicSymbols(boolean enable) {
this.remapAddressesUsingExistingPublicSymbols = enable; this.remapAddressUsingExistingPublicMangledSymbols = enable;
} }
/** /**
@ -136,7 +299,7 @@ public class PdbApplicatorOptions {
* @return {@code true} if remapAddressesUsingExistingPublicSymbols is "on." * @return {@code true} if remapAddressesUsingExistingPublicSymbols is "on."
*/ */
public boolean remapAddressUsingExistingPublicSymbols() { public boolean remapAddressUsingExistingPublicSymbols() {
return remapAddressesUsingExistingPublicSymbols; return remapAddressUsingExistingPublicMangledSymbols;
} }
/** /**
@ -179,16 +342,15 @@ public class PdbApplicatorOptions {
* Set the class layout. * Set the class layout.
* @param classLayout composite layout * @param classLayout composite layout
*/ */
public void setClassLayout(ObjectOrientedClassLayout classLayout) { public void setCompositeLayout(ObjectOrientedClassLayout classLayout) {
this.classLayout = classLayout; this.compositeLayout = classLayout;
} }
/** /**
* Returns the physical layout out classes. * Returns the physical layout out classes.
* @return the class layout. * @return the class layout.
*/ */
public ObjectOrientedClassLayout getClassLayout() { public ObjectOrientedClassLayout getCompositeLayout() {
return classLayout; return compositeLayout;
} }
} }

View file

@ -24,7 +24,7 @@ import docking.DialogComponentProvider;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
import ghidra.app.util.bin.format.pdb.PdbParser; import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions; import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.util.layout.PairLayout; import ghidra.util.layout.PairLayout;
class AskPdbOptionsDialog extends DialogComponentProvider { class AskPdbOptionsDialog extends DialogComponentProvider {
@ -32,7 +32,7 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
private boolean isCanceled; private boolean isCanceled;
private boolean useMsDiaParser; private boolean useMsDiaParser;
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE; private PdbApplicatorControl control = PdbApplicatorControl.ALL;
/** /**
* Popup PDB loader options * Popup PDB loader options
@ -48,11 +48,11 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
JPanel optionsPanel = new JPanel(new PairLayout(10, 10)); JPanel optionsPanel = new JPanel(new PairLayout(10, 10));
final GComboBox<PdbApplicatorRestrictions> restrictionsCombo = final GComboBox<PdbApplicatorControl> controlCombo =
new GComboBox<>(PdbApplicatorRestrictions.values()); new GComboBox<>(PdbApplicatorControl.values());
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE); controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
restrictionsCombo.addActionListener(e -> { controlCombo.addActionListener(e -> {
restrictions = (PdbApplicatorRestrictions) restrictionsCombo.getSelectedItem(); control = (PdbApplicatorControl) controlCombo.getSelectedItem();
}); });
optionsPanel.add(new JLabel("PDB Parser:")); optionsPanel.add(new JLabel("PDB Parser:"));
@ -63,12 +63,12 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
final GComboBox<String> combo = final GComboBox<String> combo =
new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" }); new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" });
combo.setSelectedIndex(0); combo.setSelectedIndex(0);
restrictionsCombo.setEnabled(!useMsDiaParser); controlCombo.setEnabled(!useMsDiaParser);
combo.addActionListener(e -> { combo.addActionListener(e -> {
useMsDiaParser = (combo.getSelectedIndex() == 1); useMsDiaParser = (combo.getSelectedIndex() == 1);
restrictionsCombo.setEnabled(!useMsDiaParser); controlCombo.setEnabled(!useMsDiaParser);
if (useMsDiaParser) { if (useMsDiaParser) {
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE); controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
} }
}); });
optionsPanel.add(combo); optionsPanel.add(combo);
@ -85,8 +85,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
return; // no interaction currently required return; // no interaction currently required
} }
optionsPanel.add(new JLabel("Restrictions:")); optionsPanel.add(new JLabel("Control:"));
optionsPanel.add(restrictionsCombo); optionsPanel.add(controlCombo);
panel.add(optionsPanel, BorderLayout.CENTER); panel.add(optionsPanel, BorderLayout.CENTER);
@ -101,7 +101,6 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
DockingWindowManager.showDialog(parent, AskPdbOptionsDialog.this); DockingWindowManager.showDialog(parent, AskPdbOptionsDialog.this);
} }
@Override @Override
protected void applyCallback() { protected void applyCallback() {
isCanceled = false; isCanceled = false;
@ -122,8 +121,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
return useMsDiaParser; return useMsDiaParser;
} }
PdbApplicatorRestrictions getApplicatorRestrictions() { PdbApplicatorControl getApplicatorControl() {
return restrictions; return control;
} }
} }

View file

@ -44,15 +44,15 @@ class LoadPdbTask extends Task {
private DataTypeManagerService service; private DataTypeManagerService service;
private final Program program; private final Program program;
private final boolean useMsDiaParser; private final boolean useMsDiaParser;
private final PdbApplicatorRestrictions restrictions; // PDB Universal Parser only private final PdbApplicatorControl control; // PDB Universal Parser only
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) { DataTypeManagerService service) {
super("Load PDB", true, false, true, true); super("Load PDB", true, false, true, true);
this.program = program; this.program = program;
this.pdbFile = pdbFile; this.pdbFile = pdbFile;
this.useMsDiaParser = useMsDiaParser; this.useMsDiaParser = useMsDiaParser;
this.restrictions = restrictions; this.control = control;
this.service = service; this.service = service;
} }
@ -97,8 +97,8 @@ class LoadPdbTask extends Task {
}; };
try { try {
AutoAnalysisManager.getAnalysisManager(program) AutoAnalysisManager.getAnalysisManager(program).scheduleWorker(worker, null, true,
.scheduleWorker(worker, null, true, wrappedMonitor); wrappedMonitor);
if (log.hasMessages()) { if (log.hasMessages()) {
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File", MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
"There were warnings/errors loading the PDB file.", log.toString(), "There were warnings/errors loading the PDB file.", log.toString(),
@ -157,12 +157,12 @@ class LoadPdbTask extends Task {
PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions(); PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions();
pdbApplicatorOptions.setRestrictions(restrictions); pdbApplicatorOptions.setProcessingControl(control);
PdbProgramAttributes programAttributes = new PdbProgramAttributes(program); PdbProgramAttributes programAttributes = new PdbProgramAttributes(program);
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse(
.parse(pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) { pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
PdbIdentifiers identifiers = pdb.getIdentifiers(); PdbIdentifiers identifiers = pdb.getIdentifiers();
if (!PdbLocator.verifyPdbSignature(programAttributes, identifiers)) { if (!PdbLocator.verifyPdbSignature(programAttributes, identifiers)) {

View file

@ -30,7 +30,7 @@ import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.services.DataTypeManagerService; import ghidra.app.services.DataTypeManagerService;
import ghidra.app.util.bin.format.pdb.PdbParser; import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions; import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus; import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -124,7 +124,7 @@ public class PdbPlugin extends Plugin {
} }
boolean useMsDiaParser = optionsDialog.useMsDiaParser(); boolean useMsDiaParser = optionsDialog.useMsDiaParser();
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions(); PdbApplicatorControl control = optionsDialog.getApplicatorControl();
tool.setStatusInfo(""); tool.setStatusInfo("");
@ -139,7 +139,7 @@ public class PdbPlugin extends Plugin {
// dialog prompts. We want the task progress dialog to be showing before any // dialog prompts. We want the task progress dialog to be showing before any
// prompts appear. // prompts appear.
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, restrictions, service); LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, control, service);
TaskBuilder.withTask(task) TaskBuilder.withTask(task)
.setStatusTextAlignment(SwingConstants.LEADING) .setStatusTextAlignment(SwingConstants.LEADING)
.setLaunchDelay(0); .setLaunchDelay(0);

View file

@ -37,7 +37,7 @@ import ghidra.app.util.bin.format.pdb.PdbParser;
import ghidra.app.util.bin.format.pdb.PdbParser.PdbFileType; import ghidra.app.util.bin.format.pdb.PdbParser.PdbFileType;
import ghidra.app.util.pdb.PdbLocator; import ghidra.app.util.pdb.PdbLocator;
import ghidra.app.util.pdb.PdbProgramAttributes; import ghidra.app.util.pdb.PdbProgramAttributes;
import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorRestrictions; import ghidra.app.util.pdb.pdbapplicator.PdbApplicatorControl;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus; import ghidra.framework.plugintool.util.PluginStatus;
@ -808,7 +808,7 @@ public class PdbSymbolServerPlugin extends Plugin {
} }
boolean useMsDiaParser = optionsDialog.useMsDiaParser(); boolean useMsDiaParser = optionsDialog.useMsDiaParser();
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions(); PdbApplicatorControl control = optionsDialog.getApplicatorControl();
tool.setStatusInfo(""); tool.setStatusInfo("");
@ -822,7 +822,7 @@ public class PdbSymbolServerPlugin extends Plugin {
TaskLauncher TaskLauncher
.launch( .launch(
new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, restrictions, new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, control,
service)); service));
} }
catch (Exception pe) { catch (Exception pe) {