mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-911 - Improve PDB reader/applicator options
This commit is contained in:
parent
5234839b24
commit
b510852b83
11 changed files with 409 additions and 366 deletions
|
@ -27,12 +27,12 @@ import ghidra.app.util.importer.MessageLog;
|
|||
import ghidra.app.util.opinion.PeLoader;
|
||||
import ghidra.app.util.pdb.PdbLocator;
|
||||
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.options.OptionType;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.CharsetInfo;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
|
@ -92,105 +92,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
"If checked, specifically searching for PDB in PE-Header-Specified Location.";
|
||||
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
|
||||
//==============================================================================================
|
||||
|
@ -256,9 +157,8 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
PdbProgramAttributes programAttributes = new PdbProgramAttributes(program);
|
||||
if (programAttributes.isPdbLoaded()) {
|
||||
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.");
|
||||
Msg.info(this, ">> Clear 'PDB Loaded' program property or use Load PDB action if " +
|
||||
"additional PDB processing required.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -267,8 +167,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
return true;
|
||||
}
|
||||
|
||||
setPdbLogging(log);
|
||||
|
||||
String pdbFilename;
|
||||
if (doForceLoad) {
|
||||
if (!confirmFile(forceLoadFile)) {
|
||||
|
@ -361,53 +259,16 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
options.registerOption(OPTION_NAME_FORCELOAD_FILE, OptionType.FILE_TYPE,
|
||||
DEFAULT_FORCE_LOAD_FILE, null, OPTION_DESCRIPTION_FORCELOAD_FILE);
|
||||
}
|
||||
options.registerOption(OPTION_NAME_SYMBOLPATH, OptionType.FILE_TYPE,
|
||||
symbolsRepositoryDir, null, OPTION_DESCRIPTION_SYMBOLPATH);
|
||||
options.registerOption(OPTION_NAME_SYMBOLPATH, OptionType.FILE_TYPE, symbolsRepositoryDir,
|
||||
null, OPTION_DESCRIPTION_SYMBOLPATH);
|
||||
options.registerOption(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath, null,
|
||||
OPTION_DESCRIPTION_INCLUDE_PE_PDB_PATH);
|
||||
|
||||
// PdbReaderOptions
|
||||
getPdbReaderOptions();
|
||||
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);
|
||||
}
|
||||
pdbReaderOptions.registerOptions(options);
|
||||
pdbApplicatorOptions.registerAnalyzerOptions(options);
|
||||
|
||||
// PdbApplicatorOptions
|
||||
getPdbApplicatorOptions();
|
||||
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);
|
||||
}
|
||||
pdbReaderOptions.loadOptions(options);
|
||||
pdbApplicatorOptions.loadAnalyzerOptions(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -427,33 +288,8 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
includePeSpecifiedPdbPath =
|
||||
options.getBoolean(OPTION_NAME_INCLUDE_PE_PDB_PATH, includePeSpecifiedPdbPath);
|
||||
|
||||
// PdbReaderOptions
|
||||
pdbLogging = options.getBoolean(OPTION_NAME_PDB_READER_ANALYZER_LOGGING, pdbLogging);
|
||||
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();
|
||||
pdbReaderOptions.loadOptions(options);
|
||||
pdbApplicatorOptions.loadAnalyzerOptions(options);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
|
@ -497,54 +333,6 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
|
|||
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) {
|
||||
return path.isDirectory();
|
||||
}
|
||||
|
|
|
@ -30,11 +30,9 @@ import ghidra.util.Msg;
|
|||
*/
|
||||
public class PdbLog {
|
||||
|
||||
private static File logFile;
|
||||
private static Writer nullWriter = new NullWriter();
|
||||
private static Writer nullWriter;
|
||||
private static Writer fileWriter;
|
||||
private static Writer writer = nullWriter;
|
||||
private static boolean enabled;
|
||||
private static boolean enabled = false;
|
||||
|
||||
/**
|
||||
* 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...)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -63,11 +52,11 @@ public class PdbLog {
|
|||
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method
|
||||
* uses a format string and a variable arguments list of lambdas to allow for deferred
|
||||
* processing of the message to output. Thus, when message output is disabled, the client
|
||||
* does not endure as much cost in supplying a message string that is not used.
|
||||
* does not endure as much cost in supplying a message string that is not used.
|
||||
* @param format a {@link String} format list as would be used to a printf() function, but
|
||||
* which must only specify {@code %s} {@link String} outputs.
|
||||
* @param suppliers variable number of {@link Supplier}<{@link String}> arguments. The
|
||||
* number must match the number of {@code %s} outputs in the format string.
|
||||
* number must match the number of {@code %s} outputs in the format string.
|
||||
* @see #setEnabled(boolean)
|
||||
*/
|
||||
// We know this is @SafeVarags (or SuppressWarnings("unchecked")) on potential
|
||||
|
@ -85,6 +74,7 @@ public class PdbLog {
|
|||
varArgs[i] = var;
|
||||
}
|
||||
try {
|
||||
Writer writer = getWriter();
|
||||
writer.append(String.format(format, varArgs));
|
||||
writer.append("\n");
|
||||
writer.flush();
|
||||
|
@ -98,7 +88,7 @@ public class PdbLog {
|
|||
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method
|
||||
* uses a {@link Supplier}<{@link String}> to allow for deferred processing of the message
|
||||
* to output. Thus, when message output is disabled, the client does not endure as much cost
|
||||
* in supplying a message string that is not used.
|
||||
* in supplying a message string that is not used.
|
||||
* @param supplier a {@link Supplier}<{@link String}> that supplies a {@link String}
|
||||
* message to be output.
|
||||
* @see #setEnabled(boolean)
|
||||
|
@ -109,6 +99,7 @@ public class PdbLog {
|
|||
}
|
||||
|
||||
try {
|
||||
Writer writer = getWriter();
|
||||
writer.append(supplier.get());
|
||||
writer.append("\n");
|
||||
writer.flush();
|
||||
|
@ -125,6 +116,7 @@ public class PdbLog {
|
|||
*/
|
||||
public static void message(String message) {
|
||||
try {
|
||||
Writer writer = getWriter();
|
||||
writer.append(message);
|
||||
writer.append("\n");
|
||||
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
|
||||
* deletes existing contents of the log file.
|
||||
* Returns the {@link Writer} for logging.
|
||||
* @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.
|
||||
*/
|
||||
private static Writer createFileWriter() throws IOException {
|
||||
|
||||
/*
|
||||
* 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
|
||||
* same log file name with not date or process ID attributes.
|
||||
*/
|
||||
logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log");
|
||||
if (logFile.exists()) {
|
||||
logFile.delete();
|
||||
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
|
||||
* delete the log contents upon initial opening. New log writing always uses the
|
||||
* same log file name with not date or process ID attributes.
|
||||
*/
|
||||
File logFile = new File(Application.getUserSettingsDirectory(), "pdb.analyzer.log");
|
||||
if (logFile.exists()) {
|
||||
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) {
|
||||
|
@ -215,7 +229,6 @@ public class PdbLog {
|
|||
// squash
|
||||
}
|
||||
Msg.error(PdbLog.class, "IOException encountered; disabling writer", exception);
|
||||
writer = nullWriter;
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.framework.options.Options;
|
||||
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
|
||||
|
@ -27,28 +31,103 @@ import ghidra.program.model.data.CharsetInfo;
|
|||
*/
|
||||
public class PdbReaderOptions extends Exception {
|
||||
|
||||
private static final String DEFAULT_ONE_BYTE_CHARSET_NAME = CharsetInfo.UTF8;
|
||||
private static final String DEFAULT_TWO_BYTE_CHARSET_NAME = CharsetInfo.UTF16;
|
||||
// Developer turn on/off options that are in still in development.
|
||||
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 =
|
||||
CharsetInfo.getInstance().getCharsetNamesWithCharSize(1);
|
||||
private static List<String> twoByteCharsetNames =
|
||||
CharsetInfo.getInstance().getCharsetNamesWithCharSize(2);
|
||||
|
||||
private String oneByteCharsetName;
|
||||
private String twoByteCharsetName;
|
||||
|
||||
private Charset oneByteCharset;
|
||||
private Charset twoByteCharset;
|
||||
private Charset wideCharset;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
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;
|
||||
twoByteCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME;
|
||||
wideCharCharsetName = DEFAULT_TWO_BYTE_CHARSET_NAME;
|
||||
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)) {
|
||||
throw new IllegalArgumentException("Unknown TwoByteCharset: " + name);
|
||||
}
|
||||
twoByteCharset = Charset.forName(name);
|
||||
twoByteCharsetName = name;
|
||||
wideCharset = Charset.forName(name);
|
||||
wideCharCharsetName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -108,7 +187,7 @@ public class PdbReaderOptions extends Exception {
|
|||
* @return the name of the Charset.
|
||||
*/
|
||||
public String getTwoByteCharsetName() {
|
||||
return twoByteCharsetName;
|
||||
return wideCharCharsetName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +195,7 @@ public class PdbReaderOptions extends Exception {
|
|||
* @return the name of the Wchar Charset.
|
||||
*/
|
||||
public String getWideCharCharsetName() {
|
||||
return twoByteCharsetName;
|
||||
return wideCharCharsetName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +211,7 @@ public class PdbReaderOptions extends Exception {
|
|||
* @return the Charset.
|
||||
*/
|
||||
public Charset getTwoByteCharset() {
|
||||
return twoByteCharset;
|
||||
return wideCharset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,7 +219,6 @@ public class PdbReaderOptions extends Exception {
|
|||
* @return the Wchar Charset.
|
||||
*/
|
||||
public Charset getWideCharCharset() {
|
||||
return twoByteCharset;
|
||||
return wideCharset;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -340,7 +340,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
|
|||
// TODO: Investigate. We should do this check for some classes somewhere. Should
|
||||
// we do it here. Set breakpoint here to investigate.
|
||||
}
|
||||
classType.createLayout(applicator.getPdbApplicatorOptions().getClassLayout(),
|
||||
classType.createLayout(applicator.getPdbApplicatorOptions().getCompositeLayout(),
|
||||
applicator.getVbtManager(), applicator.getCancelOnlyWrappingMonitor());
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.util.pdb.pdbapplicator;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
|
@ -140,7 +139,7 @@ public class PdbApplicator {
|
|||
* <PRE>
|
||||
* false = simple namespace
|
||||
* true = class namespace
|
||||
* </PRE>
|
||||
* </PRE>
|
||||
*/
|
||||
private Map<SymbolPath, Boolean> isClassByNamespace;
|
||||
|
||||
|
@ -190,19 +189,20 @@ public class PdbApplicator {
|
|||
initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam,
|
||||
applicatorOptionsParam, monitorParam, logParam);
|
||||
|
||||
switch (applicatorOptions.getRestrictions()) {
|
||||
switch (applicatorOptions.getProcessingControl()) {
|
||||
case DATA_TYPES_ONLY:
|
||||
processTypes();
|
||||
break;
|
||||
case PUBLIC_SYMBOLS_ONLY:
|
||||
processPublicSymbols();
|
||||
break;
|
||||
case NONE:
|
||||
case ALL:
|
||||
processTypes();
|
||||
processSymbols();
|
||||
break;
|
||||
default:
|
||||
throw new PdbException("Invalid Restriction");
|
||||
throw new PdbException("PDB: Invalid Application Control: " +
|
||||
applicatorOptions.getProcessingControl());
|
||||
}
|
||||
|
||||
if (program != null) {
|
||||
|
@ -346,15 +346,16 @@ public class PdbApplicator {
|
|||
if (programParam == null) {
|
||||
if (dataTypeManagerParam == null) {
|
||||
throw new PdbException(
|
||||
"programParam and dataTypeManagerParam may not both be null.");
|
||||
"PDB: programParam and dataTypeManagerParam may not both be 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(
|
||||
"programParam may not be null for the chosen PdbApplicatorRestrictions: " +
|
||||
applicatorOptions.getRestrictions());
|
||||
"PDB: programParam and imageBaseParam may not both be null.");
|
||||
}
|
||||
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;
|
||||
|
@ -470,7 +471,7 @@ public class PdbApplicator {
|
|||
// Information for a putative PdbTypeApplicator:
|
||||
|
||||
/**
|
||||
* Returns the {@link DataTypeManager} associated with this analyzer.
|
||||
* Returns the {@link DataTypeManager} associated with this analyzer.
|
||||
* @return DataTypeManager which this analyzer is using.
|
||||
*/
|
||||
DataTypeManager getDataTypeManager() {
|
||||
|
@ -502,8 +503,8 @@ public class PdbApplicator {
|
|||
|
||||
/**
|
||||
* Returns the {@link CategoryPath} for a typedef with with the give {@link SymbolPath} and
|
||||
* module number; 1 <= moduleNumber <= {@link PdbDebugInfo#getNumModules()},
|
||||
* except that modeleNumber of 0 represents publics/globals.
|
||||
* module number; 1 <= moduleNumber <= {@link PdbDebugInfo#getNumModules()},
|
||||
* except that modeleNumber of 0 represents publics/globals.
|
||||
* @param moduleNumber module number
|
||||
* @param symbolPath SymbolPath of the symbol
|
||||
* @return the CategoryPath
|
||||
|
@ -628,7 +629,7 @@ public class PdbApplicator {
|
|||
return sectionContribution.getModule();
|
||||
}
|
||||
}
|
||||
throw new PdbException("Module not found for section/offset");
|
||||
throw new PdbException("PDB: Module not found for section/offset");
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
|
@ -918,7 +919,7 @@ public class PdbApplicator {
|
|||
}
|
||||
|
||||
//==============================================================================================
|
||||
//
|
||||
//
|
||||
//==============================================================================================
|
||||
Register getRegister(String pdbRegisterName) {
|
||||
return registerNameToRegisterMapper.getRegister(pdbRegisterName);
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
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 {
|
||||
NONE("None"), DATA_TYPES_ONLY("Data Types Only"), PUBLIC_SYMBOLS_ONLY("Public Symbols Only");
|
||||
public enum PdbApplicatorControl {
|
||||
ALL("Process All"),
|
||||
DATA_TYPES_ONLY("Data Types Only"),
|
||||
PUBLIC_SYMBOLS_ONLY("Public Symbols Only");
|
||||
|
||||
private final String label;
|
||||
|
||||
|
@ -28,7 +30,7 @@ public enum PdbApplicatorRestrictions {
|
|||
return label;
|
||||
}
|
||||
|
||||
private PdbApplicatorRestrictions(String label) {
|
||||
private PdbApplicatorControl(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
package ghidra.app.util.pdb.pdbapplicator;
|
||||
|
||||
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
|
||||
|
@ -24,54 +26,215 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
|
|||
*/
|
||||
public class PdbApplicatorOptions {
|
||||
|
||||
public static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false;
|
||||
public static final boolean DEFAULT_APPLY_INSTRUCTION_LABELS = 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;
|
||||
// Developer turn on/off options that are in still in development.
|
||||
private static final boolean developerMode = false;
|
||||
|
||||
// TODO: set the following to true if we come up with a reasonably good solution
|
||||
public static final boolean DEFAULT_APPLY_FUNCTION_VARIABLES = false;
|
||||
// Applicator Control.
|
||||
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 =
|
||||
ObjectOrientedClassLayout.MEMBERS_ONLY;
|
||||
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
|
||||
// ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX;
|
||||
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
|
||||
// ObjectOrientedClassLayout.SIMPLE_COMPLEX;
|
||||
// public static final ObjectOrientedClassLayout DEFAULT_CLASS_LAYOUT =
|
||||
// ObjectOrientedClassLayout.COMPLEX;
|
||||
|
||||
//==============================================================================================
|
||||
// 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 static final boolean DEFAULT_APPLY_CODE_SCOPE_BLOCK_COMMENTS = false;
|
||||
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 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 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
|
||||
*/
|
||||
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;
|
||||
applyInstructionLabels = DEFAULT_APPLY_INSTRUCTION_LABELS;
|
||||
restrictions = DEFAULT_RESTRICTIONS;
|
||||
remapAddressesUsingExistingPublicSymbols = DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
|
||||
control = DEFAULT_CONTROL;
|
||||
remapAddressUsingExistingPublicMangledSymbols =
|
||||
DEFAULT_REMAP_ADDRESSES_USING_EXISTING_SYMBOLS;
|
||||
allowDemotePrimaryMangledSymbols = DEFAULT_ALLOW_DEMOTE_PRIMARY_MANGLED_SYMBOLS;
|
||||
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
|
||||
* @param restrictions the restrictions
|
||||
* Set processing control for PdbApplicator
|
||||
* @param control the processing control
|
||||
*/
|
||||
public void setRestrictions(PdbApplicatorRestrictions restrictions) {
|
||||
this.restrictions = restrictions;
|
||||
public void setProcessingControl(PdbApplicatorControl control) {
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current restrictions on PdbApplicator processing
|
||||
* @return the restrictions
|
||||
* Returns the current processing control for the PdbApplicator
|
||||
* @return the processing control
|
||||
*/
|
||||
public PdbApplicatorRestrictions getRestrictions() {
|
||||
return restrictions;
|
||||
public PdbApplicatorControl getProcessingControl() {
|
||||
return control;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +291,7 @@ public class PdbApplicatorOptions {
|
|||
* @param enable {@code true} to turn remapAddressesUsingExistingPublicSymbols on
|
||||
*/
|
||||
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."
|
||||
*/
|
||||
public boolean remapAddressUsingExistingPublicSymbols() {
|
||||
return remapAddressesUsingExistingPublicSymbols;
|
||||
return remapAddressUsingExistingPublicMangledSymbols;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,16 +342,15 @@ public class PdbApplicatorOptions {
|
|||
* Set the class layout.
|
||||
* @param classLayout composite layout
|
||||
*/
|
||||
public void setClassLayout(ObjectOrientedClassLayout classLayout) {
|
||||
this.classLayout = classLayout;
|
||||
public void setCompositeLayout(ObjectOrientedClassLayout classLayout) {
|
||||
this.compositeLayout = classLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the physical layout out classes.
|
||||
* @return the class layout.
|
||||
*/
|
||||
public ObjectOrientedClassLayout getClassLayout() {
|
||||
return classLayout;
|
||||
public ObjectOrientedClassLayout getCompositeLayout() {
|
||||
return compositeLayout;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import docking.DialogComponentProvider;
|
|||
import docking.DockingWindowManager;
|
||||
import docking.widgets.combobox.GComboBox;
|
||||
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;
|
||||
|
||||
class AskPdbOptionsDialog extends DialogComponentProvider {
|
||||
|
@ -32,12 +32,12 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
private boolean isCanceled;
|
||||
|
||||
private boolean useMsDiaParser;
|
||||
private PdbApplicatorRestrictions restrictions = PdbApplicatorRestrictions.NONE;
|
||||
private PdbApplicatorControl control = PdbApplicatorControl.ALL;
|
||||
|
||||
/**
|
||||
* Popup PDB loader options
|
||||
* @param parent parent component or null
|
||||
* @param isPdbFile true if file to be loaded is a PDB file, false
|
||||
* @param isPdbFile true if file to be loaded is a PDB file, false
|
||||
* if MsDia XML file.
|
||||
*/
|
||||
AskPdbOptionsDialog(Component parent, boolean isPdbFile) {
|
||||
|
@ -48,11 +48,11 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
|
||||
JPanel optionsPanel = new JPanel(new PairLayout(10, 10));
|
||||
|
||||
final GComboBox<PdbApplicatorRestrictions> restrictionsCombo =
|
||||
new GComboBox<>(PdbApplicatorRestrictions.values());
|
||||
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE);
|
||||
restrictionsCombo.addActionListener(e -> {
|
||||
restrictions = (PdbApplicatorRestrictions) restrictionsCombo.getSelectedItem();
|
||||
final GComboBox<PdbApplicatorControl> controlCombo =
|
||||
new GComboBox<>(PdbApplicatorControl.values());
|
||||
controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
|
||||
controlCombo.addActionListener(e -> {
|
||||
control = (PdbApplicatorControl) controlCombo.getSelectedItem();
|
||||
});
|
||||
|
||||
optionsPanel.add(new JLabel("PDB Parser:"));
|
||||
|
@ -63,12 +63,12 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
final GComboBox<String> combo =
|
||||
new GComboBox<>(new String[] { "PDB Universal", "PDB MSDIA" });
|
||||
combo.setSelectedIndex(0);
|
||||
restrictionsCombo.setEnabled(!useMsDiaParser);
|
||||
controlCombo.setEnabled(!useMsDiaParser);
|
||||
combo.addActionListener(e -> {
|
||||
useMsDiaParser = (combo.getSelectedIndex() == 1);
|
||||
restrictionsCombo.setEnabled(!useMsDiaParser);
|
||||
controlCombo.setEnabled(!useMsDiaParser);
|
||||
if (useMsDiaParser) {
|
||||
restrictionsCombo.setSelectedItem(PdbApplicatorRestrictions.NONE);
|
||||
controlCombo.setSelectedItem(PdbApplicatorControl.ALL);
|
||||
}
|
||||
});
|
||||
optionsPanel.add(combo);
|
||||
|
@ -85,8 +85,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
return; // no interaction currently required
|
||||
}
|
||||
|
||||
optionsPanel.add(new JLabel("Restrictions:"));
|
||||
optionsPanel.add(restrictionsCombo);
|
||||
optionsPanel.add(new JLabel("Control:"));
|
||||
optionsPanel.add(controlCombo);
|
||||
|
||||
panel.add(optionsPanel, BorderLayout.CENTER);
|
||||
|
||||
|
@ -101,7 +101,6 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
DockingWindowManager.showDialog(parent, AskPdbOptionsDialog.this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void applyCallback() {
|
||||
isCanceled = false;
|
||||
|
@ -122,8 +121,8 @@ class AskPdbOptionsDialog extends DialogComponentProvider {
|
|||
return useMsDiaParser;
|
||||
}
|
||||
|
||||
PdbApplicatorRestrictions getApplicatorRestrictions() {
|
||||
return restrictions;
|
||||
PdbApplicatorControl getApplicatorControl() {
|
||||
return control;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,15 +44,15 @@ class LoadPdbTask extends Task {
|
|||
private DataTypeManagerService service;
|
||||
private final Program program;
|
||||
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,
|
||||
PdbApplicatorRestrictions restrictions, DataTypeManagerService service) {
|
||||
LoadPdbTask(Program program, File pdbFile, boolean useMsDiaParser, PdbApplicatorControl control,
|
||||
DataTypeManagerService service) {
|
||||
super("Load PDB", true, false, true, true);
|
||||
this.program = program;
|
||||
this.pdbFile = pdbFile;
|
||||
this.useMsDiaParser = useMsDiaParser;
|
||||
this.restrictions = restrictions;
|
||||
this.control = control;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
|
@ -97,8 +97,8 @@ class LoadPdbTask extends Task {
|
|||
};
|
||||
|
||||
try {
|
||||
AutoAnalysisManager.getAnalysisManager(program)
|
||||
.scheduleWorker(worker, null, true, wrappedMonitor);
|
||||
AutoAnalysisManager.getAnalysisManager(program).scheduleWorker(worker, null, true,
|
||||
wrappedMonitor);
|
||||
if (log.hasMessages()) {
|
||||
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
|
||||
"There were warnings/errors loading the PDB file.", log.toString(),
|
||||
|
@ -147,7 +147,7 @@ class LoadPdbTask extends Task {
|
|||
return false;
|
||||
}
|
||||
|
||||
// NOTE: OptionDialog will not display an empty line
|
||||
// NOTE: OptionDialog will not display an empty line
|
||||
private static final String BLANK_LINE = " \n";
|
||||
|
||||
private boolean parseWithNewParser(MessageLog log, TaskMonitor monitor)
|
||||
|
@ -157,12 +157,12 @@ class LoadPdbTask extends Task {
|
|||
|
||||
PdbApplicatorOptions pdbApplicatorOptions = new PdbApplicatorOptions();
|
||||
|
||||
pdbApplicatorOptions.setRestrictions(restrictions);
|
||||
pdbApplicatorOptions.setProcessingControl(control);
|
||||
|
||||
PdbProgramAttributes programAttributes = new PdbProgramAttributes(program);
|
||||
|
||||
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser
|
||||
.parse(pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
|
||||
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse(
|
||||
pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
|
||||
|
||||
PdbIdentifiers identifiers = pdb.getIdentifiers();
|
||||
if (!PdbLocator.verifyPdbSignature(programAttributes, identifiers)) {
|
||||
|
|
|
@ -30,7 +30,7 @@ import ghidra.app.plugin.PluginCategoryNames;
|
|||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
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.util.PluginStatus;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
@ -124,7 +124,7 @@ public class PdbPlugin extends Plugin {
|
|||
}
|
||||
|
||||
boolean useMsDiaParser = optionsDialog.useMsDiaParser();
|
||||
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions();
|
||||
PdbApplicatorControl control = optionsDialog.getApplicatorControl();
|
||||
|
||||
tool.setStatusInfo("");
|
||||
|
||||
|
@ -139,7 +139,7 @@ public class PdbPlugin extends Plugin {
|
|||
// dialog prompts. We want the task progress dialog to be showing before any
|
||||
// prompts appear.
|
||||
|
||||
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, restrictions, service);
|
||||
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, control, service);
|
||||
TaskBuilder.withTask(task)
|
||||
.setStatusTextAlignment(SwingConstants.LEADING)
|
||||
.setLaunchDelay(0);
|
||||
|
|
|
@ -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.pdb.PdbLocator;
|
||||
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.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
@ -808,7 +808,7 @@ public class PdbSymbolServerPlugin extends Plugin {
|
|||
}
|
||||
|
||||
boolean useMsDiaParser = optionsDialog.useMsDiaParser();
|
||||
PdbApplicatorRestrictions restrictions = optionsDialog.getApplicatorRestrictions();
|
||||
PdbApplicatorControl control = optionsDialog.getApplicatorControl();
|
||||
|
||||
tool.setStatusInfo("");
|
||||
|
||||
|
@ -822,7 +822,7 @@ public class PdbSymbolServerPlugin extends Plugin {
|
|||
|
||||
TaskLauncher
|
||||
.launch(
|
||||
new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, restrictions,
|
||||
new LoadPdbTask(currentProgram, downloadedPdb, useMsDiaParser, control,
|
||||
service));
|
||||
}
|
||||
catch (Exception pe) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue