GP-2367 - PDB U - cleanup: remove Abstract from some names, incorporate filename and monitor into MSF and make available to PDB and other classes, better employ monitor in reader, fix some javadoc

This commit is contained in:
ghizard 2022-09-09 16:23:09 -04:00
parent 6842712129
commit e7846664a8
67 changed files with 1583 additions and 1559 deletions

View file

@ -201,11 +201,10 @@ public class Pagedump extends DumpFile {
applicatorOptions.setProcessingControl(PdbApplicatorControl.DATA_TYPES_ONLY); applicatorOptions.setProcessingControl(PdbApplicatorControl.DATA_TYPES_ONLY);
try (AbstractPdb pdb = PdbParser.parse(pdbFile.getPath(), readerOptions, monitor)) { try (AbstractPdb pdb = PdbParser.parse(pdbFile.getPath(), readerOptions, monitor)) {
monitor.setMessage("PDB: Parsing " + pdbFile + "..."); monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize(monitor); pdb.deserialize();
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdbFile.getPath(), pdb); DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb);
applicator.applyTo(program, dtm, program.getImageBase(), applicator.applyTo(program, dtm, program.getImageBase(),
applicatorOptions, monitor, applicatorOptions, (MessageLog) null);
(MessageLog) null);
} }
catch (PdbException | IOException | CancelledException e) { catch (PdbException | IOException | CancelledException e) {
Msg.error(this, e.getMessage()); Msg.error(this, e.getMessage());

View file

@ -63,7 +63,7 @@ public class PdbDeveloperDumpScript extends GhidraScript {
monitor.setMessage(message); monitor.setMessage(message);
Msg.info(this, message); Msg.info(this, message);
try (AbstractPdb pdb = PdbParser.parse(pdbFileName, new PdbReaderOptions(), monitor)) { try (AbstractPdb pdb = PdbParser.parse(pdbFileName, new PdbReaderOptions(), monitor)) {
pdb.deserialize(monitor); pdb.deserialize();
FileWriter fileWriter = new FileWriter(dumpFile); FileWriter fileWriter = new FileWriter(dumpFile);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
outputHeaderMessage(bufferedWriter, pdbFileName); outputHeaderMessage(bufferedWriter, pdbFileName);

View file

@ -86,7 +86,7 @@ public class PdbDeveloperDumpSetScript extends GhidraScript {
println("Processing PDB Dump of: " + entry.input()); println("Processing PDB Dump of: " + entry.input());
try (AbstractPdb pdb = try (AbstractPdb pdb =
PdbParser.parse(entry.input(), new PdbReaderOptions(), monitor)) { PdbParser.parse(entry.input(), new PdbReaderOptions(), monitor)) {
pdb.deserialize(monitor); pdb.deserialize();
try (BufferedWriter bufferedWriter = try (BufferedWriter bufferedWriter =
new BufferedWriter(new FileWriter(new File(entry.output())))) { new BufferedWriter(new FileWriter(new File(entry.output())))) {
outputHeaderMessage(bufferedWriter, entry.input()); outputHeaderMessage(bufferedWriter, entry.input());

View file

@ -61,7 +61,7 @@ public class PdbFactory {
try { try {
AbstractPdb pdb = PdbParser.parse(filename, new PdbReaderOptions(), monitor); AbstractPdb pdb = PdbParser.parse(filename, new PdbReaderOptions(), monitor);
PdbIdentifiers identifiers = pdb.getIdentifiers(); PdbIdentifiers identifiers = pdb.getIdentifiers();
pdb.deserialize(monitor); pdb.deserialize();
PdbReaderMetrics metrics = pdb.getPdbReaderMetrics(); PdbReaderMetrics metrics = pdb.getPdbReaderMetrics();
pdbInfo = new PdbInfo(filename, identifiers, pdb, metrics); pdbInfo = new PdbInfo(filename, identifiers, pdb, metrics);
pdbInfoByFile.put(filename, pdbInfo); pdbInfoByFile.put(filename, pdbInfo);

View file

@ -41,7 +41,7 @@ public class PdbQuery {
*/ */
public static AbstractMsType getDataTypeRecord(GhidraScript script, AbstractPdb pdb, public static AbstractMsType getDataTypeRecord(GhidraScript script, AbstractPdb pdb,
int number) { int number) {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface(); TypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) { if (tpi == null) {
println(script, "PDB does not contain a TPI... aborting search."); println(script, "PDB does not contain a TPI... aborting search.");
return null; return null;
@ -75,7 +75,7 @@ public class PdbQuery {
*/ */
public static AbstractMsType getItemTypeRecord(GhidraScript script, AbstractPdb pdb, public static AbstractMsType getItemTypeRecord(GhidraScript script, AbstractPdb pdb,
int number) { int number) {
AbstractTypeProgramInterface ipi = pdb.getItemProgramInterface(); TypeProgramInterface ipi = pdb.getItemProgramInterface();
if (ipi == null) { if (ipi == null) {
println(script, "PDB does not contain an IPI... aborting search."); println(script, "PDB does not contain an IPI... aborting search.");
return null; return null;
@ -102,7 +102,7 @@ public class PdbQuery {
/** /**
* Searches PDB data type records that contain the search string. Outputs results to the * Searches PDB data type records that contain the search string. Outputs results to the
* console. * console
* @param script the script for which we are working * @param script the script for which we are working
* @param pdb the PDB to search * @param pdb the PDB to search
* @param searchString the search string * @param searchString the search string
@ -110,7 +110,7 @@ public class PdbQuery {
*/ */
public static void searchDataTypes(GhidraScript script, AbstractPdb pdb, String searchString) public static void searchDataTypes(GhidraScript script, AbstractPdb pdb, String searchString)
throws CancelledException { throws CancelledException {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface(); TypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) { if (tpi == null) {
println(script, "PDB does not contain a TPI... aborting search."); println(script, "PDB does not contain a TPI... aborting search.");
} }
@ -140,7 +140,7 @@ public class PdbQuery {
/** /**
* Searches PDB item records that contain the search string. Outputs results to the * Searches PDB item records that contain the search string. Outputs results to the
* console. * console
* @param script the script for which we are working * @param script the script for which we are working
* @param pdb the PDB to search * @param pdb the PDB to search
* @param searchString the search string * @param searchString the search string
@ -148,7 +148,7 @@ public class PdbQuery {
*/ */
public static void searchItemTypes(GhidraScript script, AbstractPdb pdb, String searchString) public static void searchItemTypes(GhidraScript script, AbstractPdb pdb, String searchString)
throws CancelledException { throws CancelledException {
AbstractTypeProgramInterface ipi = pdb.getItemProgramInterface(); TypeProgramInterface ipi = pdb.getItemProgramInterface();
if (ipi == null) { if (ipi == null) {
println(script, "PDB does not contain an IPI... aborting search."); println(script, "PDB does not contain an IPI... aborting search.");
return; return;
@ -179,7 +179,7 @@ public class PdbQuery {
/** /**
* Searches PDB symbol records that contain the search string. Outputs results to the * Searches PDB symbol records that contain the search string. Outputs results to the
* console. * console
* @param script the script for which we are working * @param script the script for which we are working
* @param pdb the PDB to search * @param pdb the PDB to search
* @param searchString the search string * @param searchString the search string
@ -238,7 +238,7 @@ public class PdbQuery {
/** /**
* Method for outputting a message to the console (if script is not null); otherwise outputs * Method for outputting a message to the console (if script is not null); otherwise outputs
* the message to Msg.info(). * the message to Msg.info()
* @param script the script * @param script the script
* @param message the message to output to the console * @param message the message to output to the console
*/ */

View file

@ -180,10 +180,10 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
try (AbstractPdb pdb = PdbParser.parse(pdbFile.getPath(), pdbReaderOptions, monitor)) { try (AbstractPdb pdb = PdbParser.parse(pdbFile.getPath(), pdbReaderOptions, monitor)) {
monitor.setMessage("PDB: Parsing " + pdbFile + "..."); monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize(monitor); pdb.deserialize();
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdbFile.getPath(), pdb); DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb);
applicator.applyTo(program, program.getDataTypeManager(), program.getImageBase(), applicator.applyTo(program, program.getDataTypeManager(), program.getImageBase(),
pdbApplicatorOptions, monitor, log); pdbApplicatorOptions, log);
} }
catch (PdbException | IOException e) { catch (PdbException | IOException e) {
@ -249,11 +249,11 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
* on the specified program. * on the specified program.
* <p> * <p>
* Normally the analyzer would locate the PDB file on its own, but if a * Normally the analyzer would locate the PDB file on its own, but if a
* headless script wishes to override the analyzer's behaivor, it can * headless script wishes to override the analyzer's behavior, it can
* use this method to specify a file. * use this method to specify a file.
* *
* @param program {@link Program} * @param program the program
* @param pdbFile the pdb file * @param pdbFile the PDB file
*/ */
public static void setPdbFileOption(Program program, File pdbFile) { public static void setPdbFileOption(Program program, File pdbFile) {
PdbAnalyzerCommon.setPdbFileOption(NAME, program, pdbFile); PdbAnalyzerCommon.setPdbFileOption(NAME, program, pdbFile);

View file

@ -20,7 +20,7 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.AbstractMsf; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.Msf;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType; import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
@ -52,7 +52,7 @@ public abstract class AbstractPdb implements AutoCloseable {
//============================================================================================== //==============================================================================================
// Internals // Internals
//============================================================================================== //==============================================================================================
protected AbstractMsf msf; protected Msf msf;
protected PdbReaderOptions readerOptions; protected PdbReaderOptions readerOptions;
@ -63,7 +63,7 @@ public abstract class AbstractPdb implements AutoCloseable {
protected int pdbAge = 0; protected int pdbAge = 0;
protected int dbiAge = 0; protected int dbiAge = 0;
protected AbstractTypeProgramInterface typeProgramInterface; protected TypeProgramInterface typeProgramInterface;
protected PdbDebugInfo debugInfo; protected PdbDebugInfo debugInfo;
protected Processor targetProcessor = Processor.UNKNOWN; protected Processor targetProcessor = Processor.UNKNOWN;
@ -77,7 +77,7 @@ public abstract class AbstractPdb implements AutoCloseable {
protected List<Integer> parameters; protected List<Integer> parameters;
protected NameTable nameTable; protected NameTable nameTable;
protected AbstractTypeProgramInterface itemProgramInterface; //IPI seems to be a TPI. protected TypeProgramInterface itemProgramInterface; //IPI seems to be a TPI.
// Items below begin in Pdb700 // Items below begin in Pdb700
protected GUID guid; // We can return null by not initializing the guid. protected GUID guid; // We can return null by not initializing the guid.
@ -104,10 +104,10 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Parses an address segment typically used by some {@link AbstractMsSymbol} type. In addition, * Parses an address segment typically used by some {@link AbstractMsSymbol} type. In addition,
* {@link PdbReaderMetrics} may be updated for segment information. * {@link PdbReaderMetrics} may be updated for segment information
* @param reader The reader from which to parse the segment. * @param reader the reader from which to parse the segment
* @return The segment. * @return the segment
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
public int parseSegment(PdbByteReader reader) throws PdbException { public int parseSegment(PdbByteReader reader) throws PdbException {
int segment = reader.parseUnsignedShortVal(); int segment = reader.parseUnsignedShortVal();
@ -119,8 +119,8 @@ public abstract class AbstractPdb implements AutoCloseable {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Closes the {@link AbstractPdb} and resources that it uses. * Closes the {@link AbstractPdb} and resources that it uses
* @throws IOException for file I/O reasons. * @throws IOException for file I/O reasons
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
@ -130,26 +130,26 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Returns the {@link PdbReaderOptions} for this PDB. * Returns the {@link PdbReaderOptions} for this PDB
* @return the {@link PdbReaderOptions} for this PDB. * @return the {@link PdbReaderOptions} for this PDB
*/ */
public PdbReaderOptions getPdbReaderOptions() { public PdbReaderOptions getPdbReaderOptions() {
return readerOptions; return readerOptions;
} }
/** /**
* Returns the main {@link PdbIdentifiers} found in the PDB Directory. * Returns the main {@link PdbIdentifiers} found in the PDB Directory
* @return {@link PdbIdentifiers} of information. * @return {@link PdbIdentifiers} of information
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
* @throws PdbException Upon error in processing components. * @throws PdbException upon error in processing components
*/ */
public PdbIdentifiers getIdentifiers() throws IOException, PdbException { public PdbIdentifiers getIdentifiers() throws IOException, PdbException {
parseDBI(); parseDBI();
if (debugInfo != null) { if (debugInfo != null) {
try { try {
// dbiAge and targetProcessor set during deserialization of new DBI header // dbiAge and targetProcessor set during deserialization of new DBI header
debugInfo.deserialize(true, TaskMonitor.DUMMY); debugInfo.deserialize(true);
} }
catch (CancelledException e) { catch (CancelledException e) {
throw new AssertException(e); // unexpected throw new AssertException(e); // unexpected
@ -163,20 +163,19 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Deserializes this PDB from the underlying {@link AbstractMsf}. * Deserializes this PDB from the underlying {@link Msf}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error in processing components
* @throws PdbException Upon error in processing components. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public void deserialize(TaskMonitor monitor) public void deserialize()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// msf should only be null for testing versions of PDB. // msf should only be null for testing versions of PDB.
if (msf == null) { if (msf == null) {
return; return;
} }
deserializeDirectory(monitor); deserializeDirectory();
//directoryStream.dump(Integer.MAX_VALUE); //directoryStream.dump(Integer.MAX_VALUE);
//System.out.println(pdb.dumpDirectory()); //System.out.println(pdb.dumpDirectory());
@ -186,7 +185,7 @@ public abstract class AbstractPdb implements AutoCloseable {
// pdb.dumpStream(3, 0x400); // pdb.dumpStream(3, 0x400);
// pdb.dumpStream(4, 0x400); // pdb.dumpStream(4, 0x400);
deserializeSubstreams(monitor); deserializeSubstreams();
// pdb.dumpSubStreams(); // pdb.dumpSubStreams();
// pdb.dumpGlobalSymbols(); //TODO: evaluate where/who calls. // pdb.dumpGlobalSymbols(); //TODO: evaluate where/who calls.
@ -196,48 +195,48 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Returns the Version Number of the PDB. * Returns the Version Number of the PDB
* @return Version Number of the PDB. * @return Version Number of the PDB
*/ */
public int getVersionNumber() { public int getVersionNumber() {
return versionNumber; return versionNumber;
} }
/** /**
* Returns the Signature of the PDB. * Returns the Signature of the PDB
* @return Signature of the PDB. * @return Signature of the PDB
*/ */
public int getSignature() { public int getSignature() {
return signature; return signature;
} }
/** /**
* Returns the Age of the PDB. * Returns the Age of the PDB
* @return Age of the PDB. * @return Age of the PDB
*/ */
public int getAge() { public int getAge() {
return pdbAge; return pdbAge;
} }
/** /**
* Returns the GUID for the PDB. * Returns the GUID for the PDB
* @return {@link GUID} for the PDB. * @return {@link GUID} for the PDB
*/ */
public GUID getGuid() { public GUID getGuid() {
return guid; return guid;
} }
/** /**
* Tells whether the PDB file has been completely deserialized yet. * Tells whether the PDB file has been completely deserialized yet
* @return True if has been deserialized. * @return {@code true} if has been deserialized
*/ */
public boolean isDeserialized() { public boolean isDeserialized() {
return substreamsDeserialized; return substreamsDeserialized;
} }
/** /**
* Get the index number of the target processor used for compilation. * Get the index number of the target processor used for compilation
* @return Index number of the target processor used for compilation. * @return Index number of the target processor used for compilation
* @see Processor * @see Processor
* @see RegisterName * @see RegisterName
*/ */
@ -246,8 +245,8 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Returns whether there is minimal debug information. * Returns whether there is minimal debug information
* @return {@code true} if there is minimal debug information. * @return {@code true} if there is minimal debug information
*/ */
public boolean hasMinimalDebugInfo() { public boolean hasMinimalDebugInfo() {
return minimalDebugInfo; return minimalDebugInfo;
@ -275,7 +274,7 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Set the age as specified by the new DBI header. A value of 0 corresponds * Set the age as specified by the new DBI header. A value of 0 corresponds
* to the old DBI header. * to the old DBI header
* @param dbiAge age as specified by the new DBI header * @param dbiAge age as specified by the new DBI header
*/ */
void setDbiAge(int dbiAge) { void setDbiAge(int dbiAge) {
@ -283,26 +282,26 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Returns the {@link AbstractTypeProgramInterface} component. * Returns the {@link TypeProgramInterface} component
* @return {@link AbstractTypeProgramInterface} component or null if not available. * @return {@link TypeProgramInterface} component or null if not available
*/ */
public AbstractTypeProgramInterface getTypeProgramInterface() { public TypeProgramInterface getTypeProgramInterface() {
return typeProgramInterface; return typeProgramInterface;
} }
/** /**
* Returns the ItemProgramInterface (of type {@link AbstractTypeProgramInterface}) * Returns the ItemProgramInterface (of type {@link TypeProgramInterface})
* component. * component
* @return ItemProgramInterface (of type {@link AbstractTypeProgramInterface}) component * @return ItemProgramInterface (of type {@link TypeProgramInterface}) component
* or null if not available. * or null if not available
*/ */
public AbstractTypeProgramInterface getItemProgramInterface() { public TypeProgramInterface getItemProgramInterface() {
return itemProgramInterface; return itemProgramInterface;
} }
/** /**
* Returns the {@link PdbDebugInfo} component. * Returns the {@link PdbDebugInfo} component
* @return {@link PdbDebugInfo} component or null if not available. * @return {@link PdbDebugInfo} component or null if not available
*/ */
public PdbDebugInfo getDebugInfo() { public PdbDebugInfo getDebugInfo() {
return debugInfo; return debugInfo;
@ -311,8 +310,8 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Returns the record for the associated record number, which is expected to match the * Returns the record for the associated record number, which is expected to match the
* desired class * desired class
* @param recordNumber the record number. * @param recordNumber the record number
* @return the record. * @return the record
*/ */
public AbstractMsType getTypeRecord(RecordNumber recordNumber) { public AbstractMsType getTypeRecord(RecordNumber recordNumber) {
return getTypeRecord(recordNumber, AbstractMsType.class); return getTypeRecord(recordNumber, AbstractMsType.class);
@ -320,11 +319,11 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Returns the record for the associated record number, which is expected to match the * Returns the record for the associated record number, which is expected to match the
* desired class. * desired class
* @param <T> class return type. * @param <T> class return type
* @param recordNumber record number. * @param recordNumber record number
* @param typeClass desired class type for return. * @param typeClass desired class type for return
* @return the record. * @return the record
*/ */
public <T extends AbstractMsType> T getTypeRecord(RecordNumber recordNumber, public <T extends AbstractMsType> T getTypeRecord(RecordNumber recordNumber,
Class<T> typeClass) { Class<T> typeClass) {
@ -369,18 +368,18 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Returns a name from the {@link NameTable} pertaining to the index argument. * Returns a name from the {@link NameTable} pertaining to the index argument
* @param index Index of the name. * @param index index of the name
* @return Name. * @return name
*/ */
public String getNameFromNameIndex(int index) { public String getNameFromNameIndex(int index) {
return nameTable.getNameFromStreamNumber(index); return nameTable.getNameFromStreamNumber(index);
} }
/** /**
* Returns an index of the {@link String} name argument in the {@link NameTable}. * Returns an index of the {@link String} name argument in the {@link NameTable}
* @param name Name for which to find the index. * @param name name for which to find the index
* @return Index of the name argument. * @return index of the name argument
*/ */
public int getNameIndexFromName(String name) { public int getNameIndexFromName(String name) {
return nameTable.getStreamNumberFromName(name); return nameTable.getStreamNumberFromName(name);
@ -388,9 +387,9 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Returns a name from the {@link NameTable} pertaining to the byte-offset in the block of * Returns a name from the {@link NameTable} pertaining to the byte-offset in the block of
* names for the table. * names for the table
* @param offset Byte-offset of the name in the {@link NameTable} block. * @param offset byte offset of the name in the {@link NameTable} block
* @return Name at the byte offset in the Name Table. * @return name at the byte offset in the Name Table
*/ */
public String getNameStringFromOffset(int offset) { public String getNameStringFromOffset(int offset) {
return nameTable.getNameStringFromOffset(offset); return nameTable.getNameStringFromOffset(offset);
@ -400,43 +399,42 @@ public abstract class AbstractPdb implements AutoCloseable {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Returns the number of bytes needed to store a PDB version number. * Returns the number of bytes needed to store a PDB version number
* location. * @return number of bytes needed to store a PDV version number
* @return Number of bytes needed to store a PDV version number.
*/ */
static int getVersionNumberSize() { static int getVersionNumberSize() {
return VERSION_NUMBER_SIZE; return VERSION_NUMBER_SIZE;
} }
/** /**
* Deserializes PDB Version Number from the PDB Directory Stream in the {@link AbstractMsf}. * Deserializes PDB Version Number from the PDB Directory Stream in the {@link Msf}
* @param msf {@link AbstractMsf} underlying the PDB of which to probe. * @param msf {@link Msf} underlying the PDB of which to probe
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param monitor {@link TaskMonitor} used for checking cancellation
* @return Version number. * @return version number
* @throws IOException on file I/O issues. * @throws IOException on file I/O issues
* @throws PdbException on parsing issues. * @throws PdbException on parsing issues
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
static int deserializeVersionNumber(AbstractMsf msf, TaskMonitor monitor) static int deserializeVersionNumber(Msf msf, TaskMonitor monitor)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
MsfStream directoryStream = msf.getStream(PDB_DIRECTORY_STREAM_NUMBER); MsfStream directoryStream = msf.getStream(PDB_DIRECTORY_STREAM_NUMBER);
if (directoryStream.getLength() < AbstractPdb.getVersionNumberSize()) { if (directoryStream.getLength() < AbstractPdb.getVersionNumberSize()) {
throw new PdbException("Directory Stream too short"); throw new PdbException("Directory Stream too short");
} }
byte[] bytes = directoryStream.read(0, AbstractPdb.getVersionNumberSize(), monitor); byte[] bytes = directoryStream.read(0, AbstractPdb.getVersionNumberSize());
PdbByteReader pdbDirectoryReader = new PdbByteReader(bytes); PdbByteReader pdbDirectoryReader = new PdbByteReader(bytes);
return pdbDirectoryReader.parseInt(); return pdbDirectoryReader.parseInt();
} }
/** /**
* Constructor. * Constructor
* @param msf {@link AbstractMsf} foundation for the PDB. * @param msf {@link Msf} foundation for the PDB
* @param readerOptions {@link PdbReaderOptions} used for processing the PDB. * @param readerOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
* @throws PdbException Upon unknown value for configuration or error in processing components. * @throws PdbException upon unknown value for configuration or error in processing components
*/ */
AbstractPdb(AbstractMsf msf, PdbReaderOptions readerOptions) throws IOException, PdbException { AbstractPdb(Msf msf, PdbReaderOptions readerOptions) throws IOException, PdbException {
this.msf = msf; this.msf = msf;
this.readerOptions = readerOptions; this.readerOptions = readerOptions;
strings = new ArrayList<>(); strings = new ArrayList<>();
@ -446,34 +444,57 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Deserializes the main {@link PdbIdentifiers} found in the PDB Directory from the * Deserializes the main {@link PdbIdentifiers} found in the PDB Directory from the
* {@link PdbByteReader}. * {@link PdbByteReader}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param monitor {@link TaskMonitor} used for checking cancellation
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
* @throws PdbException upon error parsing a field. * @throws PdbException upon error parsing a field
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
abstract void deserializeIdentifiersOnly(TaskMonitor monitor) abstract void deserializeIdentifiersOnly(TaskMonitor monitor)
throws IOException, PdbException, CancelledException; throws IOException, PdbException, CancelledException;
/** /**
* Returns the {@link AbstractMsf} foundation for the PDB. * Returns the filename
* @return {@link AbstractMsf} foundation of the PDB. * @return the filename
*/ */
AbstractMsf getMsf() { public String getFilename() {
return msf.getFilename();
}
/**
* Returns the TaskMonitor
* @return the monitor
*/
public TaskMonitor getMonitor() {
return msf.getMonitor();
}
/**
* Check to see if this monitor has been canceled
* @throws CancelledException if monitor has been cancelled
*/
public void checkCanceled() throws CancelledException {
getMonitor().checkCanceled();
}
/**
* Returns the {@link Msf} foundation for the PDB
* @return {@link Msf} foundation of the PDB
*/
Msf getMsf() {
return msf; return msf;
} }
//TODO Not sure if we will keep this method or if more gets added to it. //TODO Not sure if we will keep this method or if more gets added to it.
/** /**
* Deserializes the sub-streams for this {@link AbstractPdb} object. * Deserializes the sub-streams for this {@link AbstractPdb} object
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error in processing components
* @throws PdbException Upon error in processing components. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserializeSubstreams(TaskMonitor monitor) void deserializeSubstreams()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
if (substreamsDeserialized) { if (substreamsDeserialized) {
@ -482,18 +503,18 @@ public abstract class AbstractPdb implements AutoCloseable {
TypeProgramInterfaceParser tpiParser = new TypeProgramInterfaceParser(); TypeProgramInterfaceParser tpiParser = new TypeProgramInterfaceParser();
typeProgramInterface = tpiParser.parse(this, monitor); typeProgramInterface = tpiParser.parse(this);
if (typeProgramInterface != null) { if (typeProgramInterface != null) {
typeProgramInterface.deserialize(monitor); typeProgramInterface.deserialize();
} }
boolean ipiStreamHasNoName = ItemProgramInterfaceParser.hackCheckNoNameForStream(nameTable); boolean ipiStreamHasNoName = ItemProgramInterfaceParser.hackCheckNoNameForStream(nameTable);
pdbReaderMetrics.witnessIpiDetection(ipiStreamHasNoName, hasIdStream); pdbReaderMetrics.witnessIpiDetection(ipiStreamHasNoName, hasIdStream);
if (hasIdStream || ipiStreamHasNoName) { if (hasIdStream || ipiStreamHasNoName) {
ItemProgramInterfaceParser ipiParser = new ItemProgramInterfaceParser(); ItemProgramInterfaceParser ipiParser = new ItemProgramInterfaceParser();
itemProgramInterface = ipiParser.parse(this, monitor); itemProgramInterface = ipiParser.parse(this);
if (itemProgramInterface != null) { if (itemProgramInterface != null) {
itemProgramInterface.deserialize(monitor); itemProgramInterface.deserialize();
} }
//processDependencyIndexPairList(); //processDependencyIndexPairList();
//dumpDependencyGraph(); //dumpDependencyGraph();
@ -501,7 +522,7 @@ public abstract class AbstractPdb implements AutoCloseable {
parseDBI(); parseDBI();
if (debugInfo != null) { if (debugInfo != null) {
debugInfo.deserialize(false, monitor); debugInfo.deserialize(false);
} }
substreamsDeserialized = true; substreamsDeserialized = true;
@ -517,47 +538,45 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Returns a {@link PdbByteReader} initialized with the complete contents of the * Returns a {@link PdbByteReader} initialized with the complete contents of the
* {@link MsfStream} referenced by {@code streamNumber}. * {@link MsfStream} referenced by {@code streamNumber}
* @param streamNumber The stream number of the {@link MsfStream} from which to load the data. * @param streamNumber the stream number of the {@link MsfStream} from which to load the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return the {@link PdbByteReader}
* @return The {@link PdbByteReader}. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
PdbByteReader getReaderForStreamNumber(int streamNumber, TaskMonitor monitor) PdbByteReader getReaderForStreamNumber(int streamNumber)
throws IOException, CancelledException { throws IOException, CancelledException {
return getReaderForStreamNumber(streamNumber, 0, MsfStream.MAX_STREAM_LENGTH, monitor); return getReaderForStreamNumber(streamNumber, 0, MsfStream.MAX_STREAM_LENGTH);
} }
/** /**
* Returns a {@link PdbByteReader} initialized with up to {@code numToRead} byte of content * Returns a {@link PdbByteReader} initialized with up to {@code numToRead} byte of content
* (less if not available) from the {@link MsfStream} referenced by {@code streamNumber} * (less if not available) from the {@link MsfStream} referenced by {@code streamNumber}
* starting at {@code streamOffset}. * starting at {@code streamOffset}
* @param streamNumber The stream number of the {@link MsfStream} from which to load the data. * @param streamNumber the stream number of the {@link MsfStream} from which to load the data
* @param streamOffset Starting location within the {@link MsfStream} from which to get the * @param streamOffset starting location within the {@link MsfStream} from which to get the
* data. * data
* @param numToRead Number of bytes used to initialize the {@link PdbByteReader}. * @param numToRead number of bytes used to initialize the {@link PdbByteReader}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return the {@link PdbByteReader}
* @return The {@link PdbByteReader}. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
PdbByteReader getReaderForStreamNumber(int streamNumber, int streamOffset, int numToRead, PdbByteReader getReaderForStreamNumber(int streamNumber, int streamOffset, int numToRead)
TaskMonitor monitor) throws IOException, CancelledException { throws IOException, CancelledException {
MsfStream stream = msf.getStream(streamNumber); MsfStream stream = msf.getStream(streamNumber);
numToRead = Math.min(numToRead, stream.getLength() - streamOffset); numToRead = Math.min(numToRead, stream.getLength() - streamOffset);
byte[] bytes = stream.read(streamOffset, numToRead, monitor); byte[] bytes = stream.read(streamOffset, numToRead);
PdbByteReader reader = new PdbByteReader(bytes); PdbByteReader reader = new PdbByteReader(bytes);
return reader; return reader;
} }
/** /**
* Debug method to dump the number of bytes for the specified stream to a {@link String}. * Debug method to dump the number of bytes for the specified stream to a {@link String}
* @param streamNumber The stream number to dump. * @param streamNumber the stream number to dump
* @param maxOut The maximum number of bytes to dump. * @param maxOut the maximum number of bytes to dump
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
String dumpStream(int streamNumber, int maxOut) { String dumpStream(int streamNumber, int maxOut) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -569,21 +588,20 @@ public abstract class AbstractPdb implements AutoCloseable {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes PDB Directory from the {@link PdbByteReader}. * Deserializes PDB Directory from the {@link PdbByteReader}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a field
* @throws PdbException upon error parsing a field. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
abstract void deserializeDirectory(TaskMonitor monitor) abstract void deserializeDirectory()
throws IOException, PdbException, CancelledException; throws IOException, PdbException, CancelledException;
/** /**
* Dumps the PDB Directory to {@link Writer}. This package-protected method is for * Dumps the PDB Directory to {@link Writer}. This package-protected method is for
* debugging only. * debugging only.
* @param writer {@link Writer}. * @param writer {@link Writer}.
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}.
*/ */
public abstract void dumpDirectory(Writer writer) throws IOException; public abstract void dumpDirectory(Writer writer) throws IOException;
@ -592,23 +610,22 @@ public abstract class AbstractPdb implements AutoCloseable {
//============================================================================================== //==============================================================================================
/** /**
* Reads the Directory stream and returns a {@link PdbByteReader} of its contents. * Reads the Directory stream and returns a {@link PdbByteReader} of its contents
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return {@link PdbByteReader} requested
* @return {@link PdbByteReader} requested. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected PdbByteReader getDirectoryReader(TaskMonitor monitor) protected PdbByteReader getDirectoryReader()
throws IOException, CancelledException { throws IOException, CancelledException {
return getReaderForStreamNumber(PDB_DIRECTORY_STREAM_NUMBER, 0, MsfStream.MAX_STREAM_LENGTH, return getReaderForStreamNumber(PDB_DIRECTORY_STREAM_NUMBER, 0,
monitor); MsfStream.MAX_STREAM_LENGTH);
} }
/** /**
* Deserializes the Version, Signature, and Age. * Deserializes the Version, Signature, and Age
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected void deserializeVersionSignatureAge(PdbByteReader reader) throws PdbException { protected void deserializeVersionSignatureAge(PdbByteReader reader) throws PdbException {
versionNumber = reader.parseInt(); versionNumber = reader.parseInt();
@ -617,8 +634,8 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Dumps the Version Signature and Age. This package-protected method is for debugging only. * Dumps the Version Signature and Age. This package-protected method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
protected String dumpVersionSignatureAge() { protected String dumpVersionSignatureAge() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -633,26 +650,25 @@ public abstract class AbstractPdb implements AutoCloseable {
} }
/** /**
* Deserializes the Parameters. * Deserializes the Parameters
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a string
* @throws PdbException upon error parsing a string. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void deserializeParameters(PdbByteReader reader, TaskMonitor monitor) protected void deserializeParameters(PdbByteReader reader)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
nameTable.deserializeDirectory(reader, monitor); nameTable.deserializeDirectory(reader);
// Read the parameters. // Read the parameters.
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); getMonitor().checkCanceled();
int val = reader.parseInt(); int val = reader.parseInt();
parameters.add(val); parameters.add(val);
} }
// Check the parameters for IDs // Check the parameters for IDs
for (int param : parameters) { for (int param : parameters) {
monitor.checkCanceled(); getMonitor().checkCanceled();
if (param == MINIMAL_DEBUG_INFO_PARAM) { if (param == MINIMAL_DEBUG_INFO_PARAM) {
minimalDebugInfo = true; minimalDebugInfo = true;
} }
@ -670,8 +686,8 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Dumps the Parameters to a {@link String}. This package-protected method is for * Dumps the Parameters to a {@link String}. This package-protected method is for
* debugging only. * debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
protected String dumpParameters() { protected String dumpParameters() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -694,11 +710,11 @@ public abstract class AbstractPdb implements AutoCloseable {
/** /**
* Dumps the Sub-Streams to a {@link Writer}. This package-protected method is for * Dumps the Sub-Streams to a {@link Writer}. This package-protected method is for
* debugging only. * debugging only
* @param writer {@link Writer}. * @param writer {@link Writer}
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public void dumpSubStreams(Writer writer) throws IOException, CancelledException, PdbException { public void dumpSubStreams(Writer writer) throws IOException, CancelledException, PdbException {
writer.write("SubStreams--------------------------------------------------\n"); writer.write("SubStreams--------------------------------------------------\n");

View file

@ -21,7 +21,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents Global Symbol Information or Public Symbol Information component of a * This class represents Global Symbol Information or Public Symbol Information component of a
@ -62,16 +61,16 @@ public abstract class AbstractSymbolInformation {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdbIn {@link AbstractPdb} that owns the Abstract Symbol Information to process. * @param pdbIn {@link AbstractPdb} that owns the Abstract Symbol Information to process
*/ */
public AbstractSymbolInformation(AbstractPdb pdbIn) { public AbstractSymbolInformation(AbstractPdb pdbIn) {
pdb = pdbIn; pdb = pdbIn;
} }
/** /**
* Returns the list of symbols for this {@link AbstractSymbolInformation}. * Returns the list of symbols for this {@link AbstractSymbolInformation}
* @return the symbols. * @return the symbols
*/ */
public List<AbstractMsSymbol> getSymbols() { public List<AbstractMsSymbol> getSymbols() {
return symbols; return symbols;
@ -79,7 +78,7 @@ public abstract class AbstractSymbolInformation {
/** /**
* Returns the Offsets of symbols within the symbol table; these are gotten from the * Returns the Offsets of symbols within the symbol table; these are gotten from the
* HashRecords and modified to point to the size field of the symbols in the symbol table. * HashRecords and modified to point to the size field of the symbols in the symbol table
* @return offsets * @return offsets
*/ */
public List<Long> getModifiedHashRecordSymbolOffsets() { public List<Long> getModifiedHashRecordSymbolOffsets() {
@ -90,15 +89,14 @@ public abstract class AbstractSymbolInformation {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Deserialize the {@link AbstractSymbolInformation} from the appropriate stream in the Pdb. * Deserialize the {@link AbstractSymbolInformation} from the appropriate stream in the Pdb
* @param streamNumber the stream number containing the information to deserialize. * @param streamNumber the stream number containing the information to deserialize
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserialize(int streamNumber, TaskMonitor monitor) void deserialize(int streamNumber)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
if (pdb.hasMinimalDebugInfo()) { if (pdb.hasMinimalDebugInfo()) {
hashRecordsBitMapLength = 0x8000; hashRecordsBitMapLength = 0x8000;
@ -113,11 +111,12 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping information from this {@link AbstractSymbolInformation}. * Debug method for dumping information from this {@link AbstractSymbolInformation}
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws IOException upon IOException writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
void dump(Writer writer) throws IOException { void dump(Writer writer) throws IOException, CancelledException {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("AbstractSymbolInformation-----------------------------------\n"); builder.append("AbstractSymbolInformation-----------------------------------\n");
dumpHashHeader(builder); dumpHashHeader(builder);
@ -128,8 +127,8 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping basic information from this {@link AbstractSymbolInformation}. * Debug method for dumping basic information from this {@link AbstractSymbolInformation}
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
*/ */
protected void dumpHashBasics(StringBuilder builder) { protected void dumpHashBasics(StringBuilder builder) {
builder.append("HashBasics--------------------------------------------------\n"); builder.append("HashBasics--------------------------------------------------\n");
@ -143,8 +142,8 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping information from this {@link AbstractSymbolInformation} header. * Debug method for dumping information from this {@link AbstractSymbolInformation} header
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
*/ */
protected void dumpHashHeader(StringBuilder builder) { protected void dumpHashHeader(StringBuilder builder) {
builder.append("HashHeader--------------------------------------------------\n"); builder.append("HashHeader--------------------------------------------------\n");
@ -160,12 +159,11 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Generates a list of symbols from the information that we have. * Generates a list of symbols from the information that we have
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon PDB corruption
* @throws PdbException Upon PDB corruption. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void generateSymbolsList(TaskMonitor monitor) protected void generateSymbolsList()
throws PdbException, CancelledException { throws PdbException, CancelledException {
symbols = new ArrayList<>(); symbols = new ArrayList<>();
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
@ -174,7 +172,7 @@ public abstract class AbstractSymbolInformation {
} }
Map<Long, AbstractMsSymbol> symbolsByOffset = debugInfo.getSymbolsByOffset(); Map<Long, AbstractMsSymbol> symbolsByOffset = debugInfo.getSymbolsByOffset();
for (SymbolHashRecord record : hashRecords) { for (SymbolHashRecord record : hashRecords) {
monitor.checkCanceled(); pdb.checkCanceled();
long offset = record.getOffset() - 2; // Modified offset long offset = record.getOffset() - 2; // Modified offset
AbstractMsSymbol symbol = symbolsByOffset.get(offset); AbstractMsSymbol symbol = symbolsByOffset.get(offset);
modifiedHashRecordSymbolOffsets.add(offset); modifiedHashRecordSymbolOffsets.add(offset);
@ -186,13 +184,15 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping hash records from this {@link AbstractSymbolInformation}. * Debug method for dumping hash records from this {@link AbstractSymbolInformation}
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
* @throws CancelledException upon user cancellation
*/ */
protected void dumpHashRecords(StringBuilder builder) { protected void dumpHashRecords(StringBuilder builder) throws CancelledException {
builder.append("HashRecords-------------------------------------------------\n"); builder.append("HashRecords-------------------------------------------------\n");
builder.append("numHashRecords: " + hashRecords.size() + "\n"); builder.append("numHashRecords: " + hashRecords.size() + "\n");
for (SymbolHashRecord record : hashRecords) { for (SymbolHashRecord record : hashRecords) {
pdb.checkCanceled();
builder.append( builder.append(
String.format("0X%08X 0X%04X\n", record.getOffset(), record.getReferenceCount())); String.format("0X%08X 0X%04X\n", record.getOffset(), record.getReferenceCount()));
} }
@ -200,13 +200,12 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* Deserializes the hash table for the symbols. * Deserializes the hash table for the symbols
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void deserializeHashTable(PdbByteReader reader, TaskMonitor monitor) protected void deserializeHashTable(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
deserializeHashHeader(reader); deserializeHashHeader(reader);
@ -214,7 +213,7 @@ public abstract class AbstractSymbolInformation {
if (headerSignature == HEADER_SIGNATURE) { if (headerSignature == HEADER_SIGNATURE) {
switch (versionNumber) { switch (versionNumber) {
case GSI70: case GSI70:
deserializeGsi70HashTable(reader, monitor); deserializeGsi70HashTable(reader);
break; break;
default: default:
throw new PdbException("Unknown GSI Version Number"); throw new PdbException("Unknown GSI Version Number");
@ -222,15 +221,15 @@ public abstract class AbstractSymbolInformation {
} }
else { else {
reader.reset(); // There was no header reader.reset(); // There was no header
deserializeGsiPre70HashTable(reader, monitor); deserializeGsiPre70HashTable(reader);
} }
} }
/** /**
* Deserialize the header of the Hash from the {@link PdbByteReader} provided. * Deserialize the header of the Hash from the {@link PdbByteReader} provided
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
private void deserializeHashHeader(PdbByteReader reader) throws PdbException { private void deserializeHashHeader(PdbByteReader reader) throws PdbException {
headerSignature = reader.parseInt(); headerSignature = reader.parseInt();
@ -241,13 +240,12 @@ public abstract class AbstractSymbolInformation {
/** /**
* Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI versions * Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI versions
* prior to 7.00 specification. * prior to 7.00 specification
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon unexpected fields
* @throws PdbException Upon unexpected fields. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeGsiPre70HashTable(PdbByteReader reader, TaskMonitor monitor) private void deserializeGsiPre70HashTable(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
int numBucketsBytes = 4 * (numHashRecords + 1); int numBucketsBytes = 4 * (numHashRecords + 1);
@ -264,7 +262,7 @@ public abstract class AbstractSymbolInformation {
hashBucketOffsets = new ArrayList<>(); hashBucketOffsets = new ArrayList<>();
while (bucketsReader.hasMore()) { while (bucketsReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
hashBucketOffsets.add(bucketsReader.parseInt()); hashBucketOffsets.add(bucketsReader.parseInt());
} }
@ -273,18 +271,17 @@ public abstract class AbstractSymbolInformation {
// take the offset and multiple by 2/3 to get the byte offset into the reader for the // take the offset and multiple by 2/3 to get the byte offset into the reader for the
// actual record. Still need to deal with the collision logic after that. // actual record. Still need to deal with the collision logic after that.
deserializeHashRecords(hashRecordsReader, monitor); deserializeHashRecords(hashRecordsReader);
} }
/** /**
* Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI 7.00 * Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI 7.00
* specification. * specification
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon unexpected fields
* @throws PdbException Upon unexpected fields. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeGsi70HashTable(PdbByteReader reader, TaskMonitor monitor) private void deserializeGsi70HashTable(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (reader.numRemaining() != hashRecordsLength + bucketsLength) { if (reader.numRemaining() != hashRecordsLength + bucketsLength) {
@ -297,7 +294,7 @@ public abstract class AbstractSymbolInformation {
PdbByteReader hashRecordsReader = reader.getSubPdbByteReader(hashRecordsLength); PdbByteReader hashRecordsReader = reader.getSubPdbByteReader(hashRecordsLength);
PdbByteReader bucketsReader = reader.getSubPdbByteReader(bucketsLength); PdbByteReader bucketsReader = reader.getSubPdbByteReader(bucketsLength);
deserializedCompressedHashBuckets(bucketsReader, monitor); deserializedCompressedHashBuckets(bucketsReader);
// int i = 0; // int i = 0;
// for (int x : hashBucketOffsets) { // for (int x : hashBucketOffsets) {
@ -308,30 +305,29 @@ public abstract class AbstractSymbolInformation {
// take the offset and multiple by 2/3 to get the byte offset into the reader for the // take the offset and multiple by 2/3 to get the byte offset into the reader for the
// actual record. Still need to deal with the collision logic after that. // actual record. Still need to deal with the collision logic after that.
deserializeHashRecords(hashRecordsReader, monitor); deserializeHashRecords(hashRecordsReader);
} }
/** /**
* Deserializes a compressed set of hash buckets from the {@link PdbByteReader} provided. The * Deserializes a compressed set of hash buckets from the {@link PdbByteReader} provided. The
* data comes as a bit-mapped representation of which indices should contain the data followed * data comes as a bit-mapped representation of which indices should contain the data followed
* by a flat set of hash buckets that will be set at those indices in the order provided. * by a flat set of hash buckets that will be set at those indices in the order provided
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializedCompressedHashBuckets(PdbByteReader reader, TaskMonitor monitor) private void deserializedCompressedHashBuckets(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
PdbByteReader bitEncoderReader = reader.getSubPdbByteReader(hashRecordsBitMapLength); PdbByteReader bitEncoderReader = reader.getSubPdbByteReader(hashRecordsBitMapLength);
// Throw away extra bytes between bit map and buckets. // Throw away extra bytes between bit map and buckets.
reader.getSubPdbByteReader(numExtraBytes); reader.getSubPdbByteReader(numExtraBytes);
while (bitEncoderReader.hasMore() && reader.hasMore()) { while (bitEncoderReader.hasMore() && reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
long val = bitEncoderReader.parseUnsignedIntVal(); long val = bitEncoderReader.parseUnsignedIntVal();
//bitEncoded[index++] = val; //bitEncoded[index++] = val;
for (int bit = 0; bit < 32 && reader.hasMore(); bit++) { for (int bit = 0; bit < 32 && reader.hasMore(); bit++) {
monitor.checkCanceled(); pdb.checkCanceled();
if ((val & 0x01L) == 0x01L) { if ((val & 0x01L) == 0x01L) {
hashBucketOffsets.add(reader.parseInt()); hashBucketOffsets.add(reader.parseInt());
} }
@ -348,7 +344,7 @@ public abstract class AbstractSymbolInformation {
throw new PdbException("Compressed GSI Hash Buckets corrupt"); throw new PdbException("Compressed GSI Hash Buckets corrupt");
} }
while (bitEncoderReader.hasMore()) { while (bitEncoderReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
if (bitEncoderReader.parseUnsignedIntVal() != 0) { if (bitEncoderReader.parseUnsignedIntVal() != 0) {
throw new PdbException("Compressed GSI Hash Buckets corrupt"); throw new PdbException("Compressed GSI Hash Buckets corrupt");
} }
@ -357,17 +353,16 @@ public abstract class AbstractSymbolInformation {
} }
/** /**
* * Deserializes the hash records
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeHashRecords(PdbByteReader reader, TaskMonitor monitor) private void deserializeHashRecords(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
hashRecords = new TreeSet<>(); hashRecords = new TreeSet<>();
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
SymbolHashRecord record = new SymbolHashRecord(); SymbolHashRecord record = new SymbolHashRecord();
record.parse(reader); record.parse(reader);
hashRecords.add(record); hashRecords.add(record);

View file

@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* C11Lines information. As best as we know, only one of C11Lines or C13Lines can be found after * C11Lines information. As best as we know, only one of C11Lines or C13Lines can be found after
@ -48,12 +47,12 @@ public class C11Lines {
private List<List<List<Long>>> offsets; // unsigned int private List<List<List<Long>>> offsets; // unsigned int
private List<List<List<Integer>>> lineNumbers; // unsigned short private List<List<List<Integer>>> lineNumbers; // unsigned short
public static C11Lines parse(AbstractPdb pdb, PdbByteReader reader, TaskMonitor monitor) public static C11Lines parse(AbstractPdb pdb, PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
return new C11Lines(pdb, reader, monitor); return new C11Lines(pdb, reader);
} }
private C11Lines(AbstractPdb pdb, PdbByteReader reader, TaskMonitor monitor) private C11Lines(AbstractPdb pdb, PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (reader.numRemaining() < 4) { if (reader.numRemaining() < 4) {
return; return;
@ -64,7 +63,7 @@ public class C11Lines {
startEnd = new ArrayList<>(); startEnd = new ArrayList<>();
seg = new ArrayList<>(); seg = new ArrayList<>();
for (int i = 0; i < cFile; i++) { for (int i = 0; i < cFile; i++) {
monitor.checkCanceled(); pdb.checkCanceled();
int val = reader.parseInt(); int val = reader.parseInt();
if (val < 0) { if (val < 0) {
throw new PdbException("beyond our max integer limitation"); throw new PdbException("beyond our max integer limitation");
@ -72,13 +71,13 @@ public class C11Lines {
baseSrcFile.add(val); baseSrcFile.add(val);
} }
for (int i = 0; i < cSeg; i++) { for (int i = 0; i < cSeg; i++) {
monitor.checkCanceled(); pdb.checkCanceled();
StartEnd se = new StartEnd(); StartEnd se = new StartEnd();
se.parse(reader); se.parse(reader);
startEnd.add(se); startEnd.add(se);
} }
for (int i = 0; i < cSeg; i++) { for (int i = 0; i < cSeg; i++) {
monitor.checkCanceled(); pdb.checkCanceled();
seg.add(reader.parseUnsignedShortVal()); seg.add(reader.parseUnsignedShortVal());
} }
ccSegs = new ArrayList<>(); ccSegs = new ArrayList<>();
@ -89,14 +88,14 @@ public class C11Lines {
offsets = new ArrayList<>(); offsets = new ArrayList<>();
lineNumbers = new ArrayList<>(); lineNumbers = new ArrayList<>();
for (int i = 0; i < cFile; i++) { for (int i = 0; i < cFile; i++) {
monitor.checkCanceled(); pdb.checkCanceled();
reader.setIndex(baseSrcFile.get(i)); reader.setIndex(baseSrcFile.get(i));
int ccSeg = reader.parseUnsignedShortVal(); int ccSeg = reader.parseUnsignedShortVal();
ccSegs.add(ccSeg); ccSegs.add(ccSeg);
reader.skip(2); // padding reader.skip(2); // padding
List<Integer> baseSrcLn = new ArrayList<>(); List<Integer> baseSrcLn = new ArrayList<>();
for (int j = 0; j < ccSeg; j++) { for (int j = 0; j < ccSeg; j++) {
monitor.checkCanceled(); pdb.checkCanceled();
baseSrcLn.add(reader.parseInt()); baseSrcLn.add(reader.parseInt());
} }
baseSrcLines.add(baseSrcLn); baseSrcLines.add(baseSrcLn);
@ -113,20 +112,20 @@ public class C11Lines {
List<List<Long>> fileSegOffsets = new ArrayList<>(); // unsigned int List<List<Long>> fileSegOffsets = new ArrayList<>(); // unsigned int
List<List<Integer>> fileSegLineNums = new ArrayList<>(); // unsigned short List<List<Integer>> fileSegLineNums = new ArrayList<>(); // unsigned short
for (int j = 0; j < ccSeg; j++) { for (int j = 0; j < ccSeg; j++) {
monitor.checkCanceled(); pdb.checkCanceled();
reader.setIndex(baseSrcLn.get(j)); reader.setIndex(baseSrcLn.get(j));
int segNum = reader.parseUnsignedShortVal(); int segNum = reader.parseUnsignedShortVal();
segNums.add(segNum); segNums.add(segNum);
int cPair = reader.parseUnsignedShortVal(); int cPair = reader.parseUnsignedShortVal();
List<Long> segOffsets = new ArrayList<>(); // unsigned ints List<Long> segOffsets = new ArrayList<>(); // unsigned ints
for (int k = 0; k < cPair; k++) { for (int k = 0; k < cPair; k++) {
monitor.checkCanceled(); pdb.checkCanceled();
segOffsets.add(reader.parseUnsignedIntVal()); segOffsets.add(reader.parseUnsignedIntVal());
} }
fileSegOffsets.add(segOffsets); fileSegOffsets.add(segOffsets);
List<Integer> segLineNums = new ArrayList<>(); // unsigned shorts List<Integer> segLineNums = new ArrayList<>(); // unsigned shorts
for (int k = 0; k < cPair; k++) { for (int k = 0; k < cPair; k++) {
monitor.checkCanceled(); pdb.checkCanceled();
segLineNums.add(reader.parseUnsignedShortVal()); segLineNums.add(reader.parseUnsignedShortVal());
} }
fileSegLineNums.add(segLineNums); fileSegLineNums.add(segLineNums);

View file

@ -50,8 +50,8 @@ abstract class C13Section {
* @param reader reader to parse from * @param reader reader to parse from
* @param monitor {@link TaskMonitor} used for checking cancellation * @param monitor {@link TaskMonitor} used for checking cancellation
* @return the parsed data * @return the parsed data
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
*/ */
static C13Section parse(PdbByteReader reader, TaskMonitor monitor) static C13Section parse(PdbByteReader reader, TaskMonitor monitor)
throws CancelledException, PdbException { throws CancelledException, PdbException {

View file

@ -20,7 +20,6 @@ import java.io.Writer;
import java.util.*; import java.util.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* Debug Data structures for PDB files. There are a number of debug streams that can be processed. * Debug Data structures for PDB files. There are a number of debug streams that can be processed.
@ -81,8 +80,8 @@ public class DebugData {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link DebugData}. * @param pdb {@link AbstractPdb} that owns this {@link DebugData}
*/ */
public DebugData(AbstractPdb pdb) { public DebugData(AbstractPdb pdb) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
@ -91,7 +90,7 @@ public class DebugData {
/** /**
* Returns the Frame Pointer Omission data * Returns the Frame Pointer Omission data
* @return the framePointerOmissionData or null if does not exist. * @return the framePointerOmissionData or null if does not exist
*/ */
public List<FramePointerOmissionRecord> getFramePointerOmissionData() { public List<FramePointerOmissionRecord> getFramePointerOmissionData() {
return framePointerOmissionData; return framePointerOmissionData;
@ -114,8 +113,8 @@ public class DebugData {
} }
/** /**
* Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;. * Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;
* @return the imageSectionHeaders or null if does not exist. * @return the imageSectionHeaders or null if does not exist
*/ */
public List<ImageSectionHeader> getImageSectionHeaders() { public List<ImageSectionHeader> getImageSectionHeaders() {
return imageSectionHeaders; return imageSectionHeaders;
@ -123,9 +122,9 @@ public class DebugData {
/** /**
* Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;. * Returns the {@link List}&lt;{@link ImageSectionHeader}&gt;.
* When this return a non-null list the OMAP_FROM_SRC should be * When this returns a non-null list the OMAP_FROM_SRC should be
* used for remapping global symbols. * used for remapping global symbols
* @return the imageSectionHeadersOrig or null if does not exist. * @return the imageSectionHeadersOrig or null if does not exist
*/ */
public List<ImageSectionHeader> getImageSectionHeadersOrig() { public List<ImageSectionHeader> getImageSectionHeadersOrig() {
return imageSectionHeadersOrig; return imageSectionHeadersOrig;
@ -138,17 +137,16 @@ public class DebugData {
* Frame Pointer Omission debug data). A stream number of 0XFFFF says that there is no data * Frame Pointer Omission debug data). A stream number of 0XFFFF says that there is no data
* for that debug type; else the stream number represents the stream that should * for that debug type; else the stream number represents the stream that should
* be deserialized to retrieve the debug data of that type. The * be deserialized to retrieve the debug data of that type. The
* {@link #deserialize(TaskMonitor)} method deserializes each of these streams * {@link #deserialize()} method deserializes each of these streams
* that are valid to the corresponding debug data type. * that are valid to the corresponding debug data type
* @param reader {@link PdbByteReader} from which to parse the header. * @param reader {@link PdbByteReader} from which to parse the header
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon error in processing components
* @throws PdbException Upon error in processing components. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public void deserializeHeader(PdbByteReader reader, TaskMonitor monitor) public void deserializeHeader(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
int debugStreamNumber = reader.parseUnsignedShortVal(); int debugStreamNumber = reader.parseUnsignedShortVal();
debugStreams.add(debugStreamNumber); debugStreams.add(debugStreamNumber);
} }
@ -160,14 +158,13 @@ public class DebugData {
/** /**
* Deserialize each valid {@link DebugData} stream, based upon valid stream numbers found while * Deserialize each valid {@link DebugData} stream, based upon valid stream numbers found while
* parsing the {@link DebugData} header. * parsing the {@link DebugData} header
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException PdbException upon error in processing components
* @throws PdbException PdbException Upon error in processing components. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes.
*/ */
public void deserialize(TaskMonitor monitor) public void deserialize()
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
if (debugStreams.isEmpty()) { if (debugStreams.isEmpty()) {
throw new PdbException( throw new PdbException(
@ -180,7 +177,7 @@ public class DebugData {
} }
switch (dbg) { switch (dbg) {
case FRAME_POINTER_OMISSION: case FRAME_POINTER_OMISSION:
deserializeFramePointerOmissionData(streamNum, monitor); deserializeFramePointerOmissionData(streamNum);
break; break;
case EXCEPTION: case EXCEPTION:
// TODO: implement. // TODO: implement.
@ -189,40 +186,40 @@ public class DebugData {
// TODO: implement. // TODO: implement.
break; break;
case OMAP_TO_SOURCE: case OMAP_TO_SOURCE:
// omapToSource = deserializeOMap(streamNum, monitor); // omapToSource = deserializeOMap(streamNum);
break; break;
case OMAP_FROM_SOURCE: case OMAP_FROM_SOURCE:
omapFromSource = deserializeOMap(streamNum, monitor); omapFromSource = deserializeOMap(streamNum);
break; break;
case SECTION_HEADER: case SECTION_HEADER:
imageSectionHeaders = deserializeSectionHeaders(streamNum, monitor); imageSectionHeaders = deserializeSectionHeaders(streamNum);
break; break;
case TOKEN_RID_MAP: case TOKEN_RID_MAP:
// TODO: implement. // TODO: implement.
break; break;
case X_DATA: case X_DATA:
deserializeXData(streamNum, monitor); deserializeXData(streamNum);
break; break;
case P_DATA: case P_DATA:
deserializePData(streamNum, monitor); deserializePData(streamNum);
break; break;
case NEW_FRAME_POINTER_OMISSION: case NEW_FRAME_POINTER_OMISSION:
// TODO: implement. // TODO: implement.
break; break;
case SECTION_HEADER_ORIG: case SECTION_HEADER_ORIG:
imageSectionHeadersOrig = deserializeSectionHeaders(streamNum, monitor); imageSectionHeadersOrig = deserializeSectionHeaders(streamNum);
break; break;
} }
} }
} }
private void deserializeFramePointerOmissionData(int streamNum, TaskMonitor monitor) private void deserializeFramePointerOmissionData(int streamNum)
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
// TODO: check implementation for completeness. // TODO: check implementation for completeness.
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
framePointerOmissionData = new ArrayList<>(); framePointerOmissionData = new ArrayList<>();
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
FramePointerOmissionRecord framePointerOmissionRecord = FramePointerOmissionRecord framePointerOmissionRecord =
new FramePointerOmissionRecord(); new FramePointerOmissionRecord();
framePointerOmissionRecord.parse(reader); framePointerOmissionRecord.parse(reader);
@ -230,12 +227,12 @@ public class DebugData {
} }
} }
private SortedMap<Long, Long> deserializeOMap(int streamNum, TaskMonitor monitor) private SortedMap<Long, Long> deserializeOMap(int streamNum)
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
SortedMap<Long, Long> omap = new TreeMap<>(); SortedMap<Long, Long> omap = new TreeMap<>();
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
long v1 = reader.parseUnsignedIntVal(); long v1 = reader.parseUnsignedIntVal();
long v2 = reader.parseUnsignedIntVal(); long v2 = reader.parseUnsignedIntVal();
omap.put(v1, v2); omap.put(v1, v2);
@ -243,12 +240,12 @@ public class DebugData {
return omap; return omap;
} }
private List<ImageSectionHeader> deserializeSectionHeaders(int streamNum, TaskMonitor monitor) private List<ImageSectionHeader> deserializeSectionHeaders(int streamNum)
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
List<ImageSectionHeader> sectionHeaders = new ArrayList<>(); List<ImageSectionHeader> sectionHeaders = new ArrayList<>();
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb); ImageSectionHeader imageSectionHeader = new ImageSectionHeader(pdb);
imageSectionHeader.parse(reader); imageSectionHeader.parse(reader);
sectionHeaders.add(imageSectionHeader); sectionHeaders.add(imageSectionHeader);
@ -259,11 +256,11 @@ public class DebugData {
// TODO: This is incomplete. // TODO: This is incomplete.
/** /**
* See the {@link LinkerUnwindInfo} class that was built for and is pertinent to * See the {@link LinkerUnwindInfo} class that was built for and is pertinent to
* processing XData. * processing XData
*/ */
private void deserializeXData(int streamNum, TaskMonitor monitor) private void deserializeXData(int streamNum)
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
int streamLength = reader.getLimit(); int streamLength = reader.getLimit();
//System.out.println(reader.dump(0x20)); //System.out.println(reader.dump(0x20));
RvaVaDebugHeader header = new RvaVaDebugHeader(); RvaVaDebugHeader header = new RvaVaDebugHeader();
@ -289,9 +286,9 @@ public class DebugData {
} }
// TODO: This is incomplete. // TODO: This is incomplete.
private void deserializePData(int streamNum, TaskMonitor monitor) private void deserializePData(int streamNum)
throws PdbException, CancelledException, IOException { throws PdbException, CancelledException, IOException {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
pData = new ArrayList<>(); pData = new ArrayList<>();
int streamLength = reader.getLimit(); int streamLength = reader.getLimit();
RvaVaDebugHeader header = new RvaVaDebugHeader(); RvaVaDebugHeader header = new RvaVaDebugHeader();
@ -310,7 +307,7 @@ public class DebugData {
// TODO: current partial implementation does not work (throws exception) // TODO: current partial implementation does not work (throws exception)
// for ucrtbase.dll arm64. Need to look at this closer. // for ucrtbase.dll arm64. Need to look at this closer.
// while (reader.hasMore()) { // while (reader.hasMore()) {
// monitor.checkCanceled(); // pdb.checkCanceled();
// ImageFunctionEntry entry = new ImageFunctionEntry(); // ImageFunctionEntry entry = new ImageFunctionEntry();
// entry.deserialize(reader); // entry.deserialize(reader);
// pData.add(entry); // pData.add(entry);
@ -340,17 +337,19 @@ public class DebugData {
} }
/** /**
* Dumps the {@link DebugData}. This package-protected method is for debugging only. * Dumps the {@link DebugData}. This package-protected method is for debugging only
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
void dump(Writer writer) throws IOException { void dump(Writer writer) throws IOException, CancelledException {
writer.write("DebugData---------------------------------------------------\n"); writer.write("DebugData---------------------------------------------------\n");
dumpDebugStreamList(writer); dumpDebugStreamList(writer);
writer.write("FramePointerOmissionData------------------------------------\n"); writer.write("FramePointerOmissionData------------------------------------\n");
if (framePointerOmissionData != null) { if (framePointerOmissionData != null) {
for (FramePointerOmissionRecord framePointerOmissionRecord : framePointerOmissionData) { for (FramePointerOmissionRecord framePointerOmissionRecord : framePointerOmissionData) {
pdb.checkCanceled();
framePointerOmissionRecord.dump(writer); framePointerOmissionRecord.dump(writer);
} }
} }
@ -360,16 +359,18 @@ public class DebugData {
// if (omapToSource != null) { // if (omapToSource != null) {
// int num = 0; // int num = 0;
// for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) { // for (Map.Entry<Long, Long> entry : omapToSource.entrySet()) {
// pdb.checkCanceled();
// writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(), // writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
// entry.getValue())); // entry.getValue()));
// } // }
// } // }
// writer.write("End OmapToSource--------------------------------------------\n"); // writer.write("End OmapToSource--------------------------------------------\n");
//
writer.write("OmapFromSource----------------------------------------------\n"); writer.write("OmapFromSource----------------------------------------------\n");
if (omapFromSource != null) { if (omapFromSource != null) {
int num = 0; int num = 0;
for (Map.Entry<Long, Long> entry : omapFromSource.entrySet()) { for (Map.Entry<Long, Long> entry : omapFromSource.entrySet()) {
pdb.checkCanceled();
writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(), writer.write(String.format("0X%08X: 0X%012X, 0X%012X\n", num++, entry.getKey(),
entry.getValue())); entry.getValue()));
} }
@ -380,6 +381,7 @@ public class DebugData {
if (imageSectionHeaders != null) { if (imageSectionHeaders != null) {
int sectionNum = 0; int sectionNum = 0;
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) { for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
pdb.checkCanceled();
imageSectionHeader.dump(writer, sectionNum++); imageSectionHeader.dump(writer, sectionNum++);
} }
} }
@ -389,6 +391,7 @@ public class DebugData {
if (imageSectionHeadersOrig != null) { if (imageSectionHeadersOrig != null) {
int sectionNum = 0; int sectionNum = 0;
for (ImageSectionHeader imageSectionHeader : imageSectionHeadersOrig) { for (ImageSectionHeader imageSectionHeader : imageSectionHeadersOrig) {
pdb.checkCanceled();
imageSectionHeader.dump(writer, sectionNum++); imageSectionHeader.dump(writer, sectionNum++);
} }
} }
@ -397,6 +400,7 @@ public class DebugData {
writer.write("PData-------------------------------------------------------\n"); writer.write("PData-------------------------------------------------------\n");
if (pData != null) { if (pData != null) {
for (ImageFunctionEntry entry : pData) { for (ImageFunctionEntry entry : pData) {
pdb.checkCanceled();
// TODO: need to output more if/when more PData is available (e.g., interpretation // TODO: need to output more if/when more PData is available (e.g., interpretation
// of XData. // of XData.
writer.append(entry.toString()); writer.append(entry.toString());
@ -408,14 +412,16 @@ public class DebugData {
} }
/** /**
* Dumps the DebugStreamList. This package-protected method is for debugging only. * Dumps the DebugStreamList. This package-protected method is for debugging only
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
private void dumpDebugStreamList(Writer writer) throws IOException { private void dumpDebugStreamList(Writer writer) throws IOException, CancelledException {
writer.write("StreamList--------------------------------------------------\n"); writer.write("StreamList--------------------------------------------------\n");
int i = 0; int i = 0;
for (int strmNumber : debugStreams) { for (int strmNumber : debugStreams) {
pdb.checkCanceled();
writer.write(String.format("StrmNumber[%02d]: %04x\n", i++, strmNumber)); writer.write(String.format("StrmNumber[%02d]: %04x\n", i++, strmNumber));
} }
writer.write("End StreamList----------------------------------------------\n"); writer.write("End StreamList----------------------------------------------\n");

View file

@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
public class EmptyTPI extends AbstractTypeProgramInterface { public class EmptyTPI extends TypeProgramInterface {
EmptyTPI(AbstractPdb pdb) { EmptyTPI(AbstractPdb pdb) {
super(pdb, RecordCategory.TYPE, -1); super(pdb, RecordCategory.TYPE, -1);

View file

@ -22,7 +22,6 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* Iterator for Global Reference Offsets section of module stream. This iterator returns * Iterator for Global Reference Offsets section of module stream. This iterator returns
@ -34,25 +33,21 @@ class GlobalReferenceIterator implements ParsingIterator<MsSymbolIterator> {
private AbstractPdb pdb; private AbstractPdb pdb;
private int symbolsStreamNumber; private int symbolsStreamNumber;
private TaskMonitor monitor;
private GlobalReferenceOffsetIterator offsetIterator = null; private GlobalReferenceOffsetIterator offsetIterator = null;
private MsSymbolIterator currentGlobalSymbolIterator = null; private MsSymbolIterator currentGlobalSymbolIterator = null;
/** /**
* An Iterator of Global Reference Symbol Iterators (iterator of iterators). * An Iterator of Global Reference Symbol Iterators (iterator of iterators)
* @param pdb {@link AbstractPdb} that owns the Symbols to be parsed * @param pdb {@link AbstractPdb} that owns the Symbols to be parsed
* @param reader PdbByteReader containing only Global Reference Offsets information and in * @param reader PdbByteReader containing only Global Reference Offsets information and in
* newly constructed state * newly constructed state
* @param monitor {@link TaskMonitor} used for checking user cancellation
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public GlobalReferenceIterator(AbstractPdb pdb, PdbByteReader reader, TaskMonitor monitor) public GlobalReferenceIterator(AbstractPdb pdb, PdbByteReader reader)
throws CancelledException, PdbException { throws CancelledException, PdbException {
this.pdb = pdb; this.pdb = pdb;
this.monitor = monitor;
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo == null) { if (debugInfo == null) {
throw new PdbException( throw new PdbException(
@ -102,7 +97,7 @@ class GlobalReferenceIterator implements ParsingIterator<MsSymbolIterator> {
Long offset = offsetIterator.next(); Long offset = offsetIterator.next();
PdbByteReader reader = PdbByteReader reader =
pdb.getReaderForStreamNumber(symbolsStreamNumber, offset.intValue(), pdb.getReaderForStreamNumber(symbolsStreamNumber, offset.intValue(),
MsfStream.MAX_STREAM_LENGTH, monitor); MsfStream.MAX_STREAM_LENGTH);
currentGlobalSymbolIterator = new MsSymbolIterator(pdb, reader); currentGlobalSymbolIterator = new MsSymbolIterator(pdb, reader);
} }
catch (IOException e) { catch (IOException e) {

View file

@ -34,7 +34,7 @@ class GlobalReferenceOffsetIterator implements ParsingIterator<Long> {
* @param reader PdbByteReader containing only Global Reference Offsets information and in * @param reader PdbByteReader containing only Global Reference Offsets information and in
* newly constructed state * newly constructed state
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public GlobalReferenceOffsetIterator(PdbByteReader reader) public GlobalReferenceOffsetIterator(PdbByteReader reader)
throws CancelledException, PdbException { throws CancelledException, PdbException {
@ -80,7 +80,7 @@ class GlobalReferenceOffsetIterator implements ParsingIterator<Long> {
/** /**
* Reads and validates size field; leaves reader pointing at first record. * Reads and validates size field; leaves reader pointing at first record.
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
private void processHeader() throws PdbException { private void processHeader() throws PdbException {
int sizeField = reader.parseInt(); int sizeField = reader.parseInt();

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents Global Symbol Information component of a PDB file. This class is only * This class represents Global Symbol Information component of a PDB file. This class is only
@ -41,32 +40,32 @@ public class GlobalSymbolInformation extends AbstractSymbolInformation {
} }
/** /**
* Deserialize the {@link GlobalSymbolInformation} from the appropriate stream in the Pdb. * Deserialize the {@link GlobalSymbolInformation} from the appropriate stream in the Pdb
* @param streamNumber the stream number containing the information to deserialize. * @param streamNumber the stream number containing the information to deserialize
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
@Override @Override
void deserialize(int streamNumber, TaskMonitor monitor) void deserialize(int streamNumber)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
super.deserialize(streamNumber, monitor); super.deserialize(streamNumber);
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
deserializeHashTable(reader, monitor); deserializeHashTable(reader);
// Organize the information // Organize the information
generateSymbolsList(monitor); generateSymbolsList();
} }
/** /**
* Debug method for dumping information from this {@link GlobalSymbolInformation}. * Debug method for dumping information from this {@link GlobalSymbolInformation}
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws IOException upon IOException writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
@Override @Override
void dump(Writer writer) throws IOException { void dump(Writer writer) throws IOException, CancelledException {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("GlobalSymbolInformation-------------------------------------\n"); builder.append("GlobalSymbolInformation-------------------------------------\n");
dumpHashHeader(builder); dumpHashHeader(builder);

View file

@ -19,7 +19,7 @@ import org.apache.commons.lang3.StringUtils;
/** /**
* Parser, extending {@link TypeProgramInterfaceParser}, for detecting and returning the * Parser, extending {@link TypeProgramInterfaceParser}, for detecting and returning the
* appropriate {@link AbstractTypeProgramInterface} format to be used as the Item Program * appropriate {@link TypeProgramInterface} format to be used as the Item Program
* Interface for the filename given. * Interface for the filename given.
*/ */
public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser { public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
@ -27,8 +27,8 @@ public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
private static final int ITEM_PROGRAM_INTERFACE_STREAM_NUMBER = 4; private static final int ITEM_PROGRAM_INTERFACE_STREAM_NUMBER = 4;
/** /**
* Returns the standard stream number that contains the serialized Item Program Interface. * Returns the standard stream number that contains the serialized Item Program Interface
* @return The standard stream number that contains the Item Program Interface. * @return the standard stream number that contains the Item Program Interface
*/ */
@Override @Override
protected int getStreamNumber() { protected int getStreamNumber() {
@ -38,8 +38,8 @@ public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
/** /**
* Returns the appropriate {@link RecordCategory} needed while processing * Returns the appropriate {@link RecordCategory} needed while processing
* the Type Program Interface} (vs. Item Program Interface). * the Type Program Interface} (vs. Item Program Interface)
* @return {@link RecordCategory#ITEM}. * @return {@link RecordCategory#ITEM}
*/ */
@Override @Override
protected RecordCategory getCategory() { protected RecordCategory getCategory() {
@ -48,10 +48,10 @@ public class ItemProgramInterfaceParser extends TypeProgramInterfaceParser {
} }
/** /**
* Returns true if there is not a name in the name table assigned to the stream number for * Returns {@code true} if there is not a name in the name table assigned to the stream number
* the IPI. * for the IPI
* @param nameTable the name table that contains the stream/name map * @param nameTable the name table that contains the stream/name map
* @return {@code true} if no name associated with the IPI stream number. * @return {@code true} if no name associated with the IPI stream number
*/ */
public static boolean hackCheckNoNameForStream(NameTable nameTable) { public static boolean hackCheckNoNameForStream(NameTable nameTable) {
String name = nameTable.getNameFromStreamNumber(ITEM_PROGRAM_INTERFACE_STREAM_NUMBER); String name = nameTable.getNameFromStreamNumber(ITEM_PROGRAM_INTERFACE_STREAM_NUMBER);

View file

@ -22,16 +22,15 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* <B> Note that this class is new, in-progress creation, being designed as a better interface for * <B> Note that this class is new, in-progress creation, being designed as a better interface for
* getting information for any particular module (stream) in a more random-access manner.</B> * getting information for any particular module (stream) in a more random-access manner.</B>
* <P> * <P>
* This class represents Module Stream data of a PDB file. This is different from the * This class represents Module Stream data of a PDB file. This is different from the
* {@link AbstractModuleInformation} and children classes that are parsed from the DBI stream, * {@link ModuleInformation} and children classes that are parsed from the DBI stream,
* which describes (or is control information for) what is the stream from which this * which describes (or is control information for) what is the stream from which this
* {@link Module} is parsed. Note that we use the {@link AbstractModuleInformation} as one of * {@link Module} is parsed. Note that we use the {@link ModuleInformation} as one of
* the construction parameter to this class. * the construction parameter to this class.
* <P> * <P>
* This class is only suitable for reading; not for writing or modifying a PDB. * This class is only suitable for reading; not for writing or modifying a PDB.
@ -42,8 +41,7 @@ import ghidra.util.task.TaskMonitor;
public class Module { public class Module {
private AbstractPdb pdb; private AbstractPdb pdb;
private AbstractModuleInformation moduleInformation; private ModuleInformation moduleInformation;
private TaskMonitor monitor;
private int streamNumber; private int streamNumber;
private MsfStream stream = null; private MsfStream stream = null;
@ -61,17 +59,15 @@ public class Module {
private boolean doDumpGlobalRefererenceInfo = false; private boolean doDumpGlobalRefererenceInfo = false;
//============================================================================================== //==============================================================================================
public Module(AbstractPdb pdb, AbstractModuleInformation moduleInformation, public Module(AbstractPdb pdb, ModuleInformation moduleInformation) {
TaskMonitor monitor) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
Objects.requireNonNull(moduleInformation, "moduleInformation cannot be null"); Objects.requireNonNull(moduleInformation, "moduleInformation cannot be null");
this.pdb = pdb; this.pdb = pdb;
this.moduleInformation = moduleInformation; this.moduleInformation = moduleInformation;
this.monitor = monitor;
precalculateStreamLocations(); precalculateStreamLocations();
} }
public AbstractModuleInformation getModuleInformation() { public ModuleInformation getModuleInformation() {
return moduleInformation; return moduleInformation;
} }
@ -115,10 +111,9 @@ public class Module {
} }
try { try {
PdbByteReader reader = PdbByteReader reader =
pdb.getReaderForStreamNumber(streamNumber, offsetLines, sizeLines, pdb.getReaderForStreamNumber(streamNumber, offsetLines, sizeLines);
monitor);
// This parser has not been tested with real data // This parser has not been tested with real data
C11Lines c11Lines = C11Lines.parse(pdb, reader, monitor); C11Lines c11Lines = C11Lines.parse(pdb, reader);
return c11Lines; return c11Lines;
} }
catch (IOException e) { catch (IOException e) {
@ -193,7 +188,7 @@ public class Module {
* Returns a C13SectionIterator that iterators over all C13Sections of this module * Returns a C13SectionIterator that iterators over all C13Sections of this module
* @return the iterator * @return the iterator
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public C13SectionIterator<C13Section> getC13SectionIterator() public C13SectionIterator<C13Section> getC13SectionIterator()
throws CancelledException, PdbException { throws CancelledException, PdbException {
@ -206,13 +201,13 @@ public class Module {
* @param clazz The class of the filter type * @param clazz The class of the filter type
* @return the iterator * @return the iterator
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public <T extends C13Section> C13SectionIterator<T> getC13SectionFilteredIterator( public <T extends C13Section> C13SectionIterator<T> getC13SectionFilteredIterator(
Class<T> clazz) throws CancelledException, PdbException { Class<T> clazz) throws CancelledException, PdbException {
PdbByteReader c13SectionReader = getC13LinesReader(); PdbByteReader c13SectionReader = getC13LinesReader();
C13SectionIterator<T> iterator = C13SectionIterator<T> iterator =
new C13SectionIterator<>(c13SectionReader, clazz, true, monitor); new C13SectionIterator<>(c13SectionReader, clazz, true, pdb.getMonitor());
return iterator; return iterator;
} }
@ -225,7 +220,7 @@ public class Module {
* nested blocks until the closing END is found for the GPROC32 * nested blocks until the closing END is found for the GPROC32
* @return the iterator * @return the iterator
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public GlobalReferenceOffsetIterator getGlobalReferenceOffsetIterator() public GlobalReferenceOffsetIterator getGlobalReferenceOffsetIterator()
throws CancelledException, PdbException { throws CancelledException, PdbException {
@ -245,13 +240,13 @@ public class Module {
* nested blocks until the closing END is found for the GPROC32 * nested blocks until the closing END is found for the GPROC32
* @return the iterator * @return the iterator
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
public GlobalReferenceIterator getGlobalReferenceIterator() public GlobalReferenceIterator getGlobalReferenceIterator()
throws CancelledException, PdbException { throws CancelledException, PdbException {
PdbByteReader globalRefsReader = getGlobalRefsReader(); PdbByteReader globalRefsReader = getGlobalRefsReader();
GlobalReferenceIterator iterator = GlobalReferenceIterator iterator =
new GlobalReferenceIterator(pdb, globalRefsReader, monitor); new GlobalReferenceIterator(pdb, globalRefsReader);
return iterator; return iterator;
} }
@ -282,7 +277,7 @@ public class Module {
} }
try { try {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
reader.skip(offset); reader.skip(offset);
try { try {
if (size == -1) { if (size == -1) {
@ -312,11 +307,11 @@ public class Module {
// is loaded into the class (note that as of this writing, the PdbByteReader still contains // is loaded into the class (note that as of this writing, the PdbByteReader still contains
// full byte array of data, consuming memory at the time of use). // full byte array of data, consuming memory at the time of use).
/** /**
* Dumps this class to a Writer. * Dumps this class to a Writer
* @param writer {@link Writer} to which to dump the information * @param writer {@link Writer} to which to dump the information
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
* @throws IOException Upon IOException writing to the {@link Writer} * @throws IOException upon IOException writing to the {@link Writer}
*/ */
void dump(Writer writer) void dump(Writer writer)
throws CancelledException, PdbException, IOException { throws CancelledException, PdbException, IOException {
@ -341,6 +336,7 @@ public class Module {
writer.write("Symbols-----------------------------------------------------\n"); writer.write("Symbols-----------------------------------------------------\n");
MsSymbolIterator symbolIterator = getSymbolIterator(); MsSymbolIterator symbolIterator = getSymbolIterator();
while (symbolIterator.hasNext()) { while (symbolIterator.hasNext()) {
pdb.checkCanceled();
AbstractMsSymbol symbol = symbolIterator.next(); AbstractMsSymbol symbol = symbolIterator.next();
writer.append(symbol.toString()); writer.append(symbol.toString());
} }
@ -365,6 +361,7 @@ public class Module {
C13SectionIterator<C13Section> c13Iterator = C13SectionIterator<C13Section> c13Iterator =
getC13SectionFilteredIterator(C13Section.class); getC13SectionFilteredIterator(C13Section.class);
while (c13Iterator.hasNext()) { while (c13Iterator.hasNext()) {
pdb.checkCanceled();
C13Section c13Section = c13Iterator.next(); C13Section c13Section = c13Iterator.next();
c13Section.dump(writer); c13Section.dump(writer);
} }
@ -375,6 +372,7 @@ public class Module {
// C13SectionIterator<DummyC13Symbols> c13SymbolsIterator = // C13SectionIterator<DummyC13Symbols> c13SymbolsIterator =
// getC13SectionFilteredIterator(DummyC13Symbols.class); // getC13SectionFilteredIterator(DummyC13Symbols.class);
// while (c13SymbolsIterator.hasNext()) { // while (c13SymbolsIterator.hasNext()) {
// pdb.checkCanceled();
// DummyC13Symbols dummyC13Symbols = c13SymbolsIterator.next(); // DummyC13Symbols dummyC13Symbols = c13SymbolsIterator.next();
// dummyC13Symbols.dump(writer); // dummyC13Symbols.dump(writer);
// } // }
@ -382,6 +380,7 @@ public class Module {
// C13SectionIterator<C13Lines> c13LinesIterator = // C13SectionIterator<C13Lines> c13LinesIterator =
// getC13SectionFilteredIterator(C13Lines.class); // getC13SectionFilteredIterator(C13Lines.class);
// while (c13LinesIterator.hasNext()) { // while (c13LinesIterator.hasNext()) {
// pdb.checkCanceled();
// C13Lines myC13Lines = c13LinesIterator.next(); // C13Lines myC13Lines = c13LinesIterator.next();
// myC13Lines.dump(writer); // myC13Lines.dump(writer);
// } // }
@ -395,6 +394,7 @@ public class Module {
GlobalReferenceOffsetIterator globalRefsOffsetIterator = GlobalReferenceOffsetIterator globalRefsOffsetIterator =
getGlobalReferenceOffsetIterator(); getGlobalReferenceOffsetIterator();
while (globalRefsOffsetIterator.hasNext()) { while (globalRefsOffsetIterator.hasNext()) {
pdb.checkCanceled();
Long val = globalRefsOffsetIterator.next(); Long val = globalRefsOffsetIterator.next();
writer.append(String.format("0x%08x\n", val)); writer.append(String.format("0x%08x\n", val));
tmp.add(val); tmp.add(val);
@ -420,6 +420,7 @@ public class Module {
GlobalReferenceIterator globalReferenceIterator = GlobalReferenceIterator globalReferenceIterator =
getGlobalReferenceIterator(); getGlobalReferenceIterator();
while (globalReferenceIterator.hasNext()) { while (globalReferenceIterator.hasNext()) {
pdb.checkCanceled();
MsSymbolIterator symIter = globalReferenceIterator.next(); MsSymbolIterator symIter = globalReferenceIterator.next();
if (symIter.hasNext()) { if (symIter.hasNext()) {
AbstractMsSymbol sym = symIter.next(); AbstractMsSymbol sym = symIter.next();

View file

@ -24,13 +24,13 @@ import java.util.*;
* We have intended to implement according to the Microsoft PDB API (source); see the API for * We have intended to implement according to the Microsoft PDB API (source); see the API for
* truth. * truth.
*/ */
public abstract class AbstractModuleInformation { public abstract class ModuleInformation {
//============================================================================================== //==============================================================================================
// Internals // Internals
//============================================================================================== //==============================================================================================
protected long modulePointer; protected long modulePointer;
protected AbstractSectionContribution sectionContribution; protected SectionContribution sectionContribution;
protected boolean writtenSinceOpen; protected boolean writtenSinceOpen;
// TODO: consider what to do (gets parsed for 600 between 500 items. Want only in 600, // TODO: consider what to do (gets parsed for 600 between 500 items. Want only in 600,
// but would have to break up the deserialize and dumpInternal methods. Issue might be, // but would have to break up the deserialize and dumpInternal methods. Issue might be,
@ -61,46 +61,46 @@ public abstract class AbstractModuleInformation {
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
public AbstractModuleInformation(AbstractPdb pdb) { public ModuleInformation(AbstractPdb pdb) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdb = pdb; this.pdb = pdb;
} }
/** /**
* Returns the number of files contributing to the module. * Returns the number of files contributing to the module
* @return Number of files. * @return number of files
*/ */
public int getNumFilesContributing() { public int getNumFilesContributing() {
return numFilesContributing; return numFilesContributing;
} }
/** /**
* Returns list of offsets for the module. * Returns list of offsets for the module
* @return Offsets. * @return offsets
*/ */
public List<Integer> getOffsetsArray() { public List<Integer> getOffsetsArray() {
return offsetsArray; return offsetsArray;
} }
/** /**
* Returns list of file names for the module. * Returns list of file names for the module
* @return File names. * @return file names
*/ */
public List<String> getFilenamesArray() { public List<String> getFilenamesArray() {
return filenamesArray; return filenamesArray;
} }
/** /**
* Returns the stream number containing debug information. * Returns the stream number containing debug information
* @return Stream number. * @return stream number
*/ */
public int getStreamNumberDebugInformation() { public int getStreamNumberDebugInformation() {
return streamNumberDebugInformation; return streamNumberDebugInformation;
} }
/** /**
* Returns the size of the local symbols debug information. * Returns the size of the local symbols debug information
* @return Size of the local symbols debug information. * @return size of the local symbols debug information
*/ */
public int getSizeLocalSymbolsDebugInformation() { public int getSizeLocalSymbolsDebugInformation() {
return sizeLocalSymbolsDebugInformation; return sizeLocalSymbolsDebugInformation;
@ -108,7 +108,7 @@ public abstract class AbstractModuleInformation {
/** /**
* Returns the size of the older-style line number information * Returns the size of the older-style line number information
* @return Size of the older-style line number information * @return size of the older-style line number information
*/ */
public int getSizeLineNumberDebugInformation() { public int getSizeLineNumberDebugInformation() {
return sizeLineNumberDebugInformation; return sizeLineNumberDebugInformation;
@ -116,25 +116,25 @@ public abstract class AbstractModuleInformation {
/** /**
* Returns the size of the C13-style line number information * Returns the size of the C13-style line number information
* @return Size of the C13-style line number information * @return size of the C13-style line number information
*/ */
public int getSizeC13StyleLineNumberInformation() { public int getSizeC13StyleLineNumberInformation() {
return sizeC13StyleLineNumberInformation; return sizeC13StyleLineNumberInformation;
} }
/** /**
* Returns the name of the module. * Returns the name of the module
* @return Name of the module. * @return name of the module
*/ */
public String getModuleName() { public String getModuleName() {
return moduleName; return moduleName;
} }
/** /**
* Returns {@link AbstractSectionContribution} of the module. * Returns {@link SectionContribution} of the module
* @return {@link AbstractSectionContribution} of the module. * @return {@link SectionContribution} of the module
*/ */
public AbstractSectionContribution getSectionContribution() { public SectionContribution getSectionContribution() {
return sectionContribution; return sectionContribution;
} }
@ -151,9 +151,9 @@ public abstract class AbstractModuleInformation {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the module. * Deserializes the module
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException upon error parsing a string name. * @throws PdbException upon error parsing a string name
*/ */
protected void deserialize(PdbByteReader reader) throws PdbException { protected void deserialize(PdbByteReader reader) throws PdbException {
modulePointer = reader.parseUnsignedIntVal(); modulePointer = reader.parseUnsignedIntVal();
@ -186,15 +186,15 @@ public abstract class AbstractModuleInformation {
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Additionals. Abstract method filled in by instances to parse additional * Deserializes the Additionals. Abstract method filled in by instances to parse additional
* data pertinent to themselves. * data pertinent to themselves
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException upon error parsing a string name. * @throws PdbException upon error parsing a string name
*/ */
protected abstract void parseAdditionals(PdbByteReader reader) throws PdbException; protected abstract void parseAdditionals(PdbByteReader reader) throws PdbException;
/** /**
* Dumps the Additionals. This method is for debugging only. * Dumps the Additionals. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
protected abstract String dumpAdditionals(); protected abstract String dumpAdditionals();
@ -211,8 +211,8 @@ public abstract class AbstractModuleInformation {
} }
/** /**
* Dumps this module. This method is for debugging only. * Dumps this module. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
String dump() { String dump() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();

View file

@ -16,9 +16,9 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractModuleInformation} for Microsoft v5.00 PDB. * This class is the version of {@link ModuleInformation} for Microsoft v5.00 PDB.
*/ */
public class ModuleInformation500 extends AbstractModuleInformation { public class ModuleInformation500 extends ModuleInformation {
//============================================================================================== //==============================================================================================
// API // API

View file

@ -16,9 +16,9 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractModuleInformation} for Microsoft v6.00 PDB. * This class is the version of {@link ModuleInformation} for Microsoft v6.00 PDB.
*/ */
public class ModuleInformation600 extends AbstractModuleInformation { public class ModuleInformation600 extends ModuleInformation {
//============================================================================================== //==============================================================================================
// API // API

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.*; import java.util.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents Name Table component of a PDB file. This class is only * This class represents Name Table component of a PDB file. This class is only
@ -54,8 +53,8 @@ public class NameTable {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this Name Table. * @param pdb {@link AbstractPdb} that owns this Name Table
*/ */
public NameTable(AbstractPdb pdb) { public NameTable(AbstractPdb pdb) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
@ -63,18 +62,18 @@ public class NameTable {
} }
/** /**
* Returns a name from the Name Table pertaining to the index argument. * Returns a name from the Name Table pertaining to the index argument
* @param index Index of the name to retrieve. * @param index index of the name to retrieve
* @return Name retrieved for the index. * @return name retrieved for the index
*/ */
public String getNameFromStreamNumber(int index) { public String getNameFromStreamNumber(int index) {
return namesByStreamNumber.get(index); return namesByStreamNumber.get(index);
} }
/** /**
* Returns an index of the name argument in the {@link NameTable}. * Returns an index of the name argument in the {@link NameTable}
* @param name Name to look up. * @param name name to look up
* @return Index of the name. * @return index of the name
*/ */
public int getStreamNumberFromName(String name) { public int getStreamNumberFromName(String name) {
Integer x = streamNumbersByName.getOrDefault(name, -1); Integer x = streamNumbersByName.getOrDefault(name, -1);
@ -83,9 +82,9 @@ public class NameTable {
/** /**
* Returns a name from the Name Table pertaining to the byte-offset in the block of names for * Returns a name from the Name Table pertaining to the byte-offset in the block of names for
* the table. * the table
* @param offset Byte-offset of the name in the {@link NameTable} block. * @param offset byte-offset of the name in the {@link NameTable} block
* @return Name found at offset. * @return name found at offset
*/ */
public String getNameStringFromOffset(int offset) { public String getNameStringFromOffset(int offset) {
if (namesByOffset == null) { if (namesByOffset == null) {
@ -96,9 +95,9 @@ public class NameTable {
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a basic object. * IMPORTANT: This method is for testing only. It allows us to set a basic object.
* Note: not all values are initialized. Add a paired offset and {@link String} name. * Note: not all values are initialized. Add a paired offset and {@link String} name
* @param offset Offset part of pair. * @param offset offset part of pair
* @param name Name part of pair. * @param name name part of pair
*/ */
public void forTestingOnlyAddOffsetNamePair(int offset, String name) { public void forTestingOnlyAddOffsetNamePair(int offset, String name) {
if (namesByOffset == null) { if (namesByOffset == null) {
@ -119,15 +118,14 @@ public class NameTable {
// Ghidra user can ad-hoc apply interpretations to those fields? Needs investigation, but // Ghidra user can ad-hoc apply interpretations to those fields? Needs investigation, but
// not critical at this time. // not critical at this time.
/** /**
* Deserializes the Directory. * Deserializes the Directory
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a string
* @throws PdbException upon error parsing a string. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserializeDirectory(PdbByteReader reader, TaskMonitor monitor) void deserializeDirectory(PdbByteReader reader)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// Get the buffer of strings // Get the buffer of strings
@ -152,10 +150,10 @@ public class NameTable {
streamNumbers = new int[numPairs]; streamNumbers = new int[numPairs];
// Read Present Set. Not really needed by us, as we use the java HashMap. // Read Present Set. Not really needed by us, as we use the java HashMap.
presentList.parse(reader, monitor); presentList.parse(reader, pdb.getMonitor());
// Read Deleted Set. Not really needed by us, as we use the java HashMap. // Read Deleted Set. Not really needed by us, as we use the java HashMap.
deletedList.parse(reader, monitor); deletedList.parse(reader, pdb.getMonitor());
// Read values of index into buffer and name index. Load the HashMaps. // Read values of index into buffer and name index. Load the HashMaps.
// Since we are using the java HashMap, we do not need to mimic the // Since we are using the java HashMap, we do not need to mimic the
@ -163,7 +161,7 @@ public class NameTable {
// of domainSize) and do not need to store the domain and range items // of domainSize) and do not need to store the domain and range items
// in a list indexed by i. // in a list indexed by i.
for (int i = 0; i < numPairs; i++) { for (int i = 0; i < numPairs; i++) {
monitor.checkCanceled(); pdb.checkCanceled();
int bufOffset = reader.parseInt(); int bufOffset = reader.parseInt();
int streamNumber = reader.parseInt(); int streamNumber = reader.parseInt();
nameBufferReader.setIndex(bufOffset); nameBufferReader.setIndex(bufOffset);
@ -174,7 +172,7 @@ public class NameTable {
namesByStreamNumber.put(streamNumber, name); namesByStreamNumber.put(streamNumber, name);
streamNumbersByName.put(name, streamNumber); streamNumbersByName.put(name, streamNumber);
} }
deserializeNameTableStreams(monitor); deserializeNameTableStreams();
} }
// TODO: Reduce code complexity once we know the details for the various cases. Probably // TODO: Reduce code complexity once we know the details for the various cases. Probably
@ -182,19 +180,18 @@ public class NameTable {
// find here. // find here.
/** /**
* Deserializes Name Table Streams. An offset-to-string map is created for each stream; each * Deserializes Name Table Streams. An offset-to-string map is created for each stream; each
* map is placed into a stream-number-to-map map. * map is placed into a stream-number-to-map map
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a string
* @throws PdbException upon error parsing a string. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserializeNameTableStreams(TaskMonitor monitor) void deserializeNameTableStreams()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
for (int streamNumber : streamNumbers) { for (int streamNumber : streamNumbers) {
monitor.checkCanceled(); pdb.checkCanceled();
Map<Integer, String> stringsByOffset = new HashMap<>(); Map<Integer, String> stringsByOffset = new HashMap<>();
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
if (reader.getLimit() >= 12) { if (reader.getLimit() >= 12) {
long hdrMagic = reader.parseUnsignedIntVal(); long hdrMagic = reader.parseUnsignedIntVal();
int hdrVer = reader.parseInt(); int hdrVer = reader.parseInt();
@ -205,7 +202,7 @@ public class NameTable {
int length = reader.parseInt(); int length = reader.parseInt();
PdbByteReader stringReader = reader.getSubPdbByteReader(length); PdbByteReader stringReader = reader.getSubPdbByteReader(length);
while (stringReader.hasMore()) { while (stringReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
int offset = stringReader.getIndex(); int offset = stringReader.getIndex();
String string = stringReader.parseNullTerminatedUtf8String(); String string = stringReader.parseNullTerminatedUtf8String();
stringsByOffset.put(offset, string); stringsByOffset.put(offset, string);

View file

@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.AbstractMsf; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.Msf;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -31,20 +31,20 @@ public class Pdb200 extends AbstractPdb {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf {@link AbstractMsf} foundation for the PDB. * @param msf {@link Msf} foundation for the PDB
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
* @throws PdbException Upon unknown value for configuration or error in processing components. * @throws PdbException upon unknown value for configuration or error in processing components
*/ */
Pdb200(AbstractMsf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException { Pdb200(Msf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException {
super(msf, pdbOptions); super(msf, pdbOptions);
} }
@Override @Override
void deserializeIdentifiersOnly(TaskMonitor monitor) void deserializeIdentifiersOnly(TaskMonitor monitor)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
} }
@ -52,9 +52,9 @@ public class Pdb200 extends AbstractPdb {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserializeDirectory(TaskMonitor monitor) void deserializeDirectory()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
} }

View file

@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.AbstractMsf; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.Msf;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -31,20 +31,20 @@ public class Pdb400 extends AbstractPdb {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf {@link AbstractMsf} foundation for the PDB. * @param msf {@link Msf} foundation for the PDB
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
* @throws PdbException Upon unknown value for configuration or error in processing components. * @throws PdbException upon unknown value for configuration or error in processing components
*/ */
Pdb400(AbstractMsf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException { Pdb400(Msf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException {
super(msf, pdbOptions); super(msf, pdbOptions);
} }
@Override @Override
void deserializeIdentifiersOnly(TaskMonitor monitor) void deserializeIdentifiersOnly(TaskMonitor monitor)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
} }
@ -52,11 +52,11 @@ public class Pdb400 extends AbstractPdb {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserializeDirectory(TaskMonitor monitor) void deserializeDirectory()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
deserializeParameters(reader, monitor); deserializeParameters(reader);
} }
@Override @Override

View file

@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.AbstractMsf; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.Msf;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -31,20 +31,20 @@ public class Pdb700 extends AbstractPdb {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf {@link AbstractMsf} foundation for the PDB. * @param msf {@link Msf} foundation for the PDB
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
* @throws PdbException Upon unknown value for configuration or error in processing components. * @throws PdbException upon unknown value for configuration or error in processing components
*/ */
Pdb700(AbstractMsf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException { Pdb700(Msf msf, PdbReaderOptions pdbOptions) throws IOException, PdbException {
super(msf, pdbOptions); super(msf, pdbOptions);
} }
@Override @Override
void deserializeIdentifiersOnly(TaskMonitor monitor) void deserializeIdentifiersOnly(TaskMonitor monitor)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
guid = reader.parseGUID(); guid = reader.parseGUID();
} }
@ -53,12 +53,12 @@ public class Pdb700 extends AbstractPdb {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserializeDirectory(TaskMonitor monitor) void deserializeDirectory()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbByteReader reader = getDirectoryReader(monitor); PdbByteReader reader = getDirectoryReader();
deserializeVersionSignatureAge(reader); deserializeVersionSignatureAge(reader);
guid = reader.parseGUID(); guid = reader.parseGUID();
deserializeParameters(reader, monitor); deserializeParameters(reader);
} }
@Override @Override
@ -76,8 +76,8 @@ public class Pdb700 extends AbstractPdb {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Dumps the GUID. This method is for debugging only. * Dumps the GUID. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
protected String dumpGUID() { protected String dumpGUID() {
if (guid == null) { if (guid == null) {

View file

@ -21,7 +21,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents DebugInfo (DBI) component of a PDB file. * This class represents DebugInfo (DBI) component of a PDB file.
@ -65,8 +64,8 @@ public abstract class PdbDebugInfo {
protected int lengthSectionMap = 0; // signed 32-bit protected int lengthSectionMap = 0; // signed 32-bit
protected int lengthFileInformation = 0; // signed 32-bit protected int lengthFileInformation = 0; // signed 32-bit
protected List<AbstractModuleInformation> moduleInformationList = new ArrayList<>(); protected List<ModuleInformation> moduleInformationList = new ArrayList<>();
protected List<AbstractSectionContribution> sectionContributionList = new ArrayList<>(); protected List<SectionContribution> sectionContributionList = new ArrayList<>();
protected List<SegmentMapDescription> segmentMapList = new ArrayList<>(); protected List<SegmentMapDescription> segmentMapList = new ArrayList<>();
protected SymbolRecords symbolRecords; protected SymbolRecords symbolRecords;
@ -83,9 +82,9 @@ public abstract class PdbDebugInfo {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this Database Interface. * @param pdb {@link AbstractPdb} that owns this debug info
* @param streamNumber The stream number of the stream containing the Database Interface. * @param streamNumber the stream number of the stream containing the debug info
*/ */
public PdbDebugInfo(AbstractPdb pdb, int streamNumber) { public PdbDebugInfo(AbstractPdb pdb, int streamNumber) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
@ -97,8 +96,8 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Returns the number of bytes needed to store the version number. * Returns the number of bytes needed to store the version number
* @return The number of bytes needed to store the version number. * @return the number of bytes needed to store the version number
*/ */
public static int getVersionNumberSize() { public static int getVersionNumberSize() {
return VERSION_NUMBER_SIZE; return VERSION_NUMBER_SIZE;
@ -109,29 +108,28 @@ public abstract class PdbDebugInfo {
* The PDB is updated with dbiAge and targetProcessor during deserialization * The PDB is updated with dbiAge and targetProcessor during deserialization
* of new DBI header. * of new DBI header.
* @param headerOnly if true only the DBI header fields will be parsed * @param headerOnly if true only the DBI header fields will be parsed
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return the version number of the debug info
* @return The version number of the Database Interface. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a field
* @throws PdbException upon error parsing a field. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public long deserialize(boolean headerOnly, TaskMonitor monitor) public long deserialize(boolean headerOnly)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
if (headerOnly) { if (headerOnly) {
PdbByteReader reader = PdbByteReader reader =
pdb.getReaderForStreamNumber(streamNumber, 0, getHeaderLength(), monitor); pdb.getReaderForStreamNumber(streamNumber, 0, getHeaderLength());
deserializeHeader(reader); deserializeHeader(reader);
} }
else { else {
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
deserializeHeader(reader); deserializeHeader(reader);
deserializeInternalSubstreams(reader, monitor); deserializeInternalSubstreams(reader);
deserializeAdditionalSubstreams(monitor); deserializeAdditionalSubstreams();
// BELOW: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff) // BELOW: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)
if (doNewStuff) { if (doNewStuff) {
parseModules(monitor); parseModules();
compareSymbols(monitor); //temporary to ensure same results with previous work. compareSymbols(); //temporary to ensure same results with previous work.
} }
// ABOVE: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff) // ABOVE: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)
} }
@ -139,7 +137,7 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Returns the number of modules. * Returns the number of modules
* @return the number of modules * @return the number of modules
*/ */
public int getNumModules() { public int getNumModules() {
@ -147,24 +145,24 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Returns the list of {@link AbstractModuleInformation}, indexed by the module number. * Returns the list of {@link ModuleInformation}, indexed by the module number
* @return List of {@link AbstractModuleInformation}. * @return list of {@link ModuleInformation}
*/ */
public List<AbstractModuleInformation> getModuleInformationList() { public List<ModuleInformation> getModuleInformationList() {
return moduleInformationList; return moduleInformationList;
} }
/** /**
* Returns the {@link AbstractModuleInformation}, based on the moduleNumber. * Returns the {@link ModuleInformation}, based on the moduleNumber
* @param moduleNumber The module number being requested (1 to {@link #getNumModules()}). * @param moduleNumber the module number being requested (1 to {@link #getNumModules()})
* @return {@link AbstractModuleInformation} for the moduleNumber provided. * @return {@link ModuleInformation} for the moduleNumber provided
* @throws PdbException Upon moduleNumber out of range or no module information. * @throws PdbException upon moduleNumber out of range or no module information
*/ */
public AbstractModuleInformation getModuleInformation(int moduleNumber) throws PdbException { public ModuleInformation getModuleInformation(int moduleNumber) throws PdbException {
if (moduleNumber < 1 || moduleNumber > moduleInformationList.size()) { if (moduleNumber < 1 || moduleNumber > moduleInformationList.size()) {
throw new PdbException("ModuleNumber out of range: " + moduleNumber); throw new PdbException("ModuleNumber out of range: " + moduleNumber);
} }
AbstractModuleInformation moduleInfo = moduleInformationList.get(moduleNumber - 1); ModuleInformation moduleInfo = moduleInformationList.get(moduleNumber - 1);
if (moduleInfo == null) { if (moduleInfo == null) {
throw new PdbException("Null AbstractModuleInformation"); throw new PdbException("Null AbstractModuleInformation");
} }
@ -172,20 +170,20 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Returns the list of combined global/public symbols. * Returns the list of combined global/public symbols
* @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to * @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to
* symbols. * symbols
*/ */
public Map<Long, AbstractMsSymbol> getSymbolsByOffset() { public Map<Long, AbstractMsSymbol> getSymbolsByOffset() {
return symbolRecords.getSymbolsByOffset(); return symbolRecords.getSymbolsByOffset();
} }
/** /**
* Returns the buffer-offset-to-symbol map for the module as specified by moduleNumber. * Returns the buffer-offset-to-symbol map for the module as specified by moduleNumber
* @param moduleNumber The number ID of the module for which to return the list. * @param moduleNumber the number ID of the module for which to return the list
* @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to * @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to
* symbols for the specified module. * symbols for the specified module
* @throws PdbException Upon moduleNumber out of range or no module information. * @throws PdbException upon moduleNumber out of range or no module information
*/ */
public Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber) public Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber)
throws PdbException { throws PdbException {
@ -200,10 +198,10 @@ public abstract class PdbDebugInfo {
/** /**
* Returns the {@link AbstractMsSymbol} from the main symbols for the * Returns the {@link AbstractMsSymbol} from the main symbols for the
* actual symbol record offset (which is past the length and symbol type fields). * actual symbol record offset (which is past the length and symbol type fields)
* @param offset the offset of the symbol (beyond length and symbol type fields); this is the * @param offset the offset of the symbol (beyond length and symbol type fields); this is the
* offset value specified by many symbol type records. * offset value specified by many symbol type records
* @return the symbol group for the module or null if not found. * @return the symbol group for the module or null if not found
*/ */
public AbstractMsSymbol getSymbolForOffsetOfRecord(long offset) { public AbstractMsSymbol getSymbolForOffsetOfRecord(long offset) {
return getSymbolsByOffset().get(offset - 4); return getSymbolsByOffset().get(offset - 4);
@ -211,13 +209,13 @@ public abstract class PdbDebugInfo {
/** /**
* Returns the {@link AbstractMsSymbol} for the module as specified by moduleNumber and * Returns the {@link AbstractMsSymbol} for the module as specified by moduleNumber and
* actual symbol record offset (which is past the length and symbol type fields). * actual symbol record offset (which is past the length and symbol type fields)
* @param moduleNumber The number ID of the module (1 to {@link #getNumModules()}) for * @param moduleNumber the number ID of the module (1 to {@link #getNumModules()}) for
* which to return the list. * which to return the list
* @param offset the offset of the symbol (beyond length and symbol type fields); this is the * @param offset the offset of the symbol (beyond length and symbol type fields); this is the
* offset value specified by many symbol type records. * offset value specified by many symbol type records
* @return the symbol group for the module or null if not found. * @return the symbol group for the module or null if not found
* @throws PdbException Upon moduleNumber out of range or no module information. * @throws PdbException upon moduleNumber out of range or no module information
*/ */
public AbstractMsSymbol getSymbolForModuleAndOffsetOfRecord(int moduleNumber, long offset) public AbstractMsSymbol getSymbolForModuleAndOffsetOfRecord(int moduleNumber, long offset)
throws PdbException { throws PdbException {
@ -229,41 +227,40 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Returns list of {@link AbstractSectionContribution} for this Database Interface. * Returns list of {@link SectionContribution} for this debug info
* @return List of {@link AbstractSectionContribution}. * @return list of {@link SectionContribution}
*/ */
public List<AbstractSectionContribution> getSectionContributionList() { public List<SectionContribution> getSectionContributionList() {
return sectionContributionList; return sectionContributionList;
} }
/** /**
* Returns list of {@link SegmentMapDescription} for this Database Interface. * Returns list of {@link SegmentMapDescription} for this debug info
* @return List of {@link SegmentMapDescription}. * @return list of {@link SegmentMapDescription}
*/ */
public List<SegmentMapDescription> getSegmentMapList() { public List<SegmentMapDescription> getSegmentMapList() {
return segmentMapList; return segmentMapList;
} }
/** /**
* Returns {@link SymbolRecords} component for this Database Interface. * Returns {@link SymbolRecords} component for this debug info
* @return {@link SymbolRecords} component. * @return {@link SymbolRecords} component
*/ */
public SymbolRecords getSymbolRecords() { public SymbolRecords getSymbolRecords() {
return symbolRecords; return symbolRecords;
} }
/** /**
* Returns {@link GlobalSymbolInformation} component for this Database Interface. * Returns {@link GlobalSymbolInformation} component for this debug info
* @return {@link GlobalSymbolInformation} component. * @return {@link GlobalSymbolInformation} component
*/ */
public GlobalSymbolInformation getGlobalSymbolInformation() { public GlobalSymbolInformation getGlobalSymbolInformation() {
return globalSymbolInformation; return globalSymbolInformation;
} }
/** /**
* Returns Public Symbol Information component for * Returns Public Symbol Information component for this debug info
* this Database Interface. * @return Public Symbol Information component
* @return Public Symbol Information component.
*/ */
public PublicSymbolInformation getPublicSymbolInformation() { public PublicSymbolInformation getPublicSymbolInformation() {
return publicSymbolInformation; return publicSymbolInformation;
@ -273,24 +270,24 @@ public abstract class PdbDebugInfo {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Returns the stream number for the GlobalSymbols component. * Returns the stream number for the GlobalSymbols component
* @return Stream number. * @return stream number
*/ */
int getGlobalSymbolsHashMaybeStreamNumber() { int getGlobalSymbolsHashMaybeStreamNumber() {
return streamNumberGlobalStaticSymbolsHashMaybe; return streamNumberGlobalStaticSymbolsHashMaybe;
} }
/** /**
* Returns the stream number for the PublicStaticSymbols component. * Returns the stream number for the PublicStaticSymbols component
* @return Stream number. * @return stream number
*/ */
int getPublicStaticSymbolsHashMaybeStreamNumber() { int getPublicStaticSymbolsHashMaybeStreamNumber() {
return streamNumberPublicStaticSymbolsHashMaybe; return streamNumberPublicStaticSymbolsHashMaybe;
} }
/** /**
* Returns the stream number for {@link SymbolRecords} component. * Returns the stream number for {@link SymbolRecords} component
* @return Stream number. * @return stream number
*/ */
int getSymbolRecordsStreamNumber() { int getSymbolRecordsStreamNumber() {
return streamNumberSymbolRecords; return streamNumberSymbolRecords;
@ -300,9 +297,9 @@ public abstract class PdbDebugInfo {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Header. * Deserializes the Header
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected abstract void deserializeHeader(PdbByteReader reader) throws PdbException; protected abstract void deserializeHeader(PdbByteReader reader) throws PdbException;
@ -313,64 +310,62 @@ public abstract class PdbDebugInfo {
protected abstract int getHeaderLength(); protected abstract int getHeaderLength();
/** /**
* Deserializes the SubStreams internal to the Database Interface stream. * Deserializes the SubStreams internal to the debug info stream
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon error parsing a field
* @throws PdbException upon error parsing a field. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected abstract void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor) protected abstract void deserializeInternalSubstreams(PdbByteReader reader)
throws PdbException, CancelledException; throws PdbException, CancelledException;
/** /**
* Deserializes the AdditionalSubstreams components. * Deserializes the AdditionalSubstreams components
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error parsing a field
* @throws PdbException upon error parsing a field. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected abstract void deserializeAdditionalSubstreams(TaskMonitor monitor) protected abstract void deserializeAdditionalSubstreams()
throws IOException, PdbException, CancelledException; throws IOException, PdbException, CancelledException;
/** /**
* Deserializes/Processes the appropriate {@link AbstractModuleInformation} flavor. * Deserializes/processes the appropriate {@link ModuleInformation} flavor
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param skip skip over the data in the {@link PdbByteReader}
* @param skip Skip over the data in the {@link PdbByteReader}. * @throws PdbException upon error parsing a field
* @throws PdbException upon error parsing a field. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected abstract void processModuleInformation(PdbByteReader reader, TaskMonitor monitor, protected abstract void processModuleInformation(PdbByteReader reader, boolean skip)
boolean skip) throws PdbException, CancelledException; throws PdbException, CancelledException;
/** /**
* Dumps the Header. This method is for debugging only. * Dumps the Header. This method is for debugging only
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
*/ */
protected abstract void dumpHeader(Writer writer) throws IOException; protected abstract void dumpHeader(Writer writer) throws IOException;
/** /**
* Dumps the Internal Substreams. This method is for debugging only. * Dumps the Internal Substreams. This method is for debugging only
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
protected abstract void dumpInternalSubstreams(Writer writer) throws IOException; protected abstract void dumpInternalSubstreams(Writer writer)
throws IOException, CancelledException;
//============================================================================================== //==============================================================================================
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes/Processes the SectionContributions component. * Deserializes/processes the SectionContributions component
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param skip skip over the data in the {@link PdbByteReader}
* @param skip Skip over the data in the {@link PdbByteReader}. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void processSectionContributions(PdbByteReader reader, TaskMonitor monitor, protected void processSectionContributions(PdbByteReader reader, boolean skip)
boolean skip) throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthSectionContributionSubstream == 0) { if (lengthSectionContributionSubstream == 0) {
return; return;
} }
@ -385,8 +380,8 @@ public abstract class PdbDebugInfo {
if (version == SCV1400) { if (version == SCV1400) {
//long version2 = substreamReader.parseUnsignedIntVal(); //long version2 = substreamReader.parseUnsignedIntVal();
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
AbstractSectionContribution sectionContribution = new SectionContribution1400(); SectionContribution sectionContribution = new SectionContribution1400();
sectionContribution.deserialize(substreamReader); sectionContribution.deserialize(substreamReader);
sectionContributionList.add(sectionContribution); sectionContributionList.add(sectionContribution);
} }
@ -394,8 +389,8 @@ public abstract class PdbDebugInfo {
else if (version == SCV600) { else if (version == SCV600) {
//long version2 = substreamReader.parseUnsignedIntVal(); //long version2 = substreamReader.parseUnsignedIntVal();
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
AbstractSectionContribution sectionContribution = new SectionContribution600(); SectionContribution sectionContribution = new SectionContribution600();
sectionContribution.deserialize(substreamReader); sectionContribution.deserialize(substreamReader);
sectionContributionList.add(sectionContribution); sectionContributionList.add(sectionContribution);
} }
@ -403,11 +398,11 @@ public abstract class PdbDebugInfo {
//TODO: Don't know when SectionContribution200 is the type to use. Don't know if //TODO: Don't know when SectionContribution200 is the type to use. Don't know if
// this part could be the default of processSectionContribs within // this part could be the default of processSectionContribs within
// DebugInfo and if the above part (test for SVC600 and SVC1400 would // DebugInfo and if the above part (test for SVC600 and SVC1400 would
// be the override method for DatabaseInformationNew. // be the override method for PdbNewDebugInfo.
else { else {
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
AbstractSectionContribution sectionContribution = new SectionContribution400(); SectionContribution sectionContribution = new SectionContribution400();
sectionContribution.deserialize(substreamReader); sectionContribution.deserialize(substreamReader);
sectionContributionList.add(sectionContribution); sectionContributionList.add(sectionContribution);
} }
@ -415,18 +410,17 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Deserializes/Processes the {@link SegmentMapDescription}. * Deserializes/processes the {@link SegmentMapDescription}
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param skip skip over the data in the {@link PdbByteReader}
* @param skip Skip over the data in the {@link PdbByteReader}. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
// TODO: unused value numSegLog? // TODO: unused value numSegLog?
// Note: this is SegmentMap or SectionMap (API structs are segment; API code is Section) // Note: this is SegmentMap or SectionMap (API structs are segment; API code is Section)
// Suppress "unused" for numSegLog // Suppress "unused" for numSegLog
@SuppressWarnings("unused") @SuppressWarnings("unused")
protected void processSegmentMap(PdbByteReader reader, TaskMonitor monitor, boolean skip) protected void processSegmentMap(PdbByteReader reader, boolean skip)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthSectionMap == 0) { if (lengthSectionMap == 0) {
return; return;
@ -442,7 +436,7 @@ public abstract class PdbDebugInfo {
int numSegLog = substreamReader.parseUnsignedShortVal(); int numSegLog = substreamReader.parseUnsignedShortVal();
// Process records // Process records
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
SegmentMapDescription segment = new SegmentMapDescription(); SegmentMapDescription segment = new SegmentMapDescription();
segment.deserialize(substreamReader); segment.deserialize(substreamReader);
segmentMapList.add(segment); segmentMapList.add(segment);
@ -453,14 +447,13 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Deserializes/Processes the FileInformation. * Deserializes/processes the FileInformation
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param skip skip over the data in the {@link PdbByteReader}
* @param skip Skip over the data in the {@link PdbByteReader}. * @throws PdbException upon error parsing filename
* @throws PdbException upon error parsing filename. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void processFileInformation(PdbByteReader reader, TaskMonitor monitor, boolean skip) protected void processFileInformation(PdbByteReader reader, boolean skip)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthFileInformation == 0) { if (lengthFileInformation == 0) {
return; return;
@ -484,7 +477,7 @@ public abstract class PdbDebugInfo {
int[] count = new int[numInformationModules]; int[] count = new int[numInformationModules];
int totalCount = 0; int totalCount = 0;
for (int moduleIndex = 0; moduleIndex < numInformationModules; moduleIndex++) { for (int moduleIndex = 0; moduleIndex < numInformationModules; moduleIndex++) {
monitor.checkCanceled(); pdb.checkCanceled();
index[moduleIndex] = indicesReader.parseUnsignedShortVal(); index[moduleIndex] = indicesReader.parseUnsignedShortVal();
count[moduleIndex] = countsReader.parseUnsignedShortVal(); count[moduleIndex] = countsReader.parseUnsignedShortVal();
totalCount += count[moduleIndex]; totalCount += count[moduleIndex];
@ -497,6 +490,7 @@ public abstract class PdbDebugInfo {
PdbByteReader offsetReader = fileInfoReader.getSubPdbByteReader(totalCount * 4); PdbByteReader offsetReader = fileInfoReader.getSubPdbByteReader(totalCount * 4);
int[] offset = new int[totalCount]; int[] offset = new int[totalCount];
for (int moduleIndex = 0; moduleIndex < totalCount; moduleIndex++) { for (int moduleIndex = 0; moduleIndex < totalCount; moduleIndex++) {
pdb.checkCanceled();
offset[moduleIndex] = offsetReader.parseInt(); offset[moduleIndex] = offsetReader.parseInt();
} }
PdbByteReader namesReader = PdbByteReader namesReader =
@ -504,8 +498,10 @@ public abstract class PdbDebugInfo {
int totalRefs = 0; int totalRefs = 0;
for (int moduleIndex = 0; moduleIndex < numInformationModules; moduleIndex++) { for (int moduleIndex = 0; moduleIndex < numInformationModules; moduleIndex++) {
AbstractModuleInformation module = moduleInformationList.get(moduleIndex); pdb.checkCanceled();
ModuleInformation module = moduleInformationList.get(moduleIndex);
for (int fileIndex = 0; fileIndex < count[moduleIndex]; fileIndex++) { for (int fileIndex = 0; fileIndex < count[moduleIndex]; fileIndex++) {
pdb.checkCanceled();
int ref = totalRefs + fileIndex; int ref = totalRefs + fileIndex;
int nameOffset = offset[ref]; int nameOffset = offset[ref];
namesReader.setIndex(nameOffset); namesReader.setIndex(nameOffset);
@ -518,7 +514,7 @@ public abstract class PdbDebugInfo {
/** /**
* Method to parse the filename for the "File Information" section from the * Method to parse the filename for the "File Information" section from the
* {@link PdbByteReader}. * {@link PdbByteReader}
* @param reader the {@link PdbByteReader} from which to parse the data * @param reader the {@link PdbByteReader} from which to parse the data
* @return the filename * @return the filename
* @throws PdbException upon error parsing the filename * @throws PdbException upon error parsing the filename
@ -527,11 +523,11 @@ public abstract class PdbDebugInfo {
/** /**
* Debug method for dumping information from this {@link PdbDebugInfo}-based * Debug method for dumping information from this {@link PdbDebugInfo}-based
* instance. * instance
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws IOException upon IOException writing to the {@link Writer}
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
protected void dump(Writer writer) throws IOException, CancelledException, PdbException { protected void dump(Writer writer) throws IOException, CancelledException, PdbException {
writer.write("DebugInfoHeader---------------------------------------------\n"); writer.write("DebugInfoHeader---------------------------------------------\n");
@ -546,12 +542,11 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Debug method for dumping additional substreams from this * Debug method for dumping additional substreams from this {@link PdbDebugInfo}-based instance
* {@link PdbDebugInfo}-based instance. * @param writer {@link Writer} to which to dump the information
* @param writer {@link Writer} to which to dump the information. * @throws IOException upon IOException writing to the {@link Writer}
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse
*/ */
protected void dumpAdditionalSubstreams(Writer writer) protected void dumpAdditionalSubstreams(Writer writer)
throws IOException, CancelledException, PdbException { throws IOException, CancelledException, PdbException {
@ -563,19 +558,22 @@ public abstract class PdbDebugInfo {
if (doNewStuff) { if (doNewStuff) {
dumpSymbols(writer); dumpSymbols(writer);
for (Module module : modules) { for (Module module : modules) {
pdb.checkCanceled();
module.dump(writer); module.dump(writer);
} }
} }
} }
/** /**
* Debug method for dumping module information for all of the {@link AbstractModuleInformation} * Debug method for dumping module information for all of the {@link ModuleInformation}
* modules from this {@link PdbDebugInfo}-based instance. * modules from this {@link PdbDebugInfo}-based instance
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws IOException upon IOException writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
protected void dumpModuleInformation(Writer writer) throws IOException { protected void dumpModuleInformation(Writer writer) throws IOException, CancelledException {
for (AbstractModuleInformation information : moduleInformationList) { for (ModuleInformation information : moduleInformationList) {
pdb.checkCanceled();
writer.write(information.dump()); writer.write(information.dump());
writer.write("\n"); writer.write("\n");
} }
@ -583,13 +581,14 @@ public abstract class PdbDebugInfo {
/** /**
* Debug method for dumping section contribution for all of the * Debug method for dumping section contribution for all of the
* {@link AbstractSectionContribution} components from this * {@link SectionContribution} components from this {@link PdbDebugInfo}-based instance
* {@link PdbDebugInfo}-based instance. * @param writer {@link Writer} to which to dump the information
* @param writer {@link Writer} to which to dump the information. * @throws IOException upon IOException writing to the {@link Writer}
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws CancelledException upon user cancellation
*/ */
protected void dumpSectionContributions(Writer writer) throws IOException { protected void dumpSectionContributions(Writer writer) throws IOException, CancelledException {
for (AbstractSectionContribution contribution : sectionContributionList) { for (SectionContribution contribution : sectionContributionList) {
pdb.checkCanceled();
writer.write(contribution.dump()); writer.write(contribution.dump());
writer.write("\n"); writer.write("\n");
} }
@ -597,13 +596,14 @@ public abstract class PdbDebugInfo {
/** /**
* Debug method for dumping segment map information for all of the * Debug method for dumping segment map information for all of the
* {@link SegmentMapDescription} components from this {@link PdbDebugInfo}-based * {@link SegmentMapDescription} components from this {@link PdbDebugInfo}-based instance
* instance. * @param writer {@link Writer} to which to dump the information
* @param writer {@link Writer} to which to dump the information. * @throws IOException upon IOException writing to the {@link Writer}
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws CancelledException upon user cancellation
*/ */
protected void dumpSegmentMap(Writer writer) throws IOException { protected void dumpSegmentMap(Writer writer) throws IOException, CancelledException {
for (SegmentMapDescription description : segmentMapList) { for (SegmentMapDescription description : segmentMapList) {
pdb.checkCanceled();
writer.write(description.dump()); writer.write(description.dump());
writer.write("\n"); writer.write("\n");
} }
@ -612,10 +612,10 @@ public abstract class PdbDebugInfo {
//============================================================================================== //==============================================================================================
// NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)... might be turned off // NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)... might be turned off
// during development. // during development.
private void parseModules(TaskMonitor monitor) throws CancelledException { private void parseModules() throws CancelledException {
for (AbstractModuleInformation moduleInformation : moduleInformationList) { for (ModuleInformation moduleInformation : moduleInformationList) {
monitor.checkCanceled(); pdb.checkCanceled();
Module module = new Module(pdb, moduleInformation, monitor); Module module = new Module(pdb, moduleInformation);
modules.add(module); modules.add(module);
} }
} }
@ -625,7 +625,7 @@ public abstract class PdbDebugInfo {
} }
/** /**
* Return the Module based upon the module number. * Return the Module based upon the module number
* @param moduleNum the module number * @param moduleNum the module number
* @return the module * @return the module
*/ */
@ -635,28 +635,27 @@ public abstract class PdbDebugInfo {
// NOTE: Designs are not done regarding possibly iterators for iterating only globals or publics // NOTE: Designs are not done regarding possibly iterators for iterating only globals or publics
/** /**
* Returns the symbol iterator for general (public and global symbols. * Returns the symbol iterator for general (public and global symbols
* @param monitor monitor for the job
* @return an iterator over all symbols of the module * @return an iterator over all symbols of the module
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
* @throws IOException upon issue reading the stream * @throws IOException upon issue reading the stream
*/ */
public MsSymbolIterator getSymbolIterator(TaskMonitor monitor) public MsSymbolIterator getSymbolIterator()
throws CancelledException, IOException { throws CancelledException, IOException {
if (streamNumberSymbolRecords == 0xffff) { if (streamNumberSymbolRecords == 0xffff) {
return null; return null;
} }
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumberSymbolRecords, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumberSymbolRecords);
MsSymbolIterator iterator = new MsSymbolIterator(pdb, reader); MsSymbolIterator iterator = new MsSymbolIterator(pdb, reader);
return iterator; return iterator;
} }
/** /**
* Returns the symbol iterator symbols of the specified module. * Returns the symbol iterator symbols of the specified module
* @param moduleNum the module number * @param moduleNum the module number
* @return an iterator over all symbols of the module * @return an iterator over all symbols of the module
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
*/ */
MsSymbolIterator getSymbolIterator(int moduleNum) throws CancelledException, PdbException { MsSymbolIterator getSymbolIterator(int moduleNum) throws CancelledException, PdbException {
Module module = modules.get(moduleNum); Module module = modules.get(moduleNum);
@ -664,17 +663,17 @@ public abstract class PdbDebugInfo {
} }
private void dumpSymbols(Writer writer) throws CancelledException, IOException { private void dumpSymbols(Writer writer) throws CancelledException, IOException {
// TODO: in GP-2367 (rename/refactor) ticket... put in appropriate monitor MsSymbolIterator iterator = getSymbolIterator();
MsSymbolIterator iterator = getSymbolIterator(TaskMonitor.DUMMY);
List<AbstractMsSymbol> symbols = new ArrayList<>(); List<AbstractMsSymbol> symbols = new ArrayList<>();
while (iterator.hasNext()) { while (iterator.hasNext()) {
pdb.checkCanceled();
symbols.add(iterator.next()); symbols.add(iterator.next());
} }
} }
// This method is temporary. It only exists for ensuring results as we transition processing // This method is temporary. It only exists for ensuring results as we transition processing
// mechanisms. // mechanisms.
private void compareSymbols(TaskMonitor monitor) private void compareSymbols()
throws CancelledException, PdbException, IOException { throws CancelledException, PdbException, IOException {
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo == null) { if (debugInfo == null) {
@ -682,9 +681,10 @@ public abstract class PdbDebugInfo {
} }
// Compare general symbols // Compare general symbols
MsSymbolIterator iterator = getSymbolIterator(monitor); MsSymbolIterator iterator = getSymbolIterator();
List<AbstractMsSymbol> symbols = new ArrayList<>(); List<AbstractMsSymbol> symbols = new ArrayList<>();
while (iterator.hasNext()) { while (iterator.hasNext()) {
pdb.checkCanceled();
symbols.add(iterator.next()); symbols.add(iterator.next());
} }
if (symbols.size() != symbolRecords.getSymbolsByOffset().size()) { if (symbols.size() != symbolRecords.getSymbolsByOffset().size()) {
@ -695,6 +695,7 @@ public abstract class PdbDebugInfo {
int cnt = 0; int cnt = 0;
for (Map.Entry<Long, AbstractMsSymbol> entry : symbolRecords.getSymbolsByOffset() for (Map.Entry<Long, AbstractMsSymbol> entry : symbolRecords.getSymbolsByOffset()
.entrySet()) { .entrySet()) {
pdb.checkCanceled();
AbstractMsSymbol msym = entry.getValue(); AbstractMsSymbol msym = entry.getValue();
AbstractMsSymbol lsym = symbols.get(cnt); AbstractMsSymbol lsym = symbols.get(cnt);
String mstr = msym.toString(); String mstr = msym.toString();
@ -709,17 +710,20 @@ public abstract class PdbDebugInfo {
// Compare module symbols // Compare module symbols
for (int modnum = 0; modnum < numModules(); modnum++) { for (int modnum = 0; modnum < numModules(); modnum++) {
pdb.checkCanceled();
Module module = modules.get(modnum); Module module = modules.get(modnum);
MsSymbolIterator moduleSymbolsIterator = module.getSymbolIterator(); MsSymbolIterator moduleSymbolsIterator = module.getSymbolIterator();
cnt = 0; cnt = 0;
Map<Long, AbstractMsSymbol> map = symbolRecords.getModuleSymbolsByOffset(modnum); Map<Long, AbstractMsSymbol> map = symbolRecords.getModuleSymbolsByOffset(modnum);
List<Long> keys = new ArrayList<>(); List<Long> keys = new ArrayList<>();
for (Map.Entry<Long, AbstractMsSymbol> entry : map.entrySet()) { for (Map.Entry<Long, AbstractMsSymbol> entry : map.entrySet()) {
pdb.checkCanceled();
Long key = entry.getKey(); Long key = entry.getKey();
keys.add(key); keys.add(key);
} }
Collections.sort(keys); Collections.sort(keys);
for (Long key : keys) { for (Long key : keys) {
pdb.checkCanceled();
AbstractMsSymbol msym = map.get(key); AbstractMsSymbol msym = map.get(key);
if (!moduleSymbolsIterator.hasNext()) { if (!moduleSymbolsIterator.hasNext()) {
// Set break-point on next line. Multiple lines here to eliminate Eclipse warning. // Set break-point on next line. Multiple lines here to eliminate Eclipse warning.

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* Parser for detecting the appropriate {@link PdbDebugInfo} format for the filename * Parser for detecting the appropriate {@link PdbDebugInfo} format for the filename
@ -44,13 +43,13 @@ public class PdbDebugInfoParser {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Parses information to determine the version of Database Interface to create. * Parses information to determine the version of debug info to create
* @param pdb {@link AbstractPdb} that owns this Database Interface. * @param pdb {@link AbstractPdb} that owns this debug info
* @return {@link PdbDebugInfo} of the appropriate Database Interface or null if * @return {@link PdbDebugInfo} of the appropriate debug info or null if the stream does not
* the stream does not have enough information to be parsed. * have enough information to be parsed
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
* @throws PdbException Upon error in processing components. * @throws PdbException upon error in processing components
*/ */
public PdbDebugInfo parse(AbstractPdb pdb) throws IOException, PdbException { public PdbDebugInfo parse(AbstractPdb pdb) throws IOException, PdbException {
PdbDebugInfo debugInfo; PdbDebugInfo debugInfo;
@ -58,7 +57,7 @@ public class PdbDebugInfoParser {
int streamNumber = getStreamNumber(); int streamNumber = getStreamNumber();
// Only reading 8-bytes - no need for monitor // Only reading 8-bytes - no need for monitor
PdbByteReader reader = PdbByteReader reader =
pdb.getReaderForStreamNumber(streamNumber, 0, 8, TaskMonitor.DUMMY); pdb.getReaderForStreamNumber(streamNumber, 0, 8);
if (reader.getLimit() == 0) { if (reader.getLimit() == 0) {
return null; return null;
} }
@ -102,8 +101,8 @@ public class PdbDebugInfoParser {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Returns the standard stream number that contains the serialized Database Interface. * Returns the standard stream number that contains the serialized debug info
* @return Stream number that contains the Database Interface. * @return stream number that contains the debug info
*/ */
protected int getStreamNumber() { protected int getStreamNumber() {
return DEBUG_INFO_STREAM_NUMBER; return DEBUG_INFO_STREAM_NUMBER;

View file

@ -40,8 +40,8 @@ public class PdbLog {
* method gives control to the client to be able to turn on/off the messaging output without * method gives control to the client to be able to turn on/off the messaging output without
* having to do conditional checks at each point that one of the messaging methods is called. * having to do conditional checks at each point that one of the messaging methods is called.
* @param enable {@code true} to enable logging; {@code false} to disable logging. Initial * @param enable {@code true} to enable logging; {@code false} to disable logging. Initial
* state is {@code false}. * state is {@code false}
* @throws IOException upon problem creating a {@link FileWriter}. * @throws IOException upon problem creating a {@link FileWriter}
* @see #message(String) * @see #message(String)
* @see #message(String, Supplier...) * @see #message(String, Supplier...)
*/ */
@ -53,11 +53,11 @@ public class PdbLog {
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method * 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 * 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 * 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 * @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. * which must only specify {@code %s} {@link String} outputs.
* @param suppliers variable number of {@link Supplier}&lt;{@link String}&gt; arguments. The * @param suppliers variable number of {@link Supplier}&lt;{@link String}&gt; 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) * @see #setEnabled(boolean)
*/ */
// We know this is @SafeVarags (or SuppressWarnings("unchecked")) on potential // We know this is @SafeVarags (or SuppressWarnings("unchecked")) on potential
@ -89,9 +89,9 @@ public class PdbLog {
* Outputs a message to the PDB log if messaging has been enable, else ignored. This method * Outputs a message to the PDB log if messaging has been enable, else ignored. This method
* uses a {@link Supplier}&lt;{@link String}&gt; to allow for deferred processing of the message * uses a {@link Supplier}&lt;{@link String}&gt; to allow for deferred processing of the message
* to output. Thus, when message output is disabled, the client does not endure as much cost * 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}&lt;{@link String}&gt; that supplies a {@link String} * @param supplier a {@link Supplier}&lt;{@link String}&gt; that supplies a {@link String}
* message to be output. * message to be output
* @see #setEnabled(boolean) * @see #setEnabled(boolean)
*/ */
public static void message(Supplier<String> supplier) { public static void message(Supplier<String> supplier) {
@ -111,8 +111,8 @@ public class PdbLog {
} }
/** /**
* Outputs a {@link String} message to the PDB log if messaging has been enable, else ignored. * Outputs a {@link String} message to the PDB log if messaging has been enable, else ignored
* @param message a {@link String} message to be output. * @param message a {@link String} message to be output
* @see #setEnabled(boolean) * @see #setEnabled(boolean)
*/ */
public static void message(String message) { public static void message(String message) {
@ -145,17 +145,17 @@ public class PdbLog {
// might not have been read, depending on the order of how record sets are read. // might not have been read, depending on the order of how record sets are read.
// TODO: is using PdbLog here. Is that what we intend? // TODO: is using PdbLog here. Is that what we intend?
/** /**
* Logs fact of record index out of range (detection is performed by caller). * Logs fact of record index out of range (detection is performed by caller)
* @param tpi the TypeProgramInterface involved. * @param tpi the TypeProgramInterface involved
* @param recordNumber the record number to report. * @param recordNumber the record number to report
*/ */
public static void logBadTypeRecordIndex(AbstractTypeProgramInterface tpi, int recordNumber) { public static void logBadTypeRecordIndex(TypeProgramInterface tpi, int recordNumber) {
message("Bad requested type record " + recordNumber + ", min: " + tpi.getTypeIndexMin() + message("Bad requested type record " + recordNumber + ", min: " + tpi.getTypeIndexMin() +
", max: " + tpi.getTypeIndexMaxExclusive()); ", max: " + tpi.getTypeIndexMaxExclusive());
} }
/** /**
* Logs fact of record index out of range (detection is performed by caller). * Logs fact of record index out of range (detection is performed by caller)
* @param type {@link AbstractMsType} found * @param type {@link AbstractMsType} found
* @param itemRequiredClass class expected * @param itemRequiredClass class expected
*/ */
@ -165,7 +165,7 @@ public class PdbLog {
} }
/** /**
* Cleans up the class by closing resources. * Cleans up the class by closing resources
*/ */
public static void dispose() { public static void dispose() {
try { try {
@ -180,8 +180,8 @@ public class PdbLog {
} }
/** /**
* Returns the {@link Writer} for logging. * Returns the {@link Writer} for logging
* @return a {@link Writer} for for logging. * @return a {@link Writer} for for logging
*/ */
private static Writer getWriter() throws IOException { private static Writer getWriter() throws IOException {
return enabled ? getFileWriter() : getNullWriter(); return enabled ? getFileWriter() : getNullWriter();
@ -189,8 +189,8 @@ public class PdbLog {
/** /**
* Returns the {@link FileWriter} for the log file. If the file is already open, it is * 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. * 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 getFileWriter() throws IOException { private static Writer getFileWriter() throws IOException {
if (fileWriter == null) { if (fileWriter == null) {
@ -210,8 +210,8 @@ public class PdbLog {
/** /**
* Returns a {@link NullWriter} for the log file when chosen instead of a FileWriter. If * 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. * one already exists, it is returned. Otherwise a new one is created
* @return a {@link NullWriter} for the log file. * @return a {@link NullWriter} for the log file
*/ */
private static Writer getNullWriter() { private static Writer getNullWriter() {
if (nullWriter == null) { if (nullWriter == null) {

View file

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link PdbDebugInfo} for newer PDB files. * This class is the version of {@link PdbDebugInfo} for newer PDB files.
@ -63,9 +62,9 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link PdbNewDebugInfo}. * @param pdb {@link AbstractPdb} that owns this {@link PdbNewDebugInfo}
* @param streamNumber The stream number that contains the {@link PdbNewDebugInfo} data. * @param streamNumber the stream number that contains the {@link PdbNewDebugInfo} data
*/ */
public PdbNewDebugInfo(AbstractPdb pdb, int streamNumber) { public PdbNewDebugInfo(AbstractPdb pdb, int streamNumber) {
super(pdb, streamNumber); super(pdb, streamNumber);
@ -73,16 +72,16 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
} }
/** /**
* Returns the {@link ImageFileMachine} machine type. * Returns the {@link ImageFileMachine} machine type
* @return the machine type. * @return the machine type
*/ */
public ImageFileMachine getMachineType() { public ImageFileMachine getMachineType() {
return machineType; return machineType;
} }
/** /**
* Returns the {@link DebugData} for this {@link PdbNewDebugInfo}. * Returns the {@link DebugData} for this {@link PdbNewDebugInfo}
* @return the {@link DebugData}. * @return the {@link DebugData}
*/ */
public DebugData getDebugData() { public DebugData getDebugData() {
return debugData; return debugData;
@ -133,34 +132,34 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
} }
@Override @Override
protected void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor) protected void deserializeInternalSubstreams(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
processModuleInformation(reader, monitor, false); processModuleInformation(reader, false);
processSectionContributions(reader, monitor, false); processSectionContributions(reader, false);
processSegmentMap(reader, monitor, false); processSegmentMap(reader, false);
processFileInformation(reader, monitor, false); processFileInformation(reader, false);
processTypeServerMap(reader, false); processTypeServerMap(reader, false);
//Note that the next two are in reverse order from their length fields in the header. //Note that the next two are in reverse order from their length fields in the header.
processEditAndContinueInformation(reader, monitor, false); processEditAndContinueInformation(reader, false);
//processDebugHeader(reader, false); //processDebugHeader(reader, false);
debugData.deserializeHeader(reader, monitor); debugData.deserializeHeader(reader);
} }
@Override @Override
protected void deserializeAdditionalSubstreams(TaskMonitor monitor) protected void deserializeAdditionalSubstreams()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// TODO: evaluate. I don't think we need GlobalSymbolInformation (hash) or the // TODO: evaluate. I don't think we need GlobalSymbolInformation (hash) or the
// PublicSymbolInformation (hash), as they are both are search mechanisms. // PublicSymbolInformation (hash), as they are both are search mechanisms.
symbolRecords.deserialize(monitor); symbolRecords.deserialize();
globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber(), monitor); globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber());
publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber(), monitor); publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber());
//TODO: Process further information that might be found from ProcessTypeServerMap, //TODO: Process further information that might be found from ProcessTypeServerMap,
// and processEditAndContinueInformation. // and processEditAndContinueInformation.
debugData.deserialize(monitor); debugData.deserialize();
} }
@Override @Override
protected void processModuleInformation(PdbByteReader reader, TaskMonitor monitor, boolean skip) protected void processModuleInformation(PdbByteReader reader, boolean skip)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthModuleInformationSubstream == 0) { if (lengthModuleInformationSubstream == 0) {
return; return;
@ -172,8 +171,8 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
PdbByteReader substreamReader = PdbByteReader substreamReader =
reader.getSubPdbByteReader(lengthModuleInformationSubstream); reader.getSubPdbByteReader(lengthModuleInformationSubstream);
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
AbstractModuleInformation moduleInformation = new ModuleInformation600(pdb); ModuleInformation moduleInformation = new ModuleInformation600(pdb);
moduleInformation.deserialize(substreamReader); moduleInformation.deserialize(substreamReader);
moduleInformationList.add(moduleInformation); moduleInformationList.add(moduleInformation);
} }
@ -230,7 +229,7 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
} }
@Override @Override
protected void dumpInternalSubstreams(Writer writer) throws IOException { protected void dumpInternalSubstreams(Writer writer) throws IOException, CancelledException {
writer.write("ModuleInformationList---------------------------------------\n"); writer.write("ModuleInformationList---------------------------------------\n");
dumpModuleInformation(writer); dumpModuleInformation(writer);
writer.write("\nEnd ModuleInformationList-----------------------------------\n"); writer.write("\nEnd ModuleInformationList-----------------------------------\n");
@ -251,10 +250,10 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
//============================================================================================== //==============================================================================================
//TODO: Find examples that exercise this. //TODO: Find examples that exercise this.
/** /**
* Deserializes/Processes the TypeServerMap. * Deserializes/processes the TypeServerMap
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param skip Skip over the data in the {@link PdbByteReader}. * @param skip skip over the data in the {@link PdbByteReader}
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
@SuppressWarnings("unused") // substreamReader @SuppressWarnings("unused") // substreamReader
protected void processTypeServerMap(PdbByteReader reader, boolean skip) throws PdbException { protected void processTypeServerMap(PdbByteReader reader, boolean skip) throws PdbException {
@ -270,16 +269,15 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
} }
/** /**
* Deserializes/Processes the EditAndContinueInformation. * Deserializes/processes the EditAndContinueInformation
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param skip skip over the data in the {@link PdbByteReader}
* @param skip Skip over the data in the {@link PdbByteReader}. * @throws PdbException upon error parsing a name or unexpected data
* @throws PdbException upon error parsing a name or unexpected data. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
@SuppressWarnings("unused") // hashVal @SuppressWarnings("unused") // hashVal
protected void processEditAndContinueInformation(PdbByteReader reader, TaskMonitor monitor, protected void processEditAndContinueInformation(PdbByteReader reader, boolean skip)
boolean skip) throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthEditAndContinueSubstream == 0) { if (lengthEditAndContinueSubstream == 0) {
return; return;
} }
@ -312,7 +310,7 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
int count = tableSize; int count = tableSize;
int realEntryCount = 0; int realEntryCount = 0;
while (--count >= 0) { while (--count >= 0) {
monitor.checkCanceled(); pdb.checkCanceled();
int offset = substreamReader.parseInt(); int offset = substreamReader.parseInt();
bufferReader.setIndex(offset); bufferReader.setIndex(offset);
String name = bufferReader.parseNullTerminatedString( String name = bufferReader.parseNullTerminatedString(
@ -336,8 +334,8 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
/** /**
* Dumps the EditAndContinueNameList. This package-protected method is for debugging only. * Dumps the EditAndContinueNameList. This package-protected method is for debugging only.
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
*/ */
protected void dumpEditAndContinueNameList(Writer writer) throws IOException { protected void dumpEditAndContinueNameList(Writer writer) throws IOException {
for (String name : editAndContinueNameList) { for (String name : editAndContinueNameList) {

View file

@ -19,7 +19,6 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link PdbDebugInfo} for older PDB files. * This class is the version of {@link PdbDebugInfo} for older PDB files.
@ -34,9 +33,9 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link PdbOldDebugInfo}. * @param pdb {@link AbstractPdb} that owns this {@link PdbOldDebugInfo}
* @param streamNumber The number of the stream that contains the {@link PdbOldDebugInfo}. * @param streamNumber the number of the stream that contains the {@link PdbOldDebugInfo}
*/ */
public PdbOldDebugInfo(AbstractPdb pdb, int streamNumber) { public PdbOldDebugInfo(AbstractPdb pdb, int streamNumber) {
super(pdb, streamNumber); super(pdb, streamNumber);
@ -62,28 +61,28 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
} }
@Override @Override
protected void deserializeInternalSubstreams(PdbByteReader reader, TaskMonitor monitor) protected void deserializeInternalSubstreams(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
processModuleInformation(reader, monitor, false); processModuleInformation(reader, false);
processSectionContributions(reader, monitor, false); processSectionContributions(reader, false);
processSegmentMap(reader, monitor, false); processSegmentMap(reader, false);
processFileInformation(reader, monitor, false); processFileInformation(reader, false);
} }
@Override @Override
protected void deserializeAdditionalSubstreams(TaskMonitor monitor) protected void deserializeAdditionalSubstreams()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// TODO: evaluate. I don't think we need GlobalSymbolInformation (hash) or the // TODO: evaluate. I don't think we need GlobalSymbolInformation (hash) or the
// PublicSymbolInformation (hash), as they are both are search mechanisms. // PublicSymbolInformation (hash), as they are both are search mechanisms.
symbolRecords.deserialize(monitor); symbolRecords.deserialize();
globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber(), monitor); globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber());
publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber(), monitor); publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber());
//TODO: SectionContributions has information about code sections and refers to //TODO: SectionContributions has information about code sections and refers to
// debug streams for each. // debug streams for each.
} }
@Override @Override
protected void processModuleInformation(PdbByteReader reader, TaskMonitor monitor, boolean skip) protected void processModuleInformation(PdbByteReader reader, boolean skip)
throws PdbException, CancelledException { throws PdbException, CancelledException {
if (lengthModuleInformationSubstream == 0) { if (lengthModuleInformationSubstream == 0) {
return; return;
@ -95,8 +94,8 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
PdbByteReader substreamReader = PdbByteReader substreamReader =
reader.getSubPdbByteReader(lengthModuleInformationSubstream); reader.getSubPdbByteReader(lengthModuleInformationSubstream);
while (substreamReader.hasMore()) { while (substreamReader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
AbstractModuleInformation moduleInformation = new ModuleInformation500(pdb); ModuleInformation moduleInformation = new ModuleInformation500(pdb);
moduleInformation.deserialize(substreamReader); moduleInformation.deserialize(substreamReader);
moduleInformationList.add(moduleInformation); moduleInformationList.add(moduleInformation);
} }
@ -129,7 +128,7 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
} }
@Override @Override
protected void dumpInternalSubstreams(Writer writer) throws IOException { protected void dumpInternalSubstreams(Writer writer) throws IOException, CancelledException {
writer.write("ModuleInformationList---------------------------------------\n"); writer.write("ModuleInformationList---------------------------------------\n");
dumpModuleInformation(writer); dumpModuleInformation(writer);
writer.write("\nEnd ModuleInformationList-----------------------------------\n"); writer.write("\nEnd ModuleInformationList-----------------------------------\n");

View file

@ -18,7 +18,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.AbstractMsf; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.Msf;
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfParser; import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfParser;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -43,16 +43,16 @@ public class PdbParser {
/** /**
* Static method to open a PDB file, determine its version, and return an {@link AbstractPdb} * Static method to open a PDB file, determine its version, and return an {@link AbstractPdb}
* appropriate for that version; it will not have been deserialized. The main method * appropriate for that version; it will not have been deserialized. The main method
* to deserialize it is {@link AbstractPdb#deserialize(TaskMonitor monitor)}; the method * to deserialize it is {@link AbstractPdb#deserialize()}; the method
* used to deserialize its main identifiers (signature, age, guid (if available)) is * used to deserialize its main identifiers (signature, age, guid (if available)) is
* {@link AbstractPdb#deserializeIdentifiersOnly(TaskMonitor monitor)}. * {@link AbstractPdb#deserializeIdentifiersOnly(TaskMonitor monitor)}
* @param filename {@link String} pathname of the PDB file to parse. * @param filename {@link String} pathname of the PDB file to parse
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param monitor {@link TaskMonitor} used for checking cancellation
* @return {@link AbstractPdb} class object for the file. * @return {@link AbstractPdb} class object for the file
* @throws IOException on file I/O issues. * @throws IOException on file I/O issues
* @throws PdbException on parsing issues. * @throws PdbException on parsing issues
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
public static AbstractPdb parse(String filename, PdbReaderOptions pdbOptions, public static AbstractPdb parse(String filename, PdbReaderOptions pdbOptions,
TaskMonitor monitor) throws IOException, PdbException, CancelledException { TaskMonitor monitor) throws IOException, PdbException, CancelledException {
@ -62,7 +62,7 @@ public class PdbParser {
// Do not do a try with resources here, as the msf must live within the PDB that is // Do not do a try with resources here, as the msf must live within the PDB that is
// created below. // created below.
AbstractMsf msf = MsfParser.parse(filename, pdbOptions, monitor); Msf msf = MsfParser.parse(filename, pdbOptions, monitor);
int versionNumber = AbstractPdb.deserializeVersionNumber(msf, monitor); int versionNumber = AbstractPdb.deserializeVersionNumber(msf, monitor);

View file

@ -20,7 +20,6 @@ import java.io.Writer;
import java.util.*; import java.util.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents Public Symbol Information component of a PDB file. This class is only * This class represents Public Symbol Information component of a PDB file. This class is only
@ -56,56 +55,56 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdbIn {@link AbstractPdb} that owns the Public Symbol Information to process. * @param pdbIn {@link AbstractPdb} that owns the Public Symbol Information to process
*/ */
public PublicSymbolInformation(AbstractPdb pdbIn) { public PublicSymbolInformation(AbstractPdb pdbIn) {
super(pdbIn); super(pdbIn);
} }
/** /**
* Returns the number of thunks in the thunk table. * Returns the number of thunks in the thunk table
* @return the number of thunks. * @return the number of thunks
*/ */
public int getNumThunks() { public int getNumThunks() {
return numThunks; return numThunks;
} }
/** /**
* Returns the section within which the thunk table is located. * Returns the section within which the thunk table is located
* @return the section of the thunk table. * @return the section of the thunk table
*/ */
public int getThunkTableSection() { public int getThunkTableSection() {
return iSectionThunkTable; return iSectionThunkTable;
} }
/** /**
* Returns the offset of the thunk table within the section it is located. * Returns the offset of the thunk table within the section it is located
* @return the offset of the thunk table. * @return the offset of the thunk table
*/ */
public int getThunkTableOffset() { public int getThunkTableOffset() {
return offsetThunkTable; return offsetThunkTable;
} }
/** /**
* Returns the size of each thunk in the thunk table. * Returns the size of each thunk in the thunk table
* @return the size of a thunk. * @return the size of a thunk
*/ */
public int getThunkSize() { public int getThunkSize() {
return thunkSize; return thunkSize;
} }
/** /**
* Returns the overall length of the thunk table. * Returns the overall length of the thunk table
* @return the thunk table length. * @return the thunk table length
*/ */
public int getThunkTableLength() { public int getThunkTableLength() {
return thunkTableLength; return thunkTableLength;
} }
/** /**
* Returns the number of sections recorded for the program. * Returns the number of sections recorded for the program
* @return the number of sections. * @return the number of sections
*/ */
public int getNumSections() { public int getNumSections() {
return numSections; return numSections;
@ -113,7 +112,7 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
/** /**
* Returns the Offsets of symbols within the symbol table gotten from the address map. These * Returns the Offsets of symbols within the symbol table gotten from the address map. These
* offsets to point to the size field of the symbols in the symbol table. * offsets to point to the size field of the symbols in the symbol table
* @return offsets * @return offsets
*/ */
public List<Long> getAddressMapSymbolOffsets() { public List<Long> getAddressMapSymbolOffsets() {
@ -124,31 +123,30 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Deserialize the {@link PublicSymbolInformation} from the appropriate stream in the Pdb. * Deserialize the {@link PublicSymbolInformation} from the appropriate stream in the Pdb
* @param streamNumber the stream number containing the information to deserialize. * @param streamNumber the stream number containing the information to deserialize
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
@Override @Override
void deserialize(int streamNumber, TaskMonitor monitor) void deserialize(int streamNumber)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
super.deserialize(streamNumber, monitor); super.deserialize(streamNumber);
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
deserializePubHeader(reader); deserializePubHeader(reader);
PdbByteReader hashReader = reader.getSubPdbByteReader(symbolHashLength); PdbByteReader hashReader = reader.getSubPdbByteReader(symbolHashLength);
deserializeHashTable(hashReader, monitor); deserializeHashTable(hashReader);
PdbByteReader addressMapReader = reader.getSubPdbByteReader(addressMapLength); PdbByteReader addressMapReader = reader.getSubPdbByteReader(addressMapLength);
deserializeAddressMap(addressMapReader, monitor); deserializeAddressMap(addressMapReader);
PdbByteReader thunkMapReader = reader.getSubPdbByteReader(thunkMapLength); PdbByteReader thunkMapReader = reader.getSubPdbByteReader(thunkMapLength);
deserializeThunkMap(thunkMapReader, monitor); deserializeThunkMap(thunkMapReader);
/* /*
* See note in {@link #deserializePubHeader(PdbByteReader)} regarding spurious data * See note in {@link #deserializePubHeader(PdbByteReader)} regarding spurious data
@ -161,19 +159,20 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
} }
numSections = sectionMapLength / 8; numSections = sectionMapLength / 8;
PdbByteReader sectionMapReader = reader.getSubPdbByteReader(sectionMapLength); PdbByteReader sectionMapReader = reader.getSubPdbByteReader(sectionMapLength);
deserializeSectionMap(sectionMapReader, monitor); deserializeSectionMap(sectionMapReader);
// Organize the information // Organize the information
generateSymbolsList(monitor); generateSymbolsList();
} }
/** /**
* Debug method for dumping information from this {@link PublicSymbolInformation}. * Debug method for dumping information from this {@link PublicSymbolInformation}
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer}. * @throws IOException upon IOException writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
@Override @Override
void dump(Writer writer) throws IOException { void dump(Writer writer) throws IOException, CancelledException {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("PublicSymbolInformation-------------------------------------\n"); builder.append("PublicSymbolInformation-------------------------------------\n");
dumpPubHeader(builder); dumpPubHeader(builder);
@ -193,23 +192,22 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
// Private Internals // Private Internals
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Address Map for these public symbols. * Deserializes the Address Map for these public symbols
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeAddressMap(PdbByteReader reader, TaskMonitor monitor) private void deserializeAddressMap(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
addressMapSymbolOffsets.add((long) reader.parseInt()); addressMapSymbolOffsets.add((long) reader.parseInt());
} }
} }
/** /**
* Debug method for dumping Address Map information from this {@link AbstractSymbolInformation}. * Debug method for dumping Address Map information from this {@link AbstractSymbolInformation}
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
*/ */
private void dumpAddressMap(StringBuilder builder) { private void dumpAddressMap(StringBuilder builder) {
builder.append("AddressMapSymbolOffsets-------------------------------------\n"); builder.append("AddressMapSymbolOffsets-------------------------------------\n");
@ -222,17 +220,16 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
} }
/** /**
* Deserializes the Thunk Map for these public symbols. * Deserializes the Thunk Map for these public symbols
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeThunkMap(PdbByteReader reader, TaskMonitor monitor) private void deserializeThunkMap(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
int count = 0; int count = 0;
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
int targetOffset = reader.parseInt(); int targetOffset = reader.parseInt();
int mapTableOffset = count * thunkSize + offsetThunkTable; int mapTableOffset = count * thunkSize + offsetThunkTable;
thunkTargetOffsetsByTableOffset.put(mapTableOffset, targetOffset); thunkTargetOffsetsByTableOffset.put(mapTableOffset, targetOffset);
@ -240,8 +237,8 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping Thunk Map information from this {@link AbstractSymbolInformation}. * Debug method for dumping Thunk Map information from this {@link AbstractSymbolInformation}
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
*/ */
private void dumpThunkMap(StringBuilder builder) { private void dumpThunkMap(StringBuilder builder) {
builder.append("ThunkMap----------------------------------------------------\n"); builder.append("ThunkMap----------------------------------------------------\n");
@ -254,16 +251,15 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
} }
/** /**
* Deserializes the Section Map for these public symbols. * Deserializes the Section Map for these public symbols
* @param reader {@link PdbByteReader} containing the data buffer to process. * @param reader {@link PdbByteReader} containing the data buffer to process
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
private void deserializeSectionMap(PdbByteReader reader, TaskMonitor monitor) private void deserializeSectionMap(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
int offset = reader.parseInt(); int offset = reader.parseInt();
int section = reader.parseUnsignedShortVal(); int section = reader.parseUnsignedShortVal();
reader.skip(2); // padding reader.skip(2); // padding
@ -272,22 +268,24 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
} }
/** /**
* Debug method for dumping Section Map information from this {@link AbstractSymbolInformation}. * Debug method for dumping Section Map information from this {@link AbstractSymbolInformation}
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
* @throws CancelledException upon user cancellation
*/ */
private void dumpSectionMap(StringBuilder builder) { private void dumpSectionMap(StringBuilder builder) throws CancelledException {
builder.append("SectionMap--------------------------------------------------\n"); builder.append("SectionMap--------------------------------------------------\n");
builder.append( builder.append(
"numAbsoluteOffsetsBySectionNumber: " + absoluteOffsetsBySectionNumber.size() + "\n"); "numAbsoluteOffsetsBySectionNumber: " + absoluteOffsetsBySectionNumber.size() + "\n");
for (Map.Entry<Integer, Integer> entry : absoluteOffsetsBySectionNumber.entrySet()) { for (Map.Entry<Integer, Integer> entry : absoluteOffsetsBySectionNumber.entrySet()) {
pdb.checkCanceled();
builder.append(String.format("0X%08X 0X%08X\n", entry.getKey(), entry.getValue())); builder.append(String.format("0X%08X 0X%08X\n", entry.getKey(), entry.getValue()));
} }
builder.append("\nEnd SectionMap----------------------------------------------\n"); builder.append("\nEnd SectionMap----------------------------------------------\n");
} }
/** /**
* Debug method for dumping the {@link PublicSymbolInformation} header. * Debug method for dumping the {@link PublicSymbolInformation} header
* @param builder {@link StringBuilder} to which to dump the information. * @param builder {@link StringBuilder} to which to dump the information
*/ */
private void dumpPubHeader(StringBuilder builder) { private void dumpPubHeader(StringBuilder builder) {
builder.append("PublicSymbolInformationHeader-------------------------------\n"); builder.append("PublicSymbolInformationHeader-------------------------------\n");

View file

@ -22,7 +22,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
* We have intended to implement according to the Microsoft PDB API (source); see the API for * We have intended to implement according to the Microsoft PDB API (source); see the API for
* truth. * truth.
*/ */
public abstract class AbstractSectionContribution { public abstract class SectionContribution {
//============================================================================================== //==============================================================================================
// Internals // Internals
@ -41,7 +41,7 @@ public abstract class AbstractSectionContribution {
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
public AbstractSectionContribution() { public SectionContribution() {
} }
public int getSection() { public int getSection() {
@ -69,15 +69,15 @@ public abstract class AbstractSectionContribution {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Section Contribution. * Deserializes the Section Contribution
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
abstract void deserialize(PdbByteReader reader) throws PdbException; abstract void deserialize(PdbByteReader reader) throws PdbException;
/** /**
* Dumps the SectionContribution. This method is for debugging only. * Dumps the SectionContribution. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
abstract String dumpInternals(); abstract String dumpInternals();
@ -85,8 +85,8 @@ public abstract class AbstractSectionContribution {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Dumps the Section Contribution. This method is for debugging only. * Dumps the Section Contribution. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
String dump() { String dump() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();

View file

@ -16,16 +16,15 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractSectionContribution} for Microsoft v14.00 PDB. * This class is the version of {@link SectionContribution} for Microsoft v14.00 PDB.
*/ */
public class SectionContribution1400 extends AbstractSectionContribution { public class SectionContribution1400 extends SectionContribution {
//============================================================================================== //==============================================================================================
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserialize(PdbByteReader reader) throws PdbException { void deserialize(PdbByteReader reader) throws PdbException {
//System.out.println(reader.dump(0x200));
isect = reader.parseUnsignedShortVal(); isect = reader.parseUnsignedShortVal();
reader.parseBytes(2); // I think there is padding here. reader.parseBytes(2); // I think there is padding here.
offset = reader.parseInt(); offset = reader.parseInt();

View file

@ -16,16 +16,15 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractSectionContribution} for Microsoft v2.00 PDB. * This class is the version of {@link SectionContribution} for Microsoft v2.00 PDB.
*/ */
public class SectionContribution200 extends AbstractSectionContribution { public class SectionContribution200 extends SectionContribution {
//============================================================================================== //==============================================================================================
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserialize(PdbByteReader reader) throws PdbException { void deserialize(PdbByteReader reader) throws PdbException {
//System.out.println(reader.dump());
isect = reader.parseUnsignedShortVal(); isect = reader.parseUnsignedShortVal();
offset = reader.parseInt(); offset = reader.parseInt();
length = reader.parseInt(); length = reader.parseInt();

View file

@ -16,16 +16,15 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractSectionContribution} for Microsoft v4.00 PDB. * This class is the version of {@link SectionContribution} for Microsoft v4.00 PDB.
*/ */
public class SectionContribution400 extends AbstractSectionContribution { public class SectionContribution400 extends SectionContribution {
//============================================================================================== //==============================================================================================
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserialize(PdbByteReader reader) throws PdbException { void deserialize(PdbByteReader reader) throws PdbException {
//System.out.println(reader.dump(0x200));
isect = reader.parseUnsignedShortVal(); isect = reader.parseUnsignedShortVal();
reader.parseBytes(2); // I think there is padding here. reader.parseBytes(2); // I think there is padding here.
offset = reader.parseInt(); offset = reader.parseInt();

View file

@ -16,16 +16,15 @@
package ghidra.app.util.bin.format.pdb2.pdbreader; package ghidra.app.util.bin.format.pdb2.pdbreader;
/** /**
* This class is the version of {@link AbstractSectionContribution} for Microsoft v6.00 PDB. * This class is the version of {@link SectionContribution} for Microsoft v6.00 PDB.
*/ */
public class SectionContribution600 extends AbstractSectionContribution { public class SectionContribution600 extends SectionContribution {
//============================================================================================== //==============================================================================================
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
@Override @Override
void deserialize(PdbByteReader reader) throws PdbException { void deserialize(PdbByteReader reader) throws PdbException {
//System.out.println(reader.dump(0x200));
isect = reader.parseUnsignedShortVal(); isect = reader.parseUnsignedShortVal();
reader.parseBytes(2); // I think there is padding here. reader.parseBytes(2); // I think there is padding here.
offset = reader.parseInt(); offset = reader.parseInt();

View file

@ -21,7 +21,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol; import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents Symbol Records component of a PDB file. This class is only * This class represents Symbol Records component of a PDB file. This class is only
@ -37,8 +36,8 @@ public class SymbolRecords {
private List<Map<Long, AbstractMsSymbol>> moduleSymbolsByOffset = new ArrayList<>(); private List<Map<Long, AbstractMsSymbol>> moduleSymbolsByOffset = new ArrayList<>();
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} to which the {@link SymbolRecords} belong. * @param pdb {@link AbstractPdb} to which the {@link SymbolRecords} belong
*/ */
public SymbolRecords(AbstractPdb pdb) { public SymbolRecords(AbstractPdb pdb) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
@ -46,38 +45,37 @@ public class SymbolRecords {
} }
/** /**
* Returns the list of symbols. * Returns the list of symbols
* @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to * @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to
* symbols. * symbols
*/ */
protected Map<Long, AbstractMsSymbol> getSymbolsByOffset() { protected Map<Long, AbstractMsSymbol> getSymbolsByOffset() {
return symbolsByOffset; return symbolsByOffset;
} }
/** /**
* Returns the buffer-offset-to-symbol map for the module as specified by moduleNumber. * Returns the buffer-offset-to-symbol map for the module as specified by moduleNumber
* @param moduleNumber The number ID of the module for which to return the list. * @param moduleNumber the number ID of the module for which to return the list
* @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to * @return {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; of buffer offsets to
* symbols for the specified module. * symbols for the specified module
*/ */
protected Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber) { protected Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber) {
return moduleSymbolsByOffset.get(moduleNumber); return moduleSymbolsByOffset.get(moduleNumber);
} }
/** /**
* Deserializes the {@link SymbolRecords} from the stream noted in the DBI header. * Deserializes the {@link SymbolRecords} from the stream noted in the DBI header
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes * inability to read required bytes
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
*/ */
void deserialize(TaskMonitor monitor) throws IOException, PdbException, CancelledException { void deserialize() throws IOException, PdbException, CancelledException {
processSymbols(monitor); processSymbols();
processModuleSymbols(monitor); processModuleSymbols();
} }
private void processSymbols(TaskMonitor monitor) private void processSymbols()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo == null) { if (debugInfo == null) {
@ -87,14 +85,14 @@ public class SymbolRecords {
if (streamNumber <= 0) { if (streamNumber <= 0) {
return; return;
} }
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
symbolsByOffset = deserializeSymbolRecords(pdb, reader, monitor); symbolsByOffset = deserializeSymbolRecords(pdb, reader);
} }
// Could split this method up into separate methods: one for module symbols and the other for // Could split this method up into separate methods: one for module symbols and the other for
// Lines processing. Note: would be processing streams more than once; lines would need to // Lines processing. Note: would be processing streams more than once; lines would need to
// skip over the symbols. // skip over the symbols.
private void processModuleSymbols(TaskMonitor monitor) private void processModuleSymbols()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// cvSignature: // cvSignature:
// >64K = C6 // >64K = C6
@ -114,15 +112,15 @@ public class SymbolRecords {
return; return;
} }
for (AbstractModuleInformation module : debugInfo.moduleInformationList) { for (ModuleInformation module : debugInfo.moduleInformationList) {
monitor.checkCanceled(); pdb.checkCanceled();
int streamNumber = module.getStreamNumberDebugInformation(); int streamNumber = module.getStreamNumberDebugInformation();
if (streamNumber == 0xffff) { if (streamNumber == 0xffff) {
moduleSymbolsByOffset.add(new TreeMap<>()); moduleSymbolsByOffset.add(new TreeMap<>());
continue; continue;
} }
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
int sizeSymbolsSection = module.getSizeLocalSymbolsDebugInformation(); int sizeSymbolsSection = module.getSizeLocalSymbolsDebugInformation();
PdbByteReader symbolsReader = reader.getSubPdbByteReader(sizeSymbolsSection); PdbByteReader symbolsReader = reader.getSubPdbByteReader(sizeSymbolsSection);
@ -152,7 +150,7 @@ public class SymbolRecords {
} }
Map<Long, AbstractMsSymbol> oneModuleSymbolsByOffset = Map<Long, AbstractMsSymbol> oneModuleSymbolsByOffset =
deserializeSymbolRecords(pdb, symbolsReader, monitor); deserializeSymbolRecords(pdb, symbolsReader);
moduleSymbolsByOffset.add(oneModuleSymbolsByOffset); moduleSymbolsByOffset.add(oneModuleSymbolsByOffset);
} }
} }
@ -163,18 +161,17 @@ public class SymbolRecords {
* symbols * symbols
* @param pdb {@link AbstractPdb} that owns the Symbols to be parsed * @param pdb {@link AbstractPdb} that owns the Symbols to be parsed
* @param reader {@link PdbByteReader} containing the symbol records to deserialize * @param reader {@link PdbByteReader} containing the symbol records to deserialize
* @param monitor {@link TaskMonitor} used for checking cancellation
* @return map of buffer offsets to {@link AbstractMsSymbol symbols} * @return map of buffer offsets to {@link AbstractMsSymbol symbols}
* @throws PdbException Upon not enough data left to parse * @throws PdbException upon not enough data left to parse
* @throws CancelledException Upon user cancellation * @throws CancelledException upon user cancellation
*/ */
public static Map<Long, AbstractMsSymbol> deserializeSymbolRecords(AbstractPdb pdb, public static Map<Long, AbstractMsSymbol> deserializeSymbolRecords(AbstractPdb pdb,
PdbByteReader reader, TaskMonitor monitor) throws PdbException, CancelledException { PdbByteReader reader) throws PdbException, CancelledException {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
//System.out.println(reader.dump(0x400)); //System.out.println(reader.dump(0x400));
Map<Long, AbstractMsSymbol> mySymbolsByOffset = new TreeMap<>(); Map<Long, AbstractMsSymbol> mySymbolsByOffset = new TreeMap<>();
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
// Including length in byte array for alignment purposes. // Including length in byte array for alignment purposes.
int offset = reader.getIndex(); int offset = reader.getIndex();
@ -185,14 +182,16 @@ public class SymbolRecords {
} }
/** /**
* Debug method for dumping information from this Symbol Records instance. * Debug method for dumping information from this Symbol Records instance
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer} * @throws IOException upon issue writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
protected void dump(Writer writer) throws IOException { protected void dump(Writer writer) throws IOException, CancelledException {
writer.write("SymbolRecords-----------------------------------------------\n"); writer.write("SymbolRecords-----------------------------------------------\n");
dumpSymbolMap(symbolsByOffset, writer); dumpSymbolMap(symbolsByOffset, writer);
for (int i = 0; i < moduleSymbolsByOffset.size(); i++) { for (int i = 0; i < moduleSymbolsByOffset.size(); i++) {
pdb.checkCanceled();
Map<Long, AbstractMsSymbol> map = moduleSymbolsByOffset.get(i); Map<Long, AbstractMsSymbol> map = moduleSymbolsByOffset.get(i);
if (map != null) { if (map != null) {
writer.write("Module(" + i + ") List:\n"); writer.write("Module(" + i + ") List:\n");
@ -204,14 +203,16 @@ public class SymbolRecords {
/** /**
* Debug method for dumping the symbols from a symbol map * Debug method for dumping the symbols from a symbol map
* @param mySymbolsByOffset the {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; to dump. * @param mySymbolsByOffset the {@link Map}&lt;{@link Long},{@link AbstractMsSymbol}&gt; to dump
* @param writer {@link Writer} to which to dump the information. * @param writer {@link Writer} to which to dump the information
* @throws IOException Upon IOException writing to the {@link Writer} * @throws IOException upon issue writing to the {@link Writer}
* @throws CancelledException upon user cancellation
*/ */
protected void dumpSymbolMap(Map<Long, AbstractMsSymbol> mySymbolsByOffset, Writer writer) protected void dumpSymbolMap(Map<Long, AbstractMsSymbol> mySymbolsByOffset, Writer writer)
throws IOException { throws IOException, CancelledException {
writer.write("SymbolMap---------------------------------------------------"); writer.write("SymbolMap---------------------------------------------------");
for (Map.Entry<Long, AbstractMsSymbol> entry : mySymbolsByOffset.entrySet()) { for (Map.Entry<Long, AbstractMsSymbol> entry : mySymbolsByOffset.entrySet()) {
pdb.checkCanceled();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("\n------------------------------------------------------------\n"); builder.append("\n------------------------------------------------------------\n");
builder.append(String.format("Offset: 0X%08X\n", entry.getKey())); builder.append(String.format("Offset: 0X%08X\n", entry.getKey()));

View file

@ -31,7 +31,7 @@ import ghidra.util.task.TaskMonitor;
* We have intended to implement according to the Microsoft PDB API (source); see the API for * We have intended to implement according to the Microsoft PDB API (source); see the API for
* truth. * truth.
*/ */
public abstract class AbstractTypeProgramInterface implements TPI { public abstract class TypeProgramInterface implements TPI {
public static final int STREAM_NUMBER_SIZE = 2; public static final int STREAM_NUMBER_SIZE = 2;
@ -63,13 +63,12 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param recordCategory the RecordCategory of these records. * @param recordCategory the RecordCategory of these records
* @param streamNumber The stream number that contains the * @param streamNumber the stream number that contains the {@link TypeProgramInterface} data
* {@link AbstractTypeProgramInterface} data.
*/ */
public AbstractTypeProgramInterface(AbstractPdb pdb, RecordCategory recordCategory, public TypeProgramInterface(AbstractPdb pdb, RecordCategory recordCategory,
int streamNumber) { int streamNumber) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdb = pdb; this.pdb = pdb;
@ -79,28 +78,28 @@ public abstract class AbstractTypeProgramInterface implements TPI {
} }
/** /**
* Returns the number of bytes needed to store a {@link AbstractTypeProgramInterface} * Returns the number of bytes needed to store a {@link TypeProgramInterface}
* version number. * version number
* @return The number of bytes read from the bytes array. * @return the number of bytes read from the bytes array
*/ */
static int getVersionNumberSize() { static int getVersionNumberSize() {
return VERSION_NUMBER_SIZE; return VERSION_NUMBER_SIZE;
} }
/** /**
* Deserializes Version Number of the {@link AbstractTypeProgramInterface} from the * Deserializes Version Number of the {@link TypeProgramInterface} from the
* {@link PdbByteReader}. * {@link PdbByteReader}
* @param reader {@link PdbByteReader} from which to deserialize. * @param reader {@link PdbByteReader} from which to deserialize
* @return Version number. * @return version number
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
static int deserializeVersionNumber(PdbByteReader reader) throws PdbException { static int deserializeVersionNumber(PdbByteReader reader) throws PdbException {
return reader.parseInt(); return reader.parseInt();
} }
/** /**
* Returns the TypeIndexMin. * Returns the TypeIndexMin
* @return The TypeIndexMin value from the header. * @return the TypeIndexMin value from the header
*/ */
@Override @Override
public int getTypeIndexMin() { public int getTypeIndexMin() {
@ -108,8 +107,8 @@ public abstract class AbstractTypeProgramInterface implements TPI {
} }
/** /**
* Returns the TypeIndexMaxExclusive. * Returns the TypeIndexMaxExclusive
* @return TypeIndexMaxExclusive value from the header. * @return TypeIndexMaxExclusive value from the header
*/ */
@Override @Override
public int getTypeIndexMaxExclusive() { public int getTypeIndexMaxExclusive() {
@ -118,9 +117,9 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* Retrieves the {@link AbstractMsType} record indicated by the recordNumber. The record must * Retrieves the {@link AbstractMsType} record indicated by the recordNumber. The record must
* already have been parsed and inserted into the list. * already have been parsed and inserted into the list
* @param recordNumber Record number to look up. * @param recordNumber Rrcord number to look up
* @return {@link AbstractMsType} pertaining to the record number. * @return {@link AbstractMsType} pertaining to the record number
*/ */
@Override @Override
public AbstractMsType getRecord(int recordNumber) { public AbstractMsType getRecord(int recordNumber) {
@ -147,20 +146,19 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Deserializes this {@link AbstractTypeProgramInterface}. * Deserializes this {@link TypeProgramInterface}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return version number of the {@link TypeProgramInterface}
* @return Version number of the {@link AbstractTypeProgramInterface}. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
int deserialize(TaskMonitor monitor) throws IOException, PdbException, CancelledException { int deserialize() throws IOException, PdbException, CancelledException {
if (pdb.getMsf() == null) { if (pdb.getMsf() == null) {
// Should only be null dummy PDBs used for testing. // Should only be null dummy PDBs used for testing.
throw new PdbException("Unexpected null MSF."); throw new PdbException("Unexpected null MSF.");
} }
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
deserializeHeader(reader); deserializeHeader(reader);
@ -169,15 +167,15 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// we have this commented out. // we have this commented out.
//hash.deserializeHashStreams(monitor); //hash.deserializeHashStreams(monitor);
deserializeTypeRecords(reader, monitor); deserializeTypeRecords(reader);
return versionNumber; return versionNumber;
} }
/** /**
* Dumps this class. This package-protected method is for debugging only. * Dumps this class. This package-protected method is for debugging only
* @param writer {@link Writer} to which to write the debug dump. * @param writer {@link Writer} to which to write the debug dump
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
*/ */
void dump(Writer writer) throws IOException { void dump(Writer writer) throws IOException {
writer.write("TypeProgramInterfaceHeader----------------------------------\n"); writer.write("TypeProgramInterfaceHeader----------------------------------\n");
@ -190,14 +188,16 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a basic object. * IMPORTANT: This method is for testing only. It allows us to set a basic object.
* <p>
* Note: not all values are initialized. This is a dummy constructor used to create a dummy * Note: not all values are initialized. This is a dummy constructor used to create a dummy
* {@link AbstractTypeProgramInterface}. * {@link TypeProgramInterface}.
* <p>
* Note: not all values of this class get initialized by this method. * Note: not all values of this class get initialized by this method.
* @param pdb {@link AbstractPdb} that owns this this class. * @param pdb {@link AbstractPdb} that owns this this class
* @param typeIndexMin The IndexMin to set/use. * @param typeIndexMin the IndexMin to set/use
* @param typeIndexMaxExclusive One greater than the MaxIndex to set/use. * @param typeIndexMaxExclusive one greater than the MaxIndex to set/use
*/ */
AbstractTypeProgramInterface(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) { TypeProgramInterface(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) {
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdb = pdb; this.pdb = pdb;
this.typeIndexMin = typeIndexMin; this.typeIndexMin = typeIndexMin;
@ -206,10 +206,10 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a record for a particular * IMPORTANT: This method is for testing only. It allows us to set a record for a particular
* record number. * record number
* @param recordNumber Record number for the {@link AbstractMsType} to be inserted. * @param recordNumber record number for the {@link AbstractMsType} to be inserted
* @param type {@link AbstractMsType} to be inserted. * @param type {@link AbstractMsType} to be inserted
* @return True if successful. * @return {@code true} if successful
*/ */
boolean setRecord(int recordNumber, AbstractMsType type) { boolean setRecord(int recordNumber, AbstractMsType type) {
if (recordNumber < typeIndexMin) { if (recordNumber < typeIndexMin) {
@ -224,9 +224,9 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* IMPORTANT: This method is for testing only. It allows us to add a record that gets its * IMPORTANT: This method is for testing only. It allows us to add a record that gets its
* record number automatically assigned. * record number automatically assigned
* @param type {@link AbstractMsType} to be inserted. * @param type {@link AbstractMsType} to be inserted
* @return Record number assigned. * @return record number assigned
*/ */
int addRecord(AbstractMsType type) { int addRecord(AbstractMsType type) {
int newRecordNum = typeList.size() + typeIndexMin; int newRecordNum = typeList.size() + typeIndexMin;
@ -238,16 +238,16 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Header of this class. * Deserializes the Header of this class
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected abstract void deserializeHeader(PdbByteReader reader) throws PdbException; protected abstract void deserializeHeader(PdbByteReader reader) throws PdbException;
/** /**
* Dumps the Header. This method is for debugging only. * Dumps the Header. This method is for debugging only
* @param writer {@link Writer} to which to dump the header. * @param writer {@link Writer} to which to dump the header
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
*/ */
protected abstract void dumpHeader(Writer writer) throws IOException; protected abstract void dumpHeader(Writer writer) throws IOException;
@ -255,19 +255,18 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Deserializes the Type Records of this class. * Deserializes the Type Records of this class
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void deserializeTypeRecords(PdbByteReader reader, TaskMonitor monitor) protected void deserializeTypeRecords(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
int recordLength; int recordLength;
int recordNumber = typeIndexMin; int recordNumber = typeIndexMin;
while (reader.hasMore()) { while (reader.hasMore()) {
monitor.checkCanceled(); pdb.checkCanceled();
recordLength = reader.parseUnsignedShortVal(); recordLength = reader.parseUnsignedShortVal();
PdbByteReader recordReader = reader.getSubPdbByteReader(recordLength); PdbByteReader recordReader = reader.getSubPdbByteReader(recordLength);
@ -292,9 +291,9 @@ public abstract class AbstractTypeProgramInterface implements TPI {
//TODO: more to do for outputting individual records (might want a toString or dump method //TODO: more to do for outputting individual records (might want a toString or dump method
// on each). // on each).
/** /**
* Dumps the Type Records. This method is for debugging only. * Dumps the Type Records. This method is for debugging only
* @param writer {@link Writer} to which to dump the records. * @param writer {@link Writer} to which to dump the records
* @throws IOException On issue writing to the {@link Writer}. * @throws IOException on issue writing to the {@link Writer}
*/ */
protected void dumpTypeRecords(Writer writer) throws IOException { protected void dumpTypeRecords(Writer writer) throws IOException {
int recordNum = typeIndexMin; int recordNum = typeIndexMin;
@ -338,9 +337,9 @@ public abstract class AbstractTypeProgramInterface implements TPI {
private List<TiOff> tiOffs = new ArrayList<>(); private List<TiOff> tiOffs = new ArrayList<>();
/** /**
* Deserializes the {@link TypeProgramInterfaceHash}. * Deserializes the {@link TypeProgramInterfaceHash}
* @param reader {@link PdbByteReader} from which to deserialize the data. * @param reader {@link PdbByteReader} from which to deserialize the data
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected void deserializeHeader800(PdbByteReader reader) throws PdbException { protected void deserializeHeader800(PdbByteReader reader) throws PdbException {
hashStreamNumber = reader.parseUnsignedShortVal(); hashStreamNumber = reader.parseUnsignedShortVal();
@ -356,11 +355,11 @@ public abstract class AbstractTypeProgramInterface implements TPI {
} }
/** /**
* Deserializes the {@link TypeProgramInterfaceHash}. * Deserializes the {@link TypeProgramInterfaceHash}
* @param hashStreamNumberParam Stream number of the hash. * @param hashStreamNumberParam stream number of the hash
* @param typeIndexMinParam The IndexMin to set/use. * @param typeIndexMinParam the IndexMin to set/use
* @param typeIndexMaxExclusiveParam One greater than the MaxIndex to set/use. * @param typeIndexMaxExclusiveParam one greater than the MaxIndex to set/use
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected void initHeader200500(int hashStreamNumberParam, int typeIndexMinParam, protected void initHeader200500(int hashStreamNumberParam, int typeIndexMinParam,
int typeIndexMaxExclusiveParam) throws PdbException { int typeIndexMaxExclusiveParam) throws PdbException {
@ -380,11 +379,11 @@ public abstract class AbstractTypeProgramInterface implements TPI {
// Suppress "unused" for hashBuffer, typeInfoOffsetPairsBuffer, hashAdjustmentBuffer // Suppress "unused" for hashBuffer, typeInfoOffsetPairsBuffer, hashAdjustmentBuffer
/** /**
* *UNDER CONSTRUCTION* Deserializes the Hash Streams... * *UNDER CONSTRUCTION* Deserializes the Hash Streams...
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param monitor {@link TaskMonitor} used for checking cancellation
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
* @throws PdbException Upon error in processing components. * @throws PdbException upon error in processing components
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
@SuppressWarnings("unused") // for method unused. @SuppressWarnings("unused") // for method unused.
protected void deserializeHashStreams(TaskMonitor monitor) protected void deserializeHashStreams(TaskMonitor monitor)
@ -400,7 +399,7 @@ public abstract class AbstractTypeProgramInterface implements TPI {
if (hashStreamNumber == 0xffff) { if (hashStreamNumber == 0xffff) {
return; return;
} }
PdbByteReader reader = pdb.getReaderForStreamNumber(hashStreamNumber, monitor); PdbByteReader reader = pdb.getReaderForStreamNumber(hashStreamNumber);
//System.out.println(reader.dump()); //System.out.println(reader.dump());
reader.setIndex(offsetHashVals); reader.setIndex(offsetHashVals);
@ -420,7 +419,7 @@ public abstract class AbstractTypeProgramInterface implements TPI {
return; return;
} }
PdbByteReader readerAuxiliary = PdbByteReader readerAuxiliary =
pdb.getReaderForStreamNumber(hashStreamNumberAuxiliary, monitor); pdb.getReaderForStreamNumber(hashStreamNumberAuxiliary);
//readerAuxiliary.dump(); //readerAuxiliary.dump();
} }
@ -501,8 +500,8 @@ public abstract class AbstractTypeProgramInterface implements TPI {
} }
/** /**
* Dumps the this {@link TypeProgramInterfaceHash}. This method is for debugging only. * Dumps the this {@link TypeProgramInterfaceHash}. This method is for debugging only
* @return {@link String} of pretty output. * @return {@link String} of pretty output
*/ */
protected String dump() { protected String dump() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -544,8 +543,8 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* This method is only intended to be used to create a dummy key for performing * This method is only intended to be used to create a dummy key for performing
* a binary search. That is the reason that an {@code offset} parameter is not * a binary search. That is the reason that an {@code offset} parameter is not
* specified. The offset is set to zero. * specified. The offset is set to zero
* @param typeIndex The type index to fill into the key. * @param typeIndex the type index to fill into the key
*/ */
protected TiOff(int typeIndex) { protected TiOff(int typeIndex) {
this.typeIndex = typeIndex; this.typeIndex = typeIndex;
@ -574,8 +573,8 @@ public abstract class AbstractTypeProgramInterface implements TPI {
/** /**
* This method is only intended to be used to create a dummy key for performing * This method is only intended to be used to create a dummy key for performing
* a binary search. That is the reason that an {@code offset} parameter is not * a binary search. That is the reason that an {@code offset} parameter is not
* specified. The offset is set to zero. * specified. The offset is set to zero
* @param typeIndex The type index to fill into the key. * @param typeIndex the type index to fill into the key
*/ */
protected KeyTiOff(int typeIndex) { protected KeyTiOff(int typeIndex) {
super(typeIndex); super(typeIndex);

View file

@ -19,9 +19,9 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
/** /**
* This class is the version of {@link AbstractTypeProgramInterface} for Microsoft v2.00 PDB. * This class is the version of {@link TypeProgramInterface} for Microsoft v2.00 PDB.
*/ */
public class TypeProgramInterface200 extends AbstractTypeProgramInterface { public class TypeProgramInterface200 extends TypeProgramInterface {
//============================================================================================== //==============================================================================================
// Internals // Internals
@ -32,10 +32,10 @@ public class TypeProgramInterface200 extends AbstractTypeProgramInterface {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param recordCategory the RecordCategory of these records. * @param recordCategory the RecordCategory of these records
* @param streamNumber The stream number that contains the {@link AbstractTypeProgramInterface}. * @param streamNumber the stream number that contains the {@link TypeProgramInterface}
*/ */
public TypeProgramInterface200(AbstractPdb pdb, RecordCategory recordCategory, public TypeProgramInterface200(AbstractPdb pdb, RecordCategory recordCategory,
int streamNumber) { int streamNumber) {
@ -79,12 +79,14 @@ public class TypeProgramInterface200 extends AbstractTypeProgramInterface {
//============================================================================================== //==============================================================================================
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a basic object. * IMPORTANT: This method is for testing only. It allows us to set a basic object.
* <p>
* Note: not all values are initialized. This is a dummy constructor used to create a dummy * Note: not all values are initialized. This is a dummy constructor used to create a dummy
* {@link AbstractTypeProgramInterface}. * {@link TypeProgramInterface}.
* <p>
* Note: not all values are initialized. * Note: not all values are initialized.
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param typeIndexMin The IndexMin to set/use. * @param typeIndexMin the IndexMin to set/use
* @param typeIndexMaxExclusive One greater than the MaxIndex to set/use. * @param typeIndexMaxExclusive one greater than the MaxIndex to set/use
*/ */
TypeProgramInterface200(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) { TypeProgramInterface200(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) {
super(pdb, typeIndexMin, typeIndexMaxExclusive); super(pdb, typeIndexMin, typeIndexMaxExclusive);

View file

@ -19,9 +19,9 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
/** /**
* This class is the version of {@link AbstractTypeProgramInterface} for Microsoft v5.00 PDB. * This class is the version of {@link TypeProgramInterface} for Microsoft v5.00 PDB.
*/ */
public class TypeProgramInterface500 extends AbstractTypeProgramInterface { public class TypeProgramInterface500 extends TypeProgramInterface {
//============================================================================================== //==============================================================================================
// Internals // Internals
@ -32,10 +32,10 @@ public class TypeProgramInterface500 extends AbstractTypeProgramInterface {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param recordCategory the RecordCategory of these records. * @param recordCategory the RecordCategory of these records
* @param streamNumber The stream number that contains the {@link AbstractTypeProgramInterface}. * @param streamNumber the stream number that contains the {@link TypeProgramInterface}
*/ */
public TypeProgramInterface500(AbstractPdb pdb, RecordCategory recordCategory, public TypeProgramInterface500(AbstractPdb pdb, RecordCategory recordCategory,
int streamNumber) { int streamNumber) {
@ -77,12 +77,14 @@ public class TypeProgramInterface500 extends AbstractTypeProgramInterface {
//============================================================================================== //==============================================================================================
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a basic object. * IMPORTANT: This method is for testing only. It allows us to set a basic object.
* <p>
* Note: not all values are initialized. This is a dummy constructor used to create a dummy * Note: not all values are initialized. This is a dummy constructor used to create a dummy
* {@link AbstractTypeProgramInterface}. * {@link TypeProgramInterface}.
* <p>
* Note: not all values are initialized. * Note: not all values are initialized.
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param typeIndexMin The IndexMin to set/use. * @param typeIndexMin the IndexMin to set/use
* @param typeIndexMaxExclusive One greater than the MaxIndex to set/use. * @param typeIndexMaxExclusive one greater than the MaxIndex to set/use
*/ */
TypeProgramInterface500(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) { TypeProgramInterface500(AbstractPdb pdb, int typeIndexMin, int typeIndexMaxExclusive) {
super(pdb, typeIndexMin, typeIndexMaxExclusive); super(pdb, typeIndexMin, typeIndexMaxExclusive);

View file

@ -19,18 +19,18 @@ import java.io.IOException;
import java.io.Writer; import java.io.Writer;
/** /**
* This class is the version of {@link AbstractTypeProgramInterface} for Microsoft v8.00 PDB. * This class is the version of {@link TypeProgramInterface} for Microsoft v8.00 PDB.
*/ */
public class TypeProgramInterface800 extends AbstractTypeProgramInterface { public class TypeProgramInterface800 extends TypeProgramInterface {
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param recordCategory the RecordCategory of these records. * @param recordCategory the RecordCategory of these records
* @param streamNumber The stream number that contains the {@link AbstractTypeProgramInterface}. * @param streamNumber the stream number that contains the {@link TypeProgramInterface}
*/ */
public TypeProgramInterface800(AbstractPdb pdb, RecordCategory recordCategory, public TypeProgramInterface800(AbstractPdb pdb, RecordCategory recordCategory,
int streamNumber) { int streamNumber) {

View file

@ -18,12 +18,11 @@ package ghidra.app.util.bin.format.pdb2.pdbreader;
import java.io.IOException; import java.io.IOException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* Parser for detecting the appropriate {@link AbstractTypeProgramInterface} format for the * Parser for detecting the appropriate {@link TypeProgramInterface} format for the
* filename given. It then creates and returns the appropriate * filename given. It then creates and returns the appropriate
* {@link AbstractTypeProgramInterface} object. * {@link TypeProgramInterface} object.
*/ */
public class TypeProgramInterfaceParser { public class TypeProgramInterfaceParser {
@ -44,30 +43,29 @@ public class TypeProgramInterfaceParser {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Parses information to determine the version of {@link AbstractTypeProgramInterface} to * Parses information to determine the version of {@link TypeProgramInterface} to
* create. * create
* @param pdb {@link AbstractPdb} that owns this {@link AbstractTypeProgramInterface}. * @param pdb {@link AbstractPdb} that owns this {@link TypeProgramInterface}
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return the appropriate {@link TypeProgramInterface} or null if the stream does
* @return the appropriate {@link AbstractTypeProgramInterface} or null if the stream does * not have enough information to be parsed
* not have enough information to be parsed. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error in processing components
* @throws PdbException Upon error in processing components. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public AbstractTypeProgramInterface parse(AbstractPdb pdb, TaskMonitor monitor) public TypeProgramInterface parse(AbstractPdb pdb)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
AbstractTypeProgramInterface typeProgramInterface; TypeProgramInterface typeProgramInterface;
int versionNumberSize = AbstractTypeProgramInterface.getVersionNumberSize(); int versionNumberSize = TypeProgramInterface.getVersionNumberSize();
int streamNumber = getStreamNumber(); int streamNumber = getStreamNumber();
PdbByteReader reader = PdbByteReader reader =
pdb.getReaderForStreamNumber(streamNumber, 0, versionNumberSize, monitor); pdb.getReaderForStreamNumber(streamNumber, 0, versionNumberSize);
if (reader.getLimit() < versionNumberSize) { if (reader.getLimit() < versionNumberSize) {
return null; return null;
} }
int versionNumber = AbstractTypeProgramInterface.deserializeVersionNumber(reader); int versionNumber = TypeProgramInterface.deserializeVersionNumber(reader);
// TODO: we do not know where the line should be drawn for each of these // TODO: we do not know where the line should be drawn for each of these
// AbstractTypeProgramInterface instantiations. Had a TI50_ID that was not an 800 // AbstractTypeProgramInterface instantiations. Had a TI50_ID that was not an 800
@ -102,8 +100,8 @@ public class TypeProgramInterfaceParser {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Returns the standard stream number that contains the serialized Type Program Interface. * Returns the standard stream number that contains the serialized Type Program Interface
* @return The standard stream number that contains the Type Program Interface. * @return the standard stream number that contains the Type Program Interface
*/ */
protected int getStreamNumber() { protected int getStreamNumber() {
return TYPE_PROGRAM_INTERFACE_STREAM_NUMBER; return TYPE_PROGRAM_INTERFACE_STREAM_NUMBER;
@ -111,8 +109,8 @@ public class TypeProgramInterfaceParser {
/** /**
* Returns the appropriate {@link RecordCategory} needed while processing * Returns the appropriate {@link RecordCategory} needed while processing
* the Type Program Interface} (vs. Item Program Interface). * the Type Program Interface} (vs. Item Program Interface)
* @return {@link RecordCategory#TYPE}. * @return {@link RecordCategory#TYPE}
*/ */
protected RecordCategory getCategory() { protected RecordCategory getCategory() {
return RecordCategory.TYPE; return RecordCategory.TYPE;

View file

@ -17,6 +17,7 @@ package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.Objects;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
@ -98,11 +99,11 @@ import ghidra.util.task.TaskMonitor;
* <P> * <P>
* @see MsfFileReader * @see MsfFileReader
* @see MsfStream * @see MsfStream
* @see AbstractMsfDirectoryStream * @see MsfDirectoryStream
* @see AbstractMsfFreePageMap * @see MsfFreePageMap
* @see AbstractMsfStreamTable * @see MsfStreamTable
*/ */
public abstract class AbstractMsf implements AutoCloseable { public abstract class Msf implements AutoCloseable {
private static final int HEADER_PAGE_NUMBER = 0; private static final int HEADER_PAGE_NUMBER = 0;
private static final int DIRECTORY_STREAM_NUMBER = 0; private static final int DIRECTORY_STREAM_NUMBER = 0;
@ -113,9 +114,9 @@ public abstract class AbstractMsf implements AutoCloseable {
protected String filename; protected String filename;
protected MsfFileReader fileReader; protected MsfFileReader fileReader;
protected AbstractMsfFreePageMap freePageMap; protected MsfFreePageMap freePageMap;
protected AbstractMsfDirectoryStream directoryStream; protected MsfDirectoryStream directoryStream;
protected AbstractMsfStreamTable streamTable; protected MsfStreamTable streamTable;
protected int pageSize; protected int pageSize;
protected int log2PageSize; protected int log2PageSize;
@ -125,23 +126,30 @@ public abstract class AbstractMsf implements AutoCloseable {
protected int currentFreePageMapFirstPageNumber; protected int currentFreePageMapFirstPageNumber;
protected int numPages = 1; // Set to 1 to allow initial read protected int numPages = 1; // Set to 1 to allow initial read
protected TaskMonitor monitor;
protected PdbReaderOptions pdbOptions; protected PdbReaderOptions pdbOptions;
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor for this class. * Constructor
* @param file The {@link RandomAccessFile} to process for this class. * @param file the {@link RandomAccessFile} to process for this class
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param filename name of {@code #file}
* @throws IOException Upon file IO seek/read issues. * @param monitor the TaskMonitor
* @throws PdbException Upon unknown value for configuration. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException upon file IO seek/read issues
* @throws PdbException upon unknown value for configuration
*/ */
public AbstractMsf(RandomAccessFile file, PdbReaderOptions pdbOptions) public Msf(RandomAccessFile file, String filename, TaskMonitor monitor,
PdbReaderOptions pdbOptions)
throws IOException, PdbException { throws IOException, PdbException {
Objects.requireNonNull(file, "file may not be null");
this.filename = Objects.requireNonNull(filename, "filename may not be null");
this.monitor = TaskMonitor.dummyIfNull(monitor);
this.pdbOptions = Objects.requireNonNull(pdbOptions, "PdbOptions may not be null");
// Do initial configuration with largest possible page size. ConfigureParameters will // Do initial configuration with largest possible page size. ConfigureParameters will
// be called again later with the proper pageSize set. // be called again later with the proper pageSize set.
this.pdbOptions = pdbOptions;
pageSize = 0x1000; pageSize = 0x1000;
configureParameters(); configureParameters();
// Create components. // Create components.
@ -150,34 +158,58 @@ public abstract class AbstractMsf implements AutoCloseable {
} }
/** /**
* Returns the page size employed by this {@link AbstractMsf}. * Returns the filename
* @return Page size. * @return the filename
*/
public String getFilename() {
return filename;
}
/**
* Returns the TaskMonitor
* @return the monitor
*/
public TaskMonitor getMonitor() {
return monitor;
}
/**
* Check to see if this monitor has been canceled
* @throws CancelledException if monitor has been cancelled
*/
public void checkCanceled() throws CancelledException {
monitor.checkCanceled();
}
/**
* Returns the page size employed by this {@link Msf}
* @return page size
*/ */
public int getPageSize() { public int getPageSize() {
return pageSize; return pageSize;
} }
/** /**
* Returns the number of streams found in this {@link AbstractMsf}. * Returns the number of streams found in this {@link Msf}
* @return Number of streams. * @return number of streams
*/ */
public int getNumStreams() { public int getNumStreams() {
return streamTable.getNumStreams(); return streamTable.getNumStreams();
} }
/** /**
* Returns the {@link MsfStream} specified by {@link AbstractMsf}. * Returns the {@link MsfStream} specified by {@link Msf}
* @param streamNumber The number of the Stream to return. Must be less than the number * @param streamNumber the number of the Stream to return. Must be less than the number
* of streams returned by {@link #getNumStreams()}. * of streams returned by {@link #getNumStreams()}
* @return {@link MsfStream} or {@code null} if no stream for the streamNumber. * @return {@link MsfStream} or {@code null} if no stream for the streamNumber
*/ */
public MsfStream getStream(int streamNumber) { public MsfStream getStream(int streamNumber) {
return streamTable.getStream(streamNumber); return streamTable.getStream(streamNumber);
} }
/** /**
* Closes resources used by this {@link AbstractMsf}. * Closes resources used by this {@link Msf}
* @throws IOException Under circumstances found when closing a {@link RandomAccessFile}. * @throws IOException under circumstances found when closing a {@link RandomAccessFile}
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
@ -191,10 +223,10 @@ public abstract class AbstractMsf implements AutoCloseable {
//============================================================================================== //==============================================================================================
/** /**
* Returns the value of the floor (greatest integer less than or equal to) of the result * Returns the value of the floor (greatest integer less than or equal to) of the result
* upon dividing the dividend by a divisor which is the power-of-two of the log2Divisor. * upon dividing the dividend by a divisor which is the power-of-two of the log2Divisor
* @param dividend The dividend to the operator * @param dividend the dividend to the operator
* @param log2Divisor The log2 of the intended divisor value. * @param log2Divisor the log2 of the intended divisor value
* @return The floor of the division result. * @return the floor of the division result
*/ */
static final int floorDivisionWithLog2Divisor(int dividend, int log2Divisor) { static final int floorDivisionWithLog2Divisor(int dividend, int log2Divisor) {
return (dividend + (1 << log2Divisor) - 1) >> log2Divisor; return (dividend + (1 << log2Divisor) - 1) >> log2Divisor;
@ -204,46 +236,45 @@ public abstract class AbstractMsf implements AutoCloseable {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Method that returns the identification byte[] required by this format. * Method that returns the identification byte[] required by this format
* @return The minimum required number. * @return the minimum required number
*/ */
protected abstract byte[] getIdentification(); protected abstract byte[] getIdentification();
/** /**
* Returns the offset (in bytes) of the PageSize within the header. * Returns the offset (in bytes) of the PageSize within the header
* @return The offset of the PageSize within the header. * @return the offset of the PageSize within the header
*/ */
protected abstract int getPageSizeOffset(); protected abstract int getPageSizeOffset();
/** /**
* Deserializes the Free Page Map page number from the {@link PdbByteReader}. * Deserializes the Free Page Map page number from the {@link PdbByteReader}
* @param reader {@link PdbByteReader} from which to read. * @param reader {@link PdbByteReader} from which to read
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected abstract void parseFreePageMapPageNumber(PdbByteReader reader) throws PdbException; protected abstract void parseFreePageMapPageNumber(PdbByteReader reader) throws PdbException;
/** /**
* Deserializes the value of the number of pages in the MSF. * Deserializes the value of the number of pages in the MSF
* @param reader {@link PdbByteReader} from which to read. * @param reader {@link PdbByteReader} from which to read
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected abstract void parseCurrentNumPages(PdbByteReader reader) throws PdbException; protected abstract void parseCurrentNumPages(PdbByteReader reader) throws PdbException;
/** /**
* Method to create the following components: StreamTable, FreePageMap, and DirectoryStream. * Method to create the following components: StreamTable, FreePageMap, and DirectoryStream.
* FreePageMap.
*/ */
abstract void create(); abstract void create();
/** /**
* Method to set parameters for the file based on version and page size. * Method to set parameters for the file based on version and page size
* @throws PdbException Upon unknown value for configuration. * @throws PdbException upon unknown value for configuration
*/ */
abstract void configureParameters() throws PdbException; abstract void configureParameters() throws PdbException;
/** /**
* Method to get the size of the page number (in bytes) when serialized to disc. * Method to get the size of the page number (in bytes) when serialized to disc
* @return The page size (in bytes). * @return the page size (in bytes)
*/ */
abstract protected int getPageNumberSize(); abstract protected int getPageNumberSize();
@ -251,8 +282,8 @@ public abstract class AbstractMsf implements AutoCloseable {
// Class Internals // Class Internals
//============================================================================================== //==============================================================================================
/** /**
* Returns Log2 value of the page size employed by this MSF. * Returns Log2 value of the page size employed by this MSF
* @return The Log2 value of the page size employed by this MSF. * @return the Log2 value of the page size employed by this MSF
*/ */
protected int getLog2PageSize() { protected int getLog2PageSize() {
return log2PageSize; return log2PageSize;
@ -260,33 +291,33 @@ public abstract class AbstractMsf implements AutoCloseable {
/** /**
* Returns the the mask used for masking off the upper bits of a value use to get the * Returns the the mask used for masking off the upper bits of a value use to get the
* mod-page-size of the value (pageSizes must be power of two for this to work). * mod-page-size of the value (pageSizes must be power of two for this to work)
* @return The mask. * @return the mask
*/ */
protected int getPageSizeModMask() { protected int getPageSizeModMask() {
return pageSizeModMask; return pageSizeModMask;
} }
/** /**
* Returns the number of pages found in sequence that compose the {@link AbstractMsfFreePageMap} * Returns the number of pages found in sequence that compose the {@link MsfFreePageMap}
* (for this {@link AbstractMsf}) when on disk. * (for this {@link Msf}) when on disk
* @return The number of sequential pages in the {@link AbstractMsfFreePageMap}. * @return the number of sequential pages in the {@link MsfFreePageMap}
*/ */
protected int getNumSequentialFreePageMapPages() { protected int getNumSequentialFreePageMapPages() {
return freePageMapNumSequentialPage; return freePageMapNumSequentialPage;
} }
/** /**
* Returns the page number containing the header of this MSF file. * Returns the page number containing the header of this MSF file
* @return The header page number. * @return the header page number
*/ */
protected int getHeaderPageNumber() { protected int getHeaderPageNumber() {
return HEADER_PAGE_NUMBER; return HEADER_PAGE_NUMBER;
} }
/** /**
* Returns the stream number containing the directory of this MSF file. * Returns the stream number containing the directory of this MSF file
* @return The directory stream number. * @return the directory stream number
*/ */
protected int getDirectoryStreamNumber() { protected int getDirectoryStreamNumber() {
return DIRECTORY_STREAM_NUMBER; return DIRECTORY_STREAM_NUMBER;
@ -296,16 +327,16 @@ public abstract class AbstractMsf implements AutoCloseable {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Returns the number of pages contained in this MSF file. * Returns the number of pages contained in this MSF file
* @return The number of pages in this MSF. * @return the number of pages in this MSF
*/ */
protected int getNumPages() { protected int getNumPages() {
return numPages; return numPages;
} }
/** /**
* Returns the first page number of the current Free Page Map. * Returns the first page number of the current Free Page Map
* @return The first page number of the current Free Page Map. * @return the first page number of the current Free Page Map
*/ */
protected int getCurrentFreePageMapFirstPageNumber() { protected int getCurrentFreePageMapFirstPageNumber() {
return currentFreePageMapFirstPageNumber; return currentFreePageMapFirstPageNumber;
@ -314,14 +345,13 @@ public abstract class AbstractMsf implements AutoCloseable {
/** /**
* Performs required initialization of this class, needed before trying to read any * Performs required initialization of this class, needed before trying to read any
* Streams. Initialization includes deserializing the remainder of the header as well * Streams. Initialization includes deserializing the remainder of the header as well
* as stream directory information. * as stream directory information
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon unknown value for configuration
* @throws PdbException Upon unknown value for configuration. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void deserialize(TaskMonitor monitor) protected void deserialize()
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
byte[] bytes = new byte[getPageSize()]; byte[] bytes = new byte[getPageSize()];
fileReader.read(getHeaderPageNumber(), 0, getPageSize(), bytes, 0); fileReader.read(getHeaderPageNumber(), 0, getPageSize(), bytes, 0);
@ -333,13 +363,13 @@ public abstract class AbstractMsf implements AutoCloseable {
parseCurrentNumPages(reader); parseCurrentNumPages(reader);
configureParameters(); configureParameters();
directoryStream.deserializeStreamInfo(reader, monitor); directoryStream.deserializeStreamInfo(reader);
// Do not need FreePageMap for just reading files. // Do not need FreePageMap for just reading files.
freePageMap.deserialize(monitor); freePageMap.deserialize();
// For debug: freePageMap.dump(); // For debug: freePageMap.dump();
streamTable.deserialize(directoryStream, monitor); streamTable.deserialize(directoryStream);
} }
} }

View file

@ -20,11 +20,12 @@ import java.io.RandomAccessFile;
import java.util.Arrays; import java.util.Arrays;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link AbstractMsf} for Microsoft v2.00 MSF. * This class is the version of {@link Msf} for Microsoft v2.00 MSF.
*/ */
public class Msf200 extends AbstractMsf { public class Msf200 extends Msf {
private static final int PAGE_NUMBER_SIZE = 2; private static final int PAGE_NUMBER_SIZE = 2;
private static final byte[] IDENTIFICATION = private static final byte[] IDENTIFICATION =
@ -39,25 +40,28 @@ public class Msf200 extends AbstractMsf {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param file The {@link RandomAccessFile} to process as a {@link Msf200}. * @param file the {@link RandomAccessFile} to process as a {@link Msf200}
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param filename name of {@code #file}
* @throws IOException Upon file IO seek/read issues. * @param monitor the TaskMonitor
* @throws PdbException Upon unknown value for configuration. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException upon file IO seek/read issues
* @throws PdbException upon unknown value for configuration
*/ */
public Msf200(RandomAccessFile file, PdbReaderOptions pdbOptions) public Msf200(RandomAccessFile file, String filename, TaskMonitor monitor,
PdbReaderOptions pdbOptions)
throws IOException, PdbException { throws IOException, PdbException {
super(file, pdbOptions); super(file, filename, monitor, pdbOptions);
} }
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Static method used to detect the header that belongs to this class. * Static method used to detect the header that belongs to this class
* @param file The {@link RandomAccessFile} to process as a {@link Msf200}. * @param file the {@link RandomAccessFile} to process as a {@link Msf200}
* @return True if the header for this class is positively identified. * @return {@code true} if the header for this class is positively identified
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
*/ */
static boolean detected(RandomAccessFile file) throws IOException { static boolean detected(RandomAccessFile file) throws IOException {
byte[] bytes = new byte[IDENTIFICATION.length]; byte[] bytes = new byte[IDENTIFICATION.length];

View file

@ -20,11 +20,12 @@ import java.io.RandomAccessFile;
import java.util.Arrays; import java.util.Arrays;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link AbstractMsf} for Microsoft v7.00 MSF. * This class is the version of {@link Msf} for Microsoft v7.00 MSF.
*/ */
public class Msf700 extends AbstractMsf { public class Msf700 extends Msf {
private static final int PAGE_NUMBER_SIZE = 4; private static final int PAGE_NUMBER_SIZE = 4;
private static final byte[] IDENTIFICATION = "Microsoft C/C++ MSF 7.00\r\n\u001aDS".getBytes(); private static final byte[] IDENTIFICATION = "Microsoft C/C++ MSF 7.00\r\n\u001aDS".getBytes();
@ -38,15 +39,18 @@ public class Msf700 extends AbstractMsf {
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param file The {@link RandomAccessFile} to process as a {@link Msf700}. * @param file the {@link RandomAccessFile} to process as a {@link Msf700}
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param filename name of {@code #file}
* @throws IOException Upon file IO seek/read issues. * @param monitor the TaskMonitor
* @throws PdbException Upon unknown value for configuration. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @throws IOException upon file IO seek/read issues
* @throws PdbException upon unknown value for configuration
*/ */
public Msf700(RandomAccessFile file, PdbReaderOptions pdbOptions) public Msf700(RandomAccessFile file, String filename, TaskMonitor monitor,
PdbReaderOptions pdbOptions)
throws IOException, PdbException { throws IOException, PdbException {
super(file, pdbOptions); super(file, filename, monitor, pdbOptions);
} }
//============================================================================================== //==============================================================================================
@ -98,10 +102,10 @@ public class Msf700 extends AbstractMsf {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Static method used to detect the header that belongs to this class. * Static method used to detect the header that belongs to this class
* @param file The RandomAccessFile to process as a {@link Msf700}. * @param file the RandomAccessFile to process as a {@link Msf700}
* @return True if the header for this class is positively identified. * @return {@code true} if the header for this class is positively identified
* @throws IOException Upon file IO seek/read issues. * @throws IOException upon file IO seek/read issues
*/ */
static boolean detected(RandomAccessFile file) throws IOException { static boolean detected(RandomAccessFile file) throws IOException {
byte[] bytes = new byte[IDENTIFICATION.length]; byte[] bytes = new byte[IDENTIFICATION.length];

View file

@ -20,26 +20,26 @@ package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
* in the older style MSF format, it was the same as a user (@link MsfStream}. Newer versions of * in the older style MSF format, it was the same as a user (@link MsfStream}. Newer versions of
* MSF needed a higher capacity stream * MSF needed a higher capacity stream
* Class extends {@link MsfStream} and represents a more complex Stream used as the Directory Stream * Class extends {@link MsfStream} and represents a more complex Stream used as the Directory Stream
* for the newer {@link AbstractMsf} (and PDB) format. In the older format, a regular * for the newer {@link Msf} (and PDB) format. In the older format, a regular
* Stream is used as the directory Stream. * Stream is used as the directory Stream.
* <P> * <P>
* Note: This extended Stream is not used as a user Stream--just as a higher-capacity directory * Note: This extended Stream is not used as a user Stream--just as a higher-capacity directory
* Stream. * Stream.
* <P> * <P>
* The format of how this {@link AbstractMsfDirectoryStream} is persisted to disk is described in * The format of how this {@link MsfDirectoryStream} is persisted to disk is described in
* the main {@link AbstractMsf} documentation. * the main {@link Msf} documentation.
*/ */
abstract class AbstractMsfDirectoryStream extends MsfStream { abstract class MsfDirectoryStream extends MsfStream {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. Sets the byte length of the Stream to -1. This method is used when the * Constructor. Sets the byte length of the Stream to -1. This method is used when the
* Stream knows/reads its length. * Stream knows/reads its length
* @param msf The {@link AbstractMsf} to which the Stream belongs. * @param msf the {@link Msf} to which the Stream belongs
*/ */
AbstractMsfDirectoryStream(AbstractMsf msf) { MsfDirectoryStream(Msf msf) {
super(msf); super(msf);
} }

View file

@ -16,21 +16,21 @@
package ghidra.app.util.bin.format.pdb2.pdbreader.msf; package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
/** /**
* This is the v200 of {@link AbstractMsfDirectoryStream}. It is essentially no different than * This is the v200 of {@link MsfDirectoryStream}. It is essentially no different than
* an {@link MsfStream}. * an {@link MsfStream}.
* @see AbstractMsfDirectoryStream * @see MsfDirectoryStream
*/ */
class MsfDirectoryStream200 extends AbstractMsfDirectoryStream { class MsfDirectoryStream200 extends MsfDirectoryStream {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. Sets the byte length of the Stream to -1. This method is used when the * Constructor. Sets the byte length of the Stream to -1. This method is used when the
* Stream knows/reads its length. * Stream knows/reads its length
* @param msf The {@link AbstractMsf} to which the Stream belongs. * @param msf the {@link Msf} to which the Stream belongs
*/ */
MsfDirectoryStream200(AbstractMsf msf) { MsfDirectoryStream200(Msf msf) {
super(msf); super(msf);
} }

View file

@ -20,24 +20,23 @@ import java.io.IOException;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This is the v700 of {@link AbstractMsfDirectoryStream}. It is essentially no different than * This is the v700 of {@link MsfDirectoryStream}. It is essentially no different than
* an {@link MsfStream}. * an {@link MsfStream}.
* @see AbstractMsfDirectoryStream * @see MsfDirectoryStream
*/ */
class MsfDirectoryStream700 extends AbstractMsfDirectoryStream { class MsfDirectoryStream700 extends MsfDirectoryStream {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. Sets the byte length of the Stream to -1. This method is used when the * Constructor. Sets the byte length of the Stream to -1. This method is used when the
* Stream knows/reads its length. * Stream knows/reads its length
* @param msf The {@link AbstractMsf} to which the Stream belongs. * @param msf the {@link Msf} to which the Stream belongs
*/ */
MsfDirectoryStream700(AbstractMsf msf) { MsfDirectoryStream700(Msf msf) {
super(msf); super(msf);
} }
@ -45,20 +44,19 @@ class MsfDirectoryStream700 extends AbstractMsfDirectoryStream {
* Deserializes Stream information from the bytes parameter starting at the index offset * Deserializes Stream information from the bytes parameter starting at the index offset
* and uses it to provide necessary information for the Stream to be usable. * and uses it to provide necessary information for the Stream to be usable.
* The information from the deserialization of the byte parameter then points to additional * The information from the deserialization of the byte parameter then points to additional
* {@link AbstractMsf} pages that need to be read as a subStream and deserialized to create * {@link Msf} pages that need to be read as a subStream and deserialized to create
* the {@link MsfDirectoryStream700}. * the {@link MsfDirectoryStream700}.
* <P> * <P>
* Generally, deserialization is part of the step of loading the Stream information from * Generally, deserialization is part of the step of loading the Stream information from
* persistent storage (disk). * persistent storage (disk).
* @param reader {@link PdbByteReader} from which to parse the information. * @param reader {@link PdbByteReader} from which to parse the information
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
@Override @Override
void deserializeStreamInfo(PdbByteReader reader, TaskMonitor monitor) void deserializeStreamInfo(PdbByteReader reader)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// Parse the length of the overall (larger) stream. // Parse the length of the overall (larger) stream.
@ -66,18 +64,18 @@ class MsfDirectoryStream700 extends AbstractMsfDirectoryStream {
// Calculate the length of the subStream which contains all of the page numbers necessary // Calculate the length of the subStream which contains all of the page numbers necessary
// for the overall (larger) stream and create a subStream with this calculated length. // for the overall (larger) stream and create a subStream with this calculated length.
int subStreamLength = int subStreamLength =
AbstractMsf.floorDivisionWithLog2Divisor(streamLength, msf.getLog2PageSize()) * Msf.floorDivisionWithLog2Divisor(streamLength, msf.getLog2PageSize()) *
msf.getPageNumberSize(); msf.getPageNumberSize();
MsfStream subStream = new MsfStream(msf, subStreamLength); MsfStream subStream = new MsfStream(msf, subStreamLength);
// Parse the page numbers of the subStream. // Parse the page numbers of the subStream.
subStream.deserializePageNumbers(reader, monitor); subStream.deserializePageNumbers(reader);
// Now read the whole subStream, creating a new byte array. // Now read the whole subStream, creating a new byte array.
byte[] bytes = subStream.read(0, subStreamLength, monitor); byte[] bytes = subStream.read(0, subStreamLength);
PdbByteReader pageNumberReader = new PdbByteReader(bytes); PdbByteReader pageNumberReader = new PdbByteReader(bytes);
// Next parse the page numbers for the overall (larger) stream from this new byte array // Next parse the page numbers for the overall (larger) stream from this new byte array
// that was read from the subStream. // that was read from the subStream.
deserializePageNumbers(pageNumberReader, monitor); deserializePageNumbers(pageNumberReader);
// The overall (larger) stream has now been set up with the overall stream length // The overall (larger) stream has now been set up with the overall stream length
// and its page numbers parsed. // and its page numbers parsed.
} }

View file

@ -20,7 +20,7 @@ import java.io.RandomAccessFile;
/** /**
* This class is responsible for reading pages from a {@link RandomAccessFile} for the * This class is responsible for reading pages from a {@link RandomAccessFile} for the
* {@link AbstractMsf} class and its underlying classes. * {@link Msf} class and its underlying classes.
*/ */
class MsfFileReader implements AutoCloseable { class MsfFileReader implements AutoCloseable {
@ -28,14 +28,14 @@ class MsfFileReader implements AutoCloseable {
// Internals // Internals
//============================================================================================== //==============================================================================================
private RandomAccessFile file; private RandomAccessFile file;
private AbstractMsf msf; private Msf msf;
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Closes this class, including its underlying file resources. * Closes this class, including its underlying file resources
* @throws IOException Under circumstances found when closing a {@link RandomAccessFile}. * @throws IOException under circumstances found when closing a {@link RandomAccessFile}
*/ */
@Override @Override
public void close() throws IOException { public void close() throws IOException {
@ -48,35 +48,35 @@ class MsfFileReader implements AutoCloseable {
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The {@link AbstractMsf} for which this class is to be associated. * @param msf the {@link Msf} for which this class is to be associated
* @param file {@link RandomAccessFile} underlying this class. * @param file {@link RandomAccessFile} underlying this class
*/ */
MsfFileReader(AbstractMsf msf, RandomAccessFile file) { MsfFileReader(Msf msf, RandomAccessFile file) {
this.msf = msf; this.msf = msf;
this.file = file; this.file = file;
} }
/** /**
* Reads a single page of bytes from the {@link AbstractMsf} and writes it into the bytes array. * Reads a single page of bytes from the {@link Msf} and writes it into the bytes array
* @param page The page number to read from the file. * @param page the page number to read from the file
* @param bytes The byte[] into which the data is to be written. * @param bytes the byte[] into which the data is to be written
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
*/ */
void readPage(int page, byte[] bytes) throws IOException { void readPage(int page, byte[] bytes) throws IOException {
read(page, 0, msf.getPageSize(), bytes, 0); read(page, 0, msf.getPageSize(), bytes, 0);
} }
/** /**
* Reads bytes from the {@link AbstractMsf} into a byte[]. * Reads bytes from the {@link Msf} into a byte[]
* @param page The page number within which to start the read. * @param page the page number within which to start the read
* @param offset The byte offset within the page to start the read. * @param offset the byte offset within the page to start the read
* @param numToRead The total number of bytes to read. * @param numToRead the total number of bytes to read
* @param bytes The byte[] into which the data is to be written. * @param bytes the byte[] into which the data is to be written
* @param bytesOffset The starting offset within the bytes array in which to start writing. * @param bytesOffset the starting offset within the bytes array in which to start writing
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* inability to read required bytes. * inability to read required bytes
*/ */
void read(int page, int offset, int numToRead, byte[] bytes, int bytesOffset) void read(int page, int offset, int numToRead, byte[] bytes, int bytesOffset)
throws IOException { throws IOException {
@ -95,7 +95,7 @@ class MsfFileReader implements AutoCloseable {
// Fail if file does not contain enough pages for the read--boundary case that assumes // Fail if file does not contain enough pages for the read--boundary case that assumes
// everything beyond the offset in the file belongs to this read. // everything beyond the offset in the file belongs to this read.
if (AbstractMsf.floorDivisionWithLog2Divisor(offset + numToRead, if (Msf.floorDivisionWithLog2Divisor(offset + numToRead,
msf.getLog2PageSize()) > msf.getNumPages()) { msf.getLog2PageSize()) > msf.getNumPages()) {
throw new IOException("Invalid MSF configuration"); throw new IOException("Invalid MSF configuration");
} }

View file

@ -20,11 +20,10 @@ import java.util.*;
import ghidra.util.LittleEndianDataConverter; import ghidra.util.LittleEndianDataConverter;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the Free Page Map for the Multi-Stream Format File (see Microsoft API). The * This class is the Free Page Map for the Multi-Stream Format File (see Microsoft API). The
* Free Page Map is a bit-encoding of whether a page within the {@link AbstractMsf} is * Free Page Map is a bit-encoding of whether a page within the {@link Msf} is
* currently used--for purposes of reusing available pages. * currently used--for purposes of reusing available pages.
* <P> * <P>
* This class was crafted to take the place of the formal Free Page Map in a complete * This class was crafted to take the place of the formal Free Page Map in a complete
@ -35,7 +34,7 @@ import ghidra.util.task.TaskMonitor;
* ENGINEERING PATH: Use java.util.BitSet for storage after processing. Could probably eliminate * ENGINEERING PATH: Use java.util.BitSet for storage after processing. Could probably eliminate
* the {@code List<Integer> map} storage. * the {@code List<Integer> map} storage.
*/ */
abstract class AbstractMsfFreePageMap { abstract class MsfFreePageMap {
//============================================================================================== //==============================================================================================
// Internals // Internals
@ -44,22 +43,22 @@ abstract class AbstractMsfFreePageMap {
private List<Integer> map = new ArrayList<>(); private List<Integer> map = new ArrayList<>();
protected static final int MAP_FIELD_SIZE = Integer.BYTES; protected static final int MAP_FIELD_SIZE = Integer.BYTES;
protected AbstractMsf msf; protected Msf msf;
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The {@link AbstractMsf} to which this class belongs. * @param msf the {@link Msf} to which this class belongs
*/ */
AbstractMsfFreePageMap(AbstractMsf msf) { MsfFreePageMap(Msf msf) {
this.msf = msf; this.msf = msf;
} }
/** /**
* Debug method to dump some of the internals of this class. * Debug method to dump some of the internals of this class
* @return Data dumped in a pretty format. * @return data dumped in a pretty format
*/ */
String dump() { String dump() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -80,19 +79,18 @@ abstract class AbstractMsfFreePageMap {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Method used to deserialize this class from disk. * Method used to deserialize this class from disc
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
abstract void deserialize(TaskMonitor monitor) throws IOException, CancelledException; abstract void deserialize() throws IOException, CancelledException;
/** /**
* Method indicating whether the Free Page Map is a "Big" Free Page Map. Currently, we have * Method indicating whether the Free Page Map is a "Big" Free Page Map. Currently, we have
* at least two types extending this class. One is "Big" (the newer v7.00) and the other is * at least two types extending this class. One is "Big" (the newer v7.00) and the other is
* not. The {@link #dump()} method makes use of this method. * not. The {@link #dump()} method makes use of this method
* @return true if it is a "Big" version of this class. * @return {@code true} if it is a "Big" version of this class
*/ */
abstract boolean isBig(); abstract boolean isBig();
@ -100,16 +98,15 @@ abstract class AbstractMsfFreePageMap {
// Internal Data Methods // Internal Data Methods
//============================================================================================== //==============================================================================================
/** /**
* Internal method for adding a records to the map from the {@code byte[]} argument. * Internal method for adding a records to the map from the {@code byte[]} argument
* @param bytes The {@code byte[]} containing the data. * @param bytes the {@code byte[]} containing the data
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
protected void addMap(byte[] bytes, TaskMonitor monitor) throws CancelledException { protected void addMap(byte[] bytes) throws CancelledException {
// TODO: If we implement FreePageMap further, then consider passing in a PdbByteReader // TODO: If we implement FreePageMap further, then consider passing in a PdbByteReader
// and using the reader to parse the appropriate Integral types. // and using the reader to parse the appropriate Integral types.
for (int index = 0; index < bytes.length - MAP_FIELD_SIZE; index += MAP_FIELD_SIZE) { for (int index = 0; index < bytes.length - MAP_FIELD_SIZE; index += MAP_FIELD_SIZE) {
monitor.checkCanceled(); msf.checkCanceled();
byte[] selectedBytes = Arrays.copyOfRange(bytes, index, index + MAP_FIELD_SIZE); byte[] selectedBytes = Arrays.copyOfRange(bytes, index, index + MAP_FIELD_SIZE);
map.add(LittleEndianDataConverter.INSTANCE.getInt(selectedBytes)); map.add(LittleEndianDataConverter.INSTANCE.getInt(selectedBytes));
} }

View file

@ -18,21 +18,20 @@ package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
import java.io.IOException; import java.io.IOException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link AbstractMsfFreePageMap} for Microsoft v2.00 Free Page Map. * This class is the version of {@link MsfFreePageMap} for Microsoft v2.00 Free Page Map.
*/ */
class MsfFreePageMap200 extends AbstractMsfFreePageMap { class MsfFreePageMap200 extends MsfFreePageMap {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The {@link AbstractMsf} to which this class belongs. * @param msf the {@link Msf} to which this class belongs
*/ */
MsfFreePageMap200(AbstractMsf msf) { MsfFreePageMap200(Msf msf) {
super(msf); super(msf);
} }
@ -42,12 +41,12 @@ class MsfFreePageMap200 extends AbstractMsfFreePageMap {
} }
@Override @Override
void deserialize(TaskMonitor monitor) throws IOException, CancelledException { void deserialize() throws IOException, CancelledException {
int size = msf.getNumSequentialFreePageMapPages() * msf.getPageSize(); int size = msf.getNumSequentialFreePageMapPages() * msf.getPageSize();
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
MsfFileReader fileReader = msf.fileReader; MsfFileReader fileReader = msf.fileReader;
fileReader.read(msf.getCurrentFreePageMapFirstPageNumber(), 0, size, bytes, 0); fileReader.read(msf.getCurrentFreePageMapFirstPageNumber(), 0, size, bytes, 0);
addMap(bytes, monitor); addMap(bytes);
} }
} }

View file

@ -18,21 +18,20 @@ package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
import java.io.IOException; import java.io.IOException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class is the version of {@link AbstractMsfFreePageMap} for Microsoft v7.00 Free Page Map. * This class is the version of {@link MsfFreePageMap} for Microsoft v7.00 Free Page Map.
*/ */
class MsfFreePageMap700 extends AbstractMsfFreePageMap { class MsfFreePageMap700 extends MsfFreePageMap {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The {@link AbstractMsf} to which this class belongs. * @param msf the {@link Msf} to which this class belongs
*/ */
MsfFreePageMap700(AbstractMsf msf) { MsfFreePageMap700(Msf msf) {
super(msf); super(msf);
} }
@ -42,11 +41,11 @@ class MsfFreePageMap700 extends AbstractMsfFreePageMap {
} }
@Override @Override
void deserialize(TaskMonitor monitor) throws IOException, CancelledException { void deserialize() throws IOException, CancelledException {
// Calculate the number of pages that the FreePageMap occupies on disk. // Calculate the number of pages that the FreePageMap occupies on disk.
int log2BitsPerPage = msf.getLog2PageSize() + 3; // 3 = log2(bitsperbyte) int log2BitsPerPage = msf.getLog2PageSize() + 3; // 3 = log2(bitsperbyte)
long freePageMapNumPages = long freePageMapNumPages =
AbstractMsf.floorDivisionWithLog2Divisor(msf.getNumPages(), log2BitsPerPage); Msf.floorDivisionWithLog2Divisor(msf.getNumPages(), log2BitsPerPage);
// Get the First page number of the FreePageMap on disk. // Get the First page number of the FreePageMap on disk.
int nextPageNumber = msf.getCurrentFreePageMapFirstPageNumber(); int nextPageNumber = msf.getCurrentFreePageMapFirstPageNumber();
@ -55,10 +54,10 @@ class MsfFreePageMap700 extends AbstractMsfFreePageMap {
MsfFileReader fileReader = msf.fileReader; MsfFileReader fileReader = msf.fileReader;
int pageSize = msf.getPageSize(); int pageSize = msf.getPageSize();
while (freePageMapNumPages > 0) { while (freePageMapNumPages > 0) {
monitor.checkCanceled(); msf.checkCanceled();
byte[] bytes = new byte[pageSize]; byte[] bytes = new byte[pageSize];
fileReader.read(nextPageNumber, 0, pageSize, bytes, 0); fileReader.read(nextPageNumber, 0, pageSize, bytes, 0);
addMap(bytes, monitor); addMap(bytes);
freePageMapNumPages--; freePageMapNumPages--;
// This is correct. Each page of the FreePageMap700 is located at pageSize number // This is correct. Each page of the FreePageMap700 is located at pageSize number
// of pages away from the last page. So if the first page of the FreePageMap700 // of pages away from the last page. So if the first page of the FreePageMap700

View file

@ -25,35 +25,35 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
/** /**
* Parser for detecting the appropriate {@link AbstractMsf} format for the filename given. * Parser for detecting the appropriate {@link Msf} format for the filename given.
* It then creates and returns the appropriate {@link AbstractMsf} object. * It then creates and returns the appropriate {@link Msf} object.
*/ */
public class MsfParser { public class MsfParser {
/** /**
* Detects, creates, and returns the appropriate {@link AbstractMsf} object found for * Detects, creates, and returns the appropriate {@link Msf} object found for
* the filename given. * the filename given
* @param filename Filename of the file to process. * @param filename name of the file to process
* @param pdbOptions {@link PdbReaderOptions} used for processing the PDB. * @param pdbOptions {@link PdbReaderOptions} used for processing the PDB
* @param monitor {@link TaskMonitor} used for checking cancellation. * @param monitor {@link TaskMonitor} used for checking cancellation
* @return Derived {@link AbstractMsf} object. * @return derived {@link Msf} object
* @throws IOException For file I/O reasons * @throws IOException for file I/O reasons
* @throws PdbException If an appropriate object cannot be created. * @throws PdbException if an appropriate object cannot be created
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
public static AbstractMsf parse(String filename, PdbReaderOptions pdbOptions, public static Msf parse(String filename, PdbReaderOptions pdbOptions,
TaskMonitor monitor) throws IOException, PdbException, CancelledException { TaskMonitor monitor) throws IOException, PdbException, CancelledException {
Objects.requireNonNull(filename, "filename cannot be null"); Objects.requireNonNull(filename, "filename cannot be null");
Objects.requireNonNull(pdbOptions, "pdbOptions cannot be null"); Objects.requireNonNull(pdbOptions, "pdbOptions cannot be null");
Objects.requireNonNull(monitor, "monitor cannot be null"); Objects.requireNonNull(monitor, "monitor cannot be null");
AbstractMsf msf; Msf msf;
RandomAccessFile file = new RandomAccessFile(filename, "r"); RandomAccessFile file = new RandomAccessFile(filename, "r");
if (Msf200.detected(file)) { if (Msf200.detected(file)) {
msf = new Msf200(file, pdbOptions); msf = new Msf200(file, filename, monitor, pdbOptions);
} }
else if (Msf700.detected(file)) { else if (Msf700.detected(file)) {
msf = new Msf700(file, pdbOptions); msf = new Msf700(file, filename, monitor, pdbOptions);
} }
else { else {
// Must close the file here. In cases where MSF is created, the MSF takes // Must close the file here. In cases where MSF is created, the MSF takes
@ -61,7 +61,7 @@ public class MsfParser {
file.close(); file.close();
throw new PdbException("MSF format not detected"); throw new PdbException("MSF format not detected");
} }
msf.deserialize(monitor); msf.deserialize();
return msf; return msf;
} }

View file

@ -23,17 +23,16 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* Class representing a Stream within an {@link AbstractMsf}--see its write-up. * Class representing a Stream within an {@link Msf}--see its write-up.
* <P> * <P>
* The stream can only be read, as it is part of a reader capability, not a read/write/modify * The stream can only be read, as it is part of a reader capability, not a read/write/modify
* capability. * capability.
* <P> * <P>
* The Stream can get initialized through a couple of mechanisms, but the essential information * The Stream can get initialized through a couple of mechanisms, but the essential information
* is the stream length, the map of stream page numbers to file page numbers, and the * is the stream length, the map of stream page numbers to file page numbers, and the
* referenced {@link AbstractMsf} to which it belongs, which contains most other * referenced {@link Msf} to which it belongs, which contains most other
* information that it needs. * information that it needs.
*/ */
public class MsfStream { public class MsfStream {
@ -48,14 +47,14 @@ public class MsfStream {
//============================================================================================== //==============================================================================================
protected int streamLength; protected int streamLength;
protected List<Integer> pageList = new ArrayList<>(); protected List<Integer> pageList = new ArrayList<>();
protected AbstractMsf msf; protected Msf msf;
//============================================================================================== //==============================================================================================
// API // API
//============================================================================================== //==============================================================================================
/** /**
* Returns the length of the Stream. * Returns the length of the Stream
* @return Byte-length of Stream. * @return byte-length of Stream
*/ */
public int getLength() { public int getLength() {
return streamLength; return streamLength;
@ -64,40 +63,38 @@ public class MsfStream {
/** /**
* Reads numToRead bytes from the stream starting at streamOffset within the stream. * Reads numToRead bytes from the stream starting at streamOffset within the stream.
* Returns the byte array containing the read information. If not all bytes are available * Returns the byte array containing the read information. If not all bytes are available
* to be read, an IOException will be thrown. * to be read, an IOException will be thrown
* @param streamOffset Location within the stream from where to start reading bytes. * @param streamOffset location within the stream from where to start reading bytes
* @param numToRead Number of bytes to read from the stream. * @param numToRead number of bytes to read from the stream
* @param monitor {@link TaskMonitor} used for checking cancellation. * @return byte[] containing the bytes read
* @return byte[] containing the bytes read. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public byte[] read(int streamOffset, int numToRead, TaskMonitor monitor) public byte[] read(int streamOffset, int numToRead)
throws IOException, CancelledException { throws IOException, CancelledException {
if (numToRead <= 0) { if (numToRead <= 0) {
return null; return null;
} }
byte[] bytes = new byte[numToRead]; byte[] bytes = new byte[numToRead];
read(streamOffset, bytes, 0, numToRead, monitor); read(streamOffset, bytes, 0, numToRead);
return bytes; return bytes;
} }
/** /**
* Reads numToRead bytes from the stream starting at streamOffset within the stream. * Reads numToRead bytes from the stream starting at streamOffset within the stream.
* The bytes are written into the bytes array starting at the bytesOffset location. * The bytes are written into the bytes array starting at the bytesOffset location.
* If not all bytes are available to be read, an IOException will be thrown. * If not all bytes are available to be read, an IOException will be thrown
* @param streamOffset Location within the stream from where to start reading bytes. * @param streamOffset location within the stream from where to start reading bytes
* @param bytes The array into which to write the data. * @param bytes the array into which to write the data
* @param bytesOffset The location within byte array at which to start writing data. * @param bytesOffset the location within byte array at which to start writing data
* @param numToRead Number of bytes to read from the stream. * @param numToRead number of bytes to read from the stream
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
public void read(int streamOffset, byte[] bytes, int bytesOffset, int numToRead, public void read(int streamOffset, byte[] bytes, int bytesOffset, int numToRead)
TaskMonitor monitor) throws IOException, CancelledException { throws IOException, CancelledException {
if (streamOffset < 0 || streamOffset > streamLength) { if (streamOffset < 0 || streamOffset > streamLength) {
throw new IOException("Offset out of range."); throw new IOException("Offset out of range.");
} }
@ -127,13 +124,13 @@ public class MsfStream {
// Read remaining pages, including last as possible partial page. // Read remaining pages, including last as possible partial page.
// Outer loop iterates over possible non-sequential groups. // Outer loop iterates over possible non-sequential groups.
while (remainingByteCount > 0) { while (remainingByteCount > 0) {
monitor.checkCanceled(); msf.checkCanceled();
// Inner loop groups together sequential pages into one big read. // Inner loop groups together sequential pages into one big read.
int firstSequentialPageNumber = pageList.get(pageNumber); int firstSequentialPageNumber = pageList.get(pageNumber);
int lastSequentialPageNumber = firstSequentialPageNumber; int lastSequentialPageNumber = firstSequentialPageNumber;
int numToReadInSequentialPages = 0; int numToReadInSequentialPages = 0;
do { do {
monitor.checkCanceled(); msf.checkCanceled();
pageNumber++; pageNumber++;
lastSequentialPageNumber++; lastSequentialPageNumber++;
int numToReadInPage = Math.min(msf.getPageSize(), remainingByteCount); int numToReadInPage = Math.min(msf.getPageSize(), remainingByteCount);
@ -148,9 +145,9 @@ public class MsfStream {
} }
/** /**
* Debug method to dump the PDB Directory in a pretty format to String. * Debug method to dump the PDB Directory in a pretty format to String
* @param maxOut Maximum number of bytes to output. * @param maxOut maximum number of bytes to output
* @return {@link String} containing the pretty output. * @return {@link String} containing the pretty output
*/ */
public String dump(int maxOut) { public String dump(int maxOut) {
int outputLength = Math.min(getLength(), maxOut); int outputLength = Math.min(getLength(), maxOut);
@ -164,7 +161,7 @@ public class MsfStream {
} }
byte[] bytes = new byte[outputLength]; byte[] bytes = new byte[outputLength];
try { try {
read(0, bytes, 0, outputLength, TaskMonitor.DUMMY); read(0, bytes, 0, outputLength);
} }
catch (IOException e) { catch (IOException e) {
// Should not occur. We limited our request to be <= the Stream length. // Should not occur. We limited our request to be <= the Stream length.
@ -188,21 +185,21 @@ public class MsfStream {
//============================================================================================== //==============================================================================================
/** /**
* Package-protected constructor of a PDB Stream. Sets the byte length of the * Package-protected constructor of a PDB Stream. Sets the byte length of the
* Stream to -1. This method is used when the Stream knows/reads its length. * Stream to -1. This method is used when the Stream knows/reads its length
* @param msf The {@link AbstractMsf} to which the Stream belongs. * @param msf the {@link Msf} to which the Stream belongs
*/ */
MsfStream(AbstractMsf msf) { MsfStream(Msf msf) {
streamLength = -1; streamLength = -1;
this.msf = msf; this.msf = msf;
} }
/** /**
* Package-protected constructor of a PDB Stream. This method is used when the * Package-protected constructor of a PDB Stream. This method is used when the
* stream length comes from an external table. * stream length comes from an external table
* @param msf The {@link AbstractMsf} to which the Stream belongs. * @param msf the {@link Msf} to which the Stream belongs
* @param streamLength The byte length of the Stream. * @param streamLength the byte length of the Stream
*/ */
MsfStream(AbstractMsf msf, int streamLength) { MsfStream(Msf msf, int streamLength) {
this.msf = msf; this.msf = msf;
this.streamLength = streamLength; this.streamLength = streamLength;
} }
@ -212,9 +209,9 @@ public class MsfStream {
* map when it was previously stored in memory) from the bytes parameter starting at the * map when it was previously stored in memory) from the bytes parameter starting at the
* index offset and uses it to provide necessary information for the Stream to be usable. * index offset and uses it to provide necessary information for the Stream to be usable.
* Generally, deserialization is part of the step of loading the Stream information from * Generally, deserialization is part of the step of loading the Stream information from
* persistent storage (disk). * persistent storage (disk)
* @param reader {@link PdbByteReader} from which to parse the information. * @param reader {@link PdbByteReader} from which to parse the information
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
void deserializeStreamLengthAndMapTableAddress(PdbByteReader reader) throws PdbException { void deserializeStreamLengthAndMapTableAddress(PdbByteReader reader) throws PdbException {
streamLength = reader.parseInt(); streamLength = reader.parseInt();
@ -226,21 +223,20 @@ public class MsfStream {
* Deserializes Stream page number information from the bytes parameter starting at the * Deserializes Stream page number information from the bytes parameter starting at the
* index offset and uses it to provide necessary information for the Stream to be usable. * index offset and uses it to provide necessary information for the Stream to be usable.
* Generally, deserialization is part of the step of loading the Stream information from * Generally, deserialization is part of the step of loading the Stream information from
* persistent storage (disk). * persistent storage (disc)
* @param reader {@link PdbByteReader} from which to parse the information. * @param reader {@link PdbByteReader} from which to parse the information
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserializePageNumbers(PdbByteReader reader, TaskMonitor monitor) void deserializePageNumbers(PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
// This calculations works fine for streamLength = 0 // This calculations works fine for streamLength = 0
// and even streamLength = -1 (0xffffffff). // and even streamLength = -1 (0xffffffff).
int numPages = int numPages =
AbstractMsf.floorDivisionWithLog2Divisor(streamLength, msf.getLog2PageSize()); Msf.floorDivisionWithLog2Divisor(streamLength, msf.getLog2PageSize());
if (msf.getPageNumberSize() == 2) { if (msf.getPageNumberSize() == 2) {
for (int i = 0; i < numPages; i++) { for (int i = 0; i < numPages; i++) {
monitor.checkCanceled(); msf.checkCanceled();
int pageNumber = reader.parseUnsignedShortVal(); int pageNumber = reader.parseUnsignedShortVal();
if (pageNumber == 0) { if (pageNumber == 0) {
break; break;
@ -250,7 +246,7 @@ public class MsfStream {
} }
else if (msf.getPageNumberSize() == 4) { else if (msf.getPageNumberSize() == 4) {
for (int i = 0; i < numPages; i++) { for (int i = 0; i < numPages; i++) {
monitor.checkCanceled(); msf.checkCanceled();
int pageNumber = reader.parseInt(); int pageNumber = reader.parseInt();
if (pageNumber == 0) { if (pageNumber == 0) {
break; break;
@ -264,18 +260,17 @@ public class MsfStream {
* Deserializes Stream information from the bytes parameter starting at the index offset * Deserializes Stream information from the bytes parameter starting at the index offset
* and uses it to provide necessary information for the Stream to be usable. * and uses it to provide necessary information for the Stream to be usable.
* Generally, deserialization is part of the step of loading the Stream information from * Generally, deserialization is part of the step of loading the Stream information from
* persistent storage (disk). * persistent storage (disc)
* @param reader {@link PdbByteReader} from which to parse the information. * @param reader {@link PdbByteReader} from which to parse the information
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon not enough data left to parse
* @throws PdbException Upon not enough data left to parse. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserializeStreamInfo(PdbByteReader reader, TaskMonitor monitor) void deserializeStreamInfo(PdbByteReader reader)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
deserializeStreamLengthAndMapTableAddress(reader); deserializeStreamLengthAndMapTableAddress(reader);
deserializePageNumbers(reader, monitor); deserializePageNumbers(reader);
} }
} }

View file

@ -22,45 +22,44 @@ import java.util.List;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents the the Stream Table used by the Multi-Stream Format File within * This class represents the the Stream Table used by the Multi-Stream Format File within
* Windows PDB files. * Windows PDB files.
* We have intended to implement to the Microsoft PDB API (source); see the API for truth. * We have intended to implement to the Microsoft PDB API (source); see the API for truth.
*/ */
abstract class AbstractMsfStreamTable { abstract class MsfStreamTable {
//============================================================================================== //==============================================================================================
// Internals // Internals
//============================================================================================== //==============================================================================================
protected AbstractMsf msf; protected Msf msf;
protected List<MsfStream> mapStreamNumberToStream; protected List<MsfStream> mapStreamNumberToStream;
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The {@link AbstractMsf} to which this class is associated. * @param msf the {@link Msf} to which this class is associated
*/ */
AbstractMsfStreamTable(AbstractMsf msf) { MsfStreamTable(Msf msf) {
this.msf = msf; this.msf = msf;
mapStreamNumberToStream = new ArrayList<>(); mapStreamNumberToStream = new ArrayList<>();
} }
/** /**
* Gets the number of streams in the stream table. * Gets the number of streams in the stream table
* @return Number of streams. * @return number of streams
*/ */
int getNumStreams() { int getNumStreams() {
return mapStreamNumberToStream.size(); return mapStreamNumberToStream.size();
} }
/** /**
* Returns the {@link MsfStream} from the stream table indexed by the streamNumber. * Returns the {@link MsfStream} from the stream table indexed by the streamNumber
* @param streamNumber The number ID of the stream to retrieve. * @param streamNumber the number ID of the stream to retrieve
* @return {@link MsfStream} or {@code null} if no stream for the streamNumber. * @return {@link MsfStream} or {@code null} if no stream for the streamNumber
*/ */
MsfStream getStream(int streamNumber) { MsfStream getStream(int streamNumber) {
return mapStreamNumberToStream.get(streamNumber); return mapStreamNumberToStream.get(streamNumber);
@ -69,18 +68,17 @@ abstract class AbstractMsfStreamTable {
/** /**
* Loads Stream Table information from the serial stream contained in the Directory Stream. * Loads Stream Table information from the serial stream contained in the Directory Stream.
* @param directoryStream The {@link MsfStream} that contains the serial information to be * @param directoryStream The {@link MsfStream} that contains the serial information to be
* deserialized. * deserialized
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws IOException on file seek or read, invalid parameters, bad file configuration, or
* @throws IOException On file seek or read, invalid parameters, bad file configuration, or * inability to read required bytes
* inability to read required bytes. * @throws PdbException upon error with PDB format
* @throws PdbException Upon error with PDB format. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void deserialize(MsfStream directoryStream, TaskMonitor monitor) void deserialize(MsfStream directoryStream)
throws IOException, PdbException, CancelledException { throws IOException, PdbException, CancelledException {
// Read whole stream and then take selections from the byte array, as needed. // Read whole stream and then take selections from the byte array, as needed.
int length = directoryStream.getLength(); int length = directoryStream.getLength();
byte[] bytes = directoryStream.read(0, length, monitor); byte[] bytes = directoryStream.read(0, length);
PdbByteReader reader = new PdbByteReader(bytes); PdbByteReader reader = new PdbByteReader(bytes);
// V2.00 has short followed by an unused short. We will presume it 0x0000 and process all // V2.00 has short followed by an unused short. We will presume it 0x0000 and process all
@ -91,7 +89,7 @@ abstract class AbstractMsfStreamTable {
// Get stream lengths and create streams. // Get stream lengths and create streams.
for (int streamNum = 0; streamNum < numStreams; streamNum++) { for (int streamNum = 0; streamNum < numStreams; streamNum++) {
monitor.checkCanceled(); msf.checkCanceled();
int streamLength = reader.parseInt(); int streamLength = reader.parseInt();
parseExtraField(reader); parseExtraField(reader);
MsfStream stream = new MsfStream(msf, streamLength); MsfStream stream = new MsfStream(msf, streamLength);
@ -100,35 +98,34 @@ abstract class AbstractMsfStreamTable {
// Populate the streams with their page information. // Populate the streams with their page information.
for (int streamNum = 0; streamNum < numStreams; streamNum++) { for (int streamNum = 0; streamNum < numStreams; streamNum++) {
monitor.checkCanceled(); msf.checkCanceled();
MsfStream stream = mapStreamNumberToStream.get(streamNum); MsfStream stream = mapStreamNumberToStream.get(streamNum);
if (stream != null) { if (stream != null) {
stream.deserializePageNumbers(reader, monitor); stream.deserializePageNumbers(reader);
} }
} }
// Now replace the directoryStream in the table with the directoryStream taken from the // Now replace the directoryStream in the table with the directoryStream taken from the
// header, as it is more up-to-date than then entry in the table. // header, as it is more up-to-date than then entry in the table.
setStream(msf.getDirectoryStreamNumber(), directoryStream, monitor); setStream(msf.getDirectoryStreamNumber(), directoryStream);
} }
/** /**
* Put a {@link MsfStream} into the Stream Table at the index location. If the index location * Put a {@link MsfStream} into the Stream Table at the index location. If the index location
* does not exist, then enough dummy Streams are added to the table to allow the new * does not exist, then enough dummy Streams are added to the table to allow the new
* {@link MsfStream} to be added at the index location. * {@link MsfStream} to be added at the index location
* @param index The location (reference number) for the {@link MsfStream} to be added * @param index the location (reference number) for the {@link MsfStream} to be added
* (possibly as a replacement). * (possibly as a replacement)
* @param stream The {@link MsfStream} to be added or used to replace an existing Stream. * @param stream the {@link MsfStream} to be added or used to replace an existing Stream
* @param monitor {@link TaskMonitor} used for checking cancellation. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation.
*/ */
void setStream(int index, MsfStream stream, TaskMonitor monitor) throws CancelledException { void setStream(int index, MsfStream stream) throws CancelledException {
if (index < mapStreamNumberToStream.size()) { if (index < mapStreamNumberToStream.size()) {
mapStreamNumberToStream.set(index, stream); mapStreamNumberToStream.set(index, stream);
} }
else { else {
for (int i = mapStreamNumberToStream.size(); i < index; i++) { for (int i = mapStreamNumberToStream.size(); i < index; i++) {
monitor.checkCanceled(); msf.checkCanceled();
mapStreamNumberToStream.add(null); mapStreamNumberToStream.add(null);
} }
mapStreamNumberToStream.add(stream); mapStreamNumberToStream.add(stream);
@ -147,15 +144,15 @@ abstract class AbstractMsfStreamTable {
// Abstract Methods // Abstract Methods
//============================================================================================== //==============================================================================================
/** /**
* Abstract method to reads/parse extra field for each entry. * Abstract method to reads/parse extra field for each entry
* @param reader The {@link PdbByteReader} that contains the data/location to parse. * @param reader the {@link PdbByteReader} that contains the data/location to parse
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
*/ */
protected abstract void parseExtraField(PdbByteReader reader) throws PdbException; protected abstract void parseExtraField(PdbByteReader reader) throws PdbException;
/** /**
* Returns the maximum number of MsfStreams allowed. * Returns the maximum number of MsfStreams allowed
* @return The maximum number of MsfStreams allowed. * @return the maximum number of MsfStreams allowed
*/ */
protected abstract int getMaxNumStreamsAllowed(); protected abstract int getMaxNumStreamsAllowed();

View file

@ -19,18 +19,18 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
/** /**
* This class is the version of {@link AbstractMsfStreamTable} for Microsoft v2.00 MSF. * This class is the version of {@link MsfStreamTable} for Microsoft v2.00 MSF.
*/ */
class MsfStreamTable200 extends AbstractMsfStreamTable { class MsfStreamTable200 extends MsfStreamTable {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The MSF associated for this class. * @param msf the MSF associated for this class
*/ */
MsfStreamTable200(AbstractMsf msf) { MsfStreamTable200(Msf msf) {
super(msf); super(msf);
} }

View file

@ -18,18 +18,18 @@ package ghidra.app.util.bin.format.pdb2.pdbreader.msf;
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbByteReader;
/** /**
* This class is the version of {@link AbstractMsfStreamTable} for Microsoft v7.00 MSF. * This class is the version of {@link MsfStreamTable} for Microsoft v7.00 MSF.
*/ */
class MsfStreamTable700 extends AbstractMsfStreamTable { class MsfStreamTable700 extends MsfStreamTable {
//============================================================================================== //==============================================================================================
// Package-Protected Internals // Package-Protected Internals
//============================================================================================== //==============================================================================================
/** /**
* Constructor. * Constructor
* @param msf The MSF associated for this class. * @param msf the MSF associated for this class
*/ */
MsfStreamTable700(AbstractMsf msf) { MsfStreamTable700(Msf msf) {
super(msf); super(msf);
} }

View file

@ -19,7 +19,6 @@ import java.util.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.*; import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/** /**
* This class represents the Discarded By Link symbol. * This class represents the Discarded By Link symbol.
@ -72,11 +71,11 @@ public class DiscardedByLinkMsSymbol extends AbstractMsSymbol {
//============================================================================================== //==============================================================================================
/** /**
* Constructor for this symbol. * Constructor for this symbol
* @param pdb {@link AbstractPdb} to which this symbol belongs. * @param pdb {@link AbstractPdb} to which this symbol belongs
* @param reader {@link PdbByteReader} from which this symbol is deserialized. * @param reader {@link PdbByteReader} from which this symbol is deserialized
* @throws PdbException Upon not enough data left to parse. * @throws PdbException upon not enough data left to parse
* @throws CancelledException Upon user cancellation. * @throws CancelledException upon user cancellation
*/ */
public DiscardedByLinkMsSymbol(AbstractPdb pdb, PdbByteReader reader) public DiscardedByLinkMsSymbol(AbstractPdb pdb, PdbByteReader reader)
throws PdbException, CancelledException { throws PdbException, CancelledException {
@ -95,12 +94,12 @@ public class DiscardedByLinkMsSymbol extends AbstractMsSymbol {
// SymbolParser parser = new SymbolParser(pdb); // SymbolParser parser = new SymbolParser(pdb);
// symbolList = parser.deserializeSymbolRecords(dataReader); // symbolList = parser.deserializeSymbolRecords(dataReader);
symbolList = getOrderedSymbols( symbolList = getOrderedSymbols(
SymbolRecords.deserializeSymbolRecords(pdb, dataReader, TaskMonitor.DUMMY)); SymbolRecords.deserializeSymbolRecords(pdb, dataReader));
} }
/** /**
* Returns the list of symbols in the order they were seen. * Returns the list of symbols in the order they were seen
* @return the list of symbols. * @return the list of symbols
*/ */
private List<AbstractMsSymbol> getOrderedSymbols(Map<Long, AbstractMsSymbol> symbolsByOffset) { private List<AbstractMsSymbol> getOrderedSymbols(Map<Long, AbstractMsSymbol> symbolsByOffset) {
List<Long> offsets = new ArrayList<>(symbolsByOffset.keySet()); List<Long> offsets = new ArrayList<>(symbolsByOffset.keySet());

View file

@ -18,8 +18,8 @@ package ghidra.app.util.pdb.pdbapplicator;
import java.util.*; import java.util.*;
import ghidra.app.util.SymbolPath; import ghidra.app.util.SymbolPath;
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractTypeProgramInterface;
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber; import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
import ghidra.app.util.bin.format.pdb2.pdbreader.TypeProgramInterface;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -51,15 +51,14 @@ public class ComplexTypeApplierMapper {
//============================================================================================== //==============================================================================================
//============================================================================================== //==============================================================================================
void mapAppliers(TaskMonitor monitor) throws CancelledException { void mapAppliers(TaskMonitor monitor) throws CancelledException {
AbstractTypeProgramInterface typeProgramInterface = TypeProgramInterface typeProgramInterface = applicator.getPdb().getTypeProgramInterface();
applicator.getPdb().getTypeProgramInterface();
if (typeProgramInterface == null) { if (typeProgramInterface == null) {
return; return;
} }
int indexLimit = typeProgramInterface.getTypeIndexMaxExclusive(); int indexLimit = typeProgramInterface.getTypeIndexMaxExclusive();
int indexNumber = typeProgramInterface.getTypeIndexMin(); int indexNumber = typeProgramInterface.getTypeIndexMin();
monitor.initialize(indexLimit - indexNumber); monitor.initialize(indexLimit - indexNumber);
applicator.setMonitorMessage("PDB: Mapping Composites..."); monitor.setMessage("PDB: Mapping Composites...");
while (indexNumber < indexLimit) { while (indexNumber < indexLimit) {
monitor.checkCanceled(); monitor.checkCanceled();
//PdbResearch.checkBreak(indexNumber); //PdbResearch.checkBreak(indexNumber);

View file

@ -52,13 +52,14 @@ import ghidra.util.task.TaskMonitor;
* The class is to be constructed first. * The class is to be constructed first.
* <p> * <p>
* The * The
* {@link #applyTo(Program, DataTypeManager, Address, PdbApplicatorOptions, TaskMonitor, MessageLog)} * {@link #applyTo(Program, DataTypeManager, Address, PdbApplicatorOptions, MessageLog)} method is
* method is then called with the appropriate {@link PdbApplicatorOptions} along with a * then called with the appropriate {@link PdbApplicatorOptions} along with
* {@link Program} and/or {@link DataTypeManager}. Either, but not both can be null. * a {@link Program} and/or {@link DataTypeManager}. Either, but not both can be null.
* If the Program is not null but the DatatypeManager is null, then the DataTypeManager is gotten * If the Program is not null but the DatatypeManager is null, then the DataTypeManager is gotten
* from the Program. If the Program is null, then data types can be applied to a DataTypeManager. * from the Program. If the Program is null, then data types can be applied to a DataTypeManager.
* The validation logic for the parameters is found in * The validation logic for the parameters is found in
* {@link #validateAndSetParameters(Program, DataTypeManager, Address, PdbApplicatorOptions, TaskMonitor, MessageLog)}. * {@link #validateAndSetParameters(Program, DataTypeManager, Address, PdbApplicatorOptions,
* MessageLog)}.
* <p> * <p>
* Once the parameters are validated, appropriate classes and storage containers are constructed. * Once the parameters are validated, appropriate classes and storage containers are constructed.
* Then processing commences, first with data types, followed by symbol-related processing. * Then processing commences, first with data types, followed by symbol-related processing.
@ -72,10 +73,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
/** /**
* Returns integer value of BigInteger or Integer.MAX_VALUE if does not fit. * Returns integer value of BigInteger or Long.MAX_VALUE if does not fit
* @param myApplicator PdbApplicator for which we are working. * @param myApplicator PdbApplicator for which we are working
* @param big BigInteger value to convert. * @param big BigInteger value to convert
* @return the integer value. * @return the integer value
*/ */
static long bigIntegerToLong(DefaultPdbApplicator myApplicator, BigInteger big) { static long bigIntegerToLong(DefaultPdbApplicator myApplicator, BigInteger big) {
try { try {
@ -90,10 +91,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns integer value of BigInteger or Integer.MAX_VALUE if does not fit. * Returns integer value of BigInteger or Integer.MAX_VALUE if does not fit
* @param myApplicator PdbApplicator for which we are working. * @param myApplicator PdbApplicator for which we are working
* @param big BigInteger value to convert. * @param big BigInteger value to convert
* @return the integer value. * @return the integer value
*/ */
static int bigIntegerToInt(DefaultPdbApplicator myApplicator, BigInteger big) { static int bigIntegerToInt(DefaultPdbApplicator myApplicator, BigInteger big) {
try { try {
@ -108,7 +109,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
//============================================================================================== //==============================================================================================
private String pdbFilename;
private AbstractPdb pdb; private AbstractPdb pdb;
private PdbApplicatorMetrics pdbApplicatorMetrics; private PdbApplicatorMetrics pdbApplicatorMetrics;
@ -118,7 +118,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
private PdbApplicatorOptions applicatorOptions; private PdbApplicatorOptions applicatorOptions;
private MessageLog log; private MessageLog log;
private TaskMonitor monitor;
private CancelOnlyWrappingTaskMonitor cancelOnlyWrappingMonitor; private CancelOnlyWrappingTaskMonitor cancelOnlyWrappingMonitor;
//============================================================================================== //==============================================================================================
@ -165,11 +164,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
private Map<Integer, Set<RecordNumber>> recordNumbersByModuleNumber; private Map<Integer, Set<RecordNumber>> recordNumbersByModuleNumber;
//============================================================================================== //==============================================================================================
// TODO: eventually put access methods on AbstractPdb to get filename from it (deep down). public DefaultPdbApplicator(AbstractPdb pdb) {
public DefaultPdbApplicator(String pdbFilename, AbstractPdb pdb) {
Objects.requireNonNull(pdbFilename, "pdbFilename cannot be null");
Objects.requireNonNull(pdb, "pdb cannot be null"); Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdbFilename = pdbFilename;
this.pdb = pdb; this.pdb = pdb;
} }
@ -177,29 +173,28 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
/** /**
* Applies the PDB to the {@link Program} or {@link DataTypeManager}. Either, but not both, * Applies the PDB to the {@link Program} or {@link DataTypeManager}. Either, but not both,
* can be null. * can be null
* @param programParam The {@link Program} to which to apply the PDB. Can be null in certain * @param programParam the {@link Program} to which to apply the PDB. Can be null in certain
* circumstances. * circumstances
* @param dataTypeManagerParam The {@link DataTypeManager} to which to apply data types. Can be * @param dataTypeManagerParam the {@link DataTypeManager} to which to apply data types. Can be
* null in certain circumstances. * null in certain circumstances
* @param imageBaseParam Address bases from which symbol addresses are based. If null, uses * @param imageBaseParam address bases from which symbol addresses are based. If null, uses
* the image base of the program (both cannot be null). * the image base of the program (both cannot be null)
* @param applicatorOptionsParam {@link PdbApplicatorOptions} used for applying the PDB. * @param applicatorOptionsParam {@link PdbApplicatorOptions} used for applying the PDB
* @param monitorParam TaskMonitor uses for watching progress and cancellation notices. * @param logParam the MessageLog to which to output messages
* @param logParam The MessageLog to which to output messages. * @throws PdbException if there was a problem processing the data
* @throws PdbException if there was a problem processing the data. * @throws CancelledException upon user cancellation
* @throws CancelledException Upon user cancellation
*/ */
public void applyTo(Program programParam, DataTypeManager dataTypeManagerParam, public void applyTo(Program programParam, DataTypeManager dataTypeManagerParam,
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam, Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
TaskMonitor monitorParam, MessageLog logParam) throws PdbException, CancelledException { MessageLog logParam) throws PdbException, CancelledException {
// FIXME: should not support use of DataTypeManager-only since it will not have the correct data // FIXME: should not support use of DataTypeManager-only since it will not have the correct
// organization if it corresponds to a data type archive. Need to evaulate archive use case // data organization if it corresponds to a data type archive. Need to evaluate archive
// and determine if a program must always be used. // use case and determine if a program must always be used.
initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam, initializeApplyTo(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, monitorParam, logParam); applicatorOptionsParam, logParam);
switch (applicatorOptions.getProcessingControl()) { switch (applicatorOptions.getProcessingControl()) {
case DATA_TYPES_ONLY: case DATA_TYPES_ONLY:
@ -231,7 +226,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void processTypes() throws CancelledException, PdbException { private void processTypes() throws CancelledException, PdbException {
setMonitorMessage("PDB: Applying to DTM " + dataTypeManager.getName() + "..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying to DTM " + dataTypeManager.getName() + "...");
PdbResearch.initBreakPointRecordNumbers(); // for developmental debug PdbResearch.initBreakPointRecordNumbers(); // for developmental debug
@ -323,12 +319,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void initializeApplyTo(Program programParam, DataTypeManager dataTypeManagerParam, private void initializeApplyTo(Program programParam, DataTypeManager dataTypeManagerParam,
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam, Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
TaskMonitor monitorParam, MessageLog logParam) throws PdbException, CancelledException { MessageLog logParam) throws PdbException, CancelledException {
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam, validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, monitorParam, logParam); applicatorOptionsParam, logParam);
cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(monitor); cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(getMonitor());
pdbApplicatorMetrics = new PdbApplicatorMetrics(); pdbApplicatorMetrics = new PdbApplicatorMetrics();
pdbPeHeaderInfoManager = new PdbPeHeaderInfoManager(this); pdbPeHeaderInfoManager = new PdbPeHeaderInfoManager(this);
@ -338,7 +334,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
pdbAddressManager = new PdbAddressManager(this, imageBase); pdbAddressManager = new PdbAddressManager(this, imageBase);
categoryUtils = setPdbCatogoryUtils(pdbFilename); categoryUtils = setPdbCatogoryUtils(pdb.getFilename());
pdbPrimitiveTypeApplicator = new PdbPrimitiveTypeApplicator(dataTypeManager); pdbPrimitiveTypeApplicator = new PdbPrimitiveTypeApplicator(dataTypeManager);
typeApplierParser = new TypeApplierFactory(this); typeApplierParser = new TypeApplierFactory(this);
complexApplierMapper = new ComplexTypeApplierMapper(this); complexApplierMapper = new ComplexTypeApplierMapper(this);
@ -367,8 +363,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void validateAndSetParameters(Program programParam, private void validateAndSetParameters(Program programParam,
DataTypeManager dataTypeManagerParam, Address imageBaseParam, DataTypeManager dataTypeManagerParam, Address imageBaseParam,
PdbApplicatorOptions applicatorOptionsParam, TaskMonitor monitorParam, PdbApplicatorOptions applicatorOptionsParam, MessageLog logParam) throws PdbException {
MessageLog logParam) throws PdbException {
applicatorOptions = applicatorOptions =
(applicatorOptionsParam != null) ? applicatorOptionsParam : new PdbApplicatorOptions(); (applicatorOptionsParam != null) ? applicatorOptionsParam : new PdbApplicatorOptions();
if (programParam == null) { if (programParam == null) {
@ -386,7 +381,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
applicatorOptions.getProcessingControl()); applicatorOptions.getProcessingControl());
} }
} }
monitor = (monitorParam != null) ? monitorParam : TaskMonitor.DUMMY;
log = (logParam != null) ? logParam : new MessageLog(); log = (logParam != null) ? logParam : new MessageLog();
program = programParam; program = programParam;
dataTypeManager = dataTypeManager =
@ -404,7 +398,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
// moduleNumber zero is our global/public group. // moduleNumber zero is our global/public group.
for (int moduleNumber = 0; moduleNumber <= num; moduleNumber++) { for (int moduleNumber = 0; moduleNumber <= num; moduleNumber++) {
monitor.checkCanceled(); checkCanceled();
Map<Long, AbstractMsSymbol> symbols = debugInfo.getModuleSymbolsByOffset(moduleNumber); Map<Long, AbstractMsSymbol> symbols = debugInfo.getModuleSymbolsByOffset(moduleNumber);
SymbolGroup symbolGroup = new SymbolGroup(symbols, moduleNumber); SymbolGroup symbolGroup = new SymbolGroup(symbols, moduleNumber);
mySymbolGroups.add(symbolGroup); mySymbolGroups.add(symbolGroup);
@ -416,8 +410,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
// Basic utility methods. // Basic utility methods.
//============================================================================================== //==============================================================================================
/** /**
* Returns the {@link PdbApplicatorOptions} for this PdbApplicator. * Returns the {@link PdbApplicatorOptions} for this PdbApplicator
* @return the {@link PdbApplicatorOptions} for this PdbApplicator. * @return the {@link PdbApplicatorOptions} for this PdbApplicator
*/ */
PdbApplicatorOptions getPdbApplicatorOptions() { PdbApplicatorOptions getPdbApplicatorOptions() {
return applicatorOptions; return applicatorOptions;
@ -428,15 +422,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @throws CancelledException if monitor has been cancelled * @throws CancelledException if monitor has been cancelled
*/ */
void checkCanceled() throws CancelledException { void checkCanceled() throws CancelledException {
monitor.checkCanceled(); getMonitor().checkCanceled();
}
/**
* Sets the message displayed on the task monitor
* @param message the message to display
*/
void setMonitorMessage(String message) {
monitor.setMessage(message);
} }
/** /**
@ -448,7 +434,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the MessageLog. * Returns the MessageLog
* @return the MessageLog * @return the MessageLog
*/ */
MessageLog getMessageLog() { MessageLog getMessageLog() {
@ -483,34 +469,34 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the {@link TaskMonitor} to available for this analyzer. * Returns the TaskMonitor
* @return the monitor. * @return the monitor
*/ */
TaskMonitor getMonitor() { public TaskMonitor getMonitor() {
return monitor; return pdb.getMonitor();
} }
/** /**
* Returns the {@link CancelOnlyWrappingTaskMonitor} to available for this analyzer. This is * Returns the {@link CancelOnlyWrappingTaskMonitor} to available for this analyzer. This is
* useful for the user to be able to control the monitor progress bar without called commands * useful for the user to be able to control the monitor progress bar without called commands
* changing its progress on smaller tasks. * changing its progress on smaller tasks
* @return the monitor. * @return the monitor
*/ */
TaskMonitor getCancelOnlyWrappingMonitor() { TaskMonitor getCancelOnlyWrappingMonitor() {
return cancelOnlyWrappingMonitor; return cancelOnlyWrappingMonitor;
} }
/** /**
* Returns the {@link PdbApplicatorMetrics} being used for this applicator. * Returns the {@link PdbApplicatorMetrics} being used for this applicator
* @return the {@link PdbApplicatorMetrics}. * @return the {@link PdbApplicatorMetrics}
*/ */
PdbApplicatorMetrics getPdbApplicatorMetrics() { PdbApplicatorMetrics getPdbApplicatorMetrics() {
return pdbApplicatorMetrics; return pdbApplicatorMetrics;
} }
/** /**
* Returns the {@link AbstractPdb} being analyzed. * Returns the {@link AbstractPdb} being analyzed
* @return {@link AbstractPdb} being analyzed. * @return {@link AbstractPdb} being analyzed
*/ */
@Override @Override
public AbstractPdb getPdb() { public AbstractPdb getPdb() {
@ -518,8 +504,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the {@link Program} for which this analyzer is working. * Returns the {@link Program} for which this analyzer is working
* @return {@link Program} for which this analyzer is working. * @return {@link Program} for which this analyzer is working
*/ */
@Override @Override
public Program getProgram() { public Program getProgram() {
@ -530,8 +516,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
// Information for a putative PdbTypeApplicator: // 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. * @return DataTypeManager which this analyzer is using
*/ */
DataTypeManager getDataTypeManager() { DataTypeManager getDataTypeManager() {
return dataTypeManager; return dataTypeManager;
@ -551,10 +537,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
/** /**
* Get the {@link CategoryPath} associated with the {@link SymbolPath} specified, rooting * Get the {@link CategoryPath} associated with the {@link SymbolPath} specified, rooting
* it either at the PDB Category. * it either at the PDB Category
* @param symbolPath Symbol path to be used to create the CategoryPath. Null represents global * @param symbolPath symbol path to be used to create the CategoryPath. Null represents global
* namespace. * namespace
* @return {@link CategoryPath} created for the input. * @return {@link CategoryPath} created for the input
*/ */
CategoryPath getCategory(SymbolPath symbolPath) { CategoryPath getCategory(SymbolPath symbolPath) {
return categoryUtils.getCategory(symbolPath); return categoryUtils.getCategory(symbolPath);
@ -562,8 +548,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Returns the {@link CategoryPath} for a typedef with with the give {@link SymbolPath} and * Returns the {@link CategoryPath} for a typedef with with the give {@link SymbolPath} and
* module number; 1 <= moduleNumber <= {@link PdbDebugInfo#getNumModules()}, * module number; 1 <= moduleNumber <= {@link PdbDebugInfo#getNumModules()}
* except that modeleNumber of 0 represents publics/globals. * except that modeleNumber of 0 represents publics/globals
* @param moduleNumber module number * @param moduleNumber module number
* @param symbolPath SymbolPath of the symbol * @param symbolPath SymbolPath of the symbol
* @return the CategoryPath * @return the CategoryPath
@ -573,7 +559,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the {@link CategoryPath} for Anonymous Functions Category for the PDB. * Returns the {@link CategoryPath} for Anonymous Functions Category for the PDB
* @return the {@link CategoryPath} * @return the {@link CategoryPath}
*/ */
CategoryPath getAnonymousFunctionsCategory() { CategoryPath getAnonymousFunctionsCategory() {
@ -581,7 +567,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the {@link CategoryPath} for Anonymous Types Category for the PDB. * Returns the {@link CategoryPath} for Anonymous Types Category for the PDB
* @return the {@link CategoryPath} * @return the {@link CategoryPath}
*/ */
CategoryPath getAnonymousTypesCategory() { CategoryPath getAnonymousTypesCategory() {
@ -616,7 +602,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
for (int index = 1; index <= num; index++) { for (int index = 1; index <= num; index++) {
monitor.checkCanceled(); checkCanceled();
String moduleName = debugInfo.getModuleInformation(index).getModuleName(); String moduleName = debugInfo.getModuleInformation(index).getModuleName();
categoryNames.add(moduleName); categoryNames.add(moduleName);
} }
@ -650,7 +636,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
List<MsTypeApplier> getVerticesInPostOrder() { List<MsTypeApplier> getVerticesInPostOrder() {
setMonitorMessage("PDB: Determining data type dependency order..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Determining data type dependency order...");
return GraphAlgorithms.getVerticesInPostOrder(applierDependencyGraph, return GraphAlgorithms.getVerticesInPostOrder(applierDependencyGraph,
GraphNavigator.topDownNavigator()); GraphNavigator.topDownNavigator());
} }
@ -686,7 +673,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
throw new PdbException("PDB: DebugInfo is null"); throw new PdbException("PDB: DebugInfo is null");
} }
for (AbstractSectionContribution sectionContribution : debugInfo for (SectionContribution sectionContribution : debugInfo
.getSectionContributionList()) { .getSectionContributionList()) {
int sectionContributionOffset = sectionContribution.getOffset(); int sectionContributionOffset = sectionContribution.getOffset();
int maxSectionContributionOffset = int maxSectionContributionOffset =
@ -700,13 +687,14 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void processDataTypesSequentially() throws CancelledException, PdbException { private void processDataTypesSequentially() throws CancelledException, PdbException {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface(); TypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) { if (tpi == null) {
return; return;
} }
int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin(); int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin();
TaskMonitor monitor = getMonitor();
monitor.initialize(num); monitor.initialize(num);
setMonitorMessage("PDB: Processing " + num + " data type components..."); monitor.setMessage("PDB: Processing " + num + " data type components...");
for (int indexNumber = for (int indexNumber =
tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) { tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCanceled(); monitor.checkCanceled();
@ -767,13 +755,14 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
//============================================================================================== //==============================================================================================
private void processItemTypesSequentially() throws CancelledException, PdbException { private void processItemTypesSequentially() throws CancelledException, PdbException {
AbstractTypeProgramInterface ipi = pdb.getItemProgramInterface(); TypeProgramInterface ipi = pdb.getItemProgramInterface();
if (ipi == null) { if (ipi == null) {
return; return;
} }
int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin(); int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin();
TaskMonitor monitor = getMonitor();
monitor.initialize(num); monitor.initialize(num);
setMonitorMessage("PDB: Processing " + num + " item type components..."); monitor.setMessage("PDB: Processing " + num + " item type components...");
for (int indexNumber = for (int indexNumber =
ipi.getTypeIndexMin(); indexNumber < ipi.getTypeIndexMaxExclusive(); indexNumber++) { ipi.getTypeIndexMin(); indexNumber < ipi.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCanceled(); monitor.checkCanceled();
@ -792,8 +781,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void processDeferred() throws CancelledException, PdbException { private void processDeferred() throws CancelledException, PdbException {
List<MsTypeApplier> verticesInPostOrder = getVerticesInPostOrder(); List<MsTypeApplier> verticesInPostOrder = getVerticesInPostOrder();
TaskMonitor monitor = getMonitor();
monitor.initialize(verticesInPostOrder.size()); monitor.initialize(verticesInPostOrder.size());
setMonitorMessage("PDB: Processing " + verticesInPostOrder.size() + monitor.setMessage("PDB: Processing " + verticesInPostOrder.size() +
" deferred data type dependencies..."); " deferred data type dependencies...");
for (MsTypeApplier applier : verticesInPostOrder) { for (MsTypeApplier applier : verticesInPostOrder) {
monitor.checkCanceled(); monitor.checkCanceled();
@ -808,13 +798,14 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void resolveSequentially() throws CancelledException { private void resolveSequentially() throws CancelledException {
AbstractTypeProgramInterface tpi = pdb.getTypeProgramInterface(); TypeProgramInterface tpi = pdb.getTypeProgramInterface();
if (tpi == null) { if (tpi == null) {
return; return;
} }
int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin(); int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin();
TaskMonitor monitor = getMonitor();
monitor.initialize(num); monitor.initialize(num);
setMonitorMessage("PDB: Resolving " + num + " data type components..."); monitor.setMessage("PDB: Resolving " + num + " data type components...");
long longStart = System.currentTimeMillis(); long longStart = System.currentTimeMillis();
for (int indexNumber = for (int indexNumber =
tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) { tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) {
@ -869,10 +860,10 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Returns true if the {@link Address} is an invalid address for continuing application of * Returns true if the {@link Address} is an invalid address for continuing application of
* information to the program. Will report Error or message for an invalid address and will * information to the program. Will report Error or message for an invalid address and will
* report a "External address" message for the name when the address is external. * report a "External address" message for the name when the address is external
* @param address the address to test * @param address the address to test
* @param name name associated with the address used for reporting error/info situations. * @param name name associated with the address used for reporting error/info situations
* @return {@code true} if the address should be processed. * @return {@code true} if the address should be processed
*/ */
boolean isInvalidAddress(Address address, String name) { boolean isInvalidAddress(Address address, String name) {
if (address == PdbAddressManager.BAD_ADDRESS) { if (address == PdbAddressManager.BAD_ADDRESS) {
@ -899,30 +890,30 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Returns the Address for the given section and offset. * Returns the Address for the given section and offset
* @param symbol The {@link AddressMsSymbol} * @param symbol the {@link AddressMsSymbol}
* @return The Address, which can be {@code Address.NO_ADDRESS} if invalid or * @return the Address, which can be {@code Address.NO_ADDRESS} if invalid or
* {@code Address.EXTERNAL_ADDRESS} if the address is external to the program. * {@code Address.EXTERNAL_ADDRESS} if the address is external to the program
*/ */
Address getAddress(AddressMsSymbol symbol) { Address getAddress(AddressMsSymbol symbol) {
return pdbAddressManager.getAddress(symbol); return pdbAddressManager.getAddress(symbol);
} }
/** /**
* Returns the Address for the given section and offset. * Returns the Address for the given section and offset
* @param segment The segment * @param segment the segment
* @param offset The offset * @param offset the offset
* @return The Address * @return the Address
*/ */
Address getAddress(int segment, long offset) { Address getAddress(int segment, long offset) {
return pdbAddressManager.getRawAddress(segment, offset); return pdbAddressManager.getRawAddress(segment, offset);
} }
/** /**
* Returns the Address for the given section and offset. * Returns the Address for the given section and offset
* @param symbol The {@link AddressMsSymbol} * @param symbol The {@link AddressMsSymbol}
* @return The Address, which can be {@code Address.NO_ADDRESS} if invalid or * @return the Address, which can be {@code Address.NO_ADDRESS} if invalid or
* {@code Address.EXTERNAL_ADDRESS} if the address is external to the program. * {@code Address.EXTERNAL_ADDRESS} if the address is external to the program
*/ */
Address getRawAddress(AddressMsSymbol symbol) { Address getRawAddress(AddressMsSymbol symbol) {
return pdbAddressManager.getRawAddress(symbol); return pdbAddressManager.getRawAddress(symbol);
@ -933,7 +924,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
* associated address. This allows the PdbAddressManager to create and organize the * associated address. This allows the PdbAddressManager to create and organize the
* re-mapped address and supply them. Also returns the address of the pre-existing symbol * re-mapped address and supply them. Also returns the address of the pre-existing symbol
* of the same name if the name was unique, otherwise null if it didn't exist or wasn't * of the same name if the name was unique, otherwise null if it didn't exist or wasn't
* unique. * unique
* @param name the symbol name * @param name the symbol name
* @param address its associated address * @param address its associated address
* @return the {@link Address} of existing symbol or null * @return the {@link Address} of existing symbol or null
@ -946,7 +937,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
* Returns the Address of an existing symbol for the query address, where the mapping is * Returns the Address of an existing symbol for the query address, where the mapping is
* derived by using a the address of a PDB symbol as the key and finding the address of * derived by using a the address of a PDB symbol as the key and finding the address of
* a symbol in the program of the same "unique" name. This is accomplished using public * a symbol in the program of the same "unique" name. This is accomplished using public
* mangled symbols. If the program symbol came from the PDB, then it maps to itself. * mangled symbols. If the program symbol came from the PDB, then it maps to itself
* @param address the query address * @param address the query address
* @return the remapAddress * @return the remapAddress
*/ */
@ -989,8 +980,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Get CLI metadata for specified tableNum and rowNum within the CLI * Get CLI metadata for specified tableNum and rowNum within the CLI metadata stream
* metadata stream.
* @param tableNum CLI metadata stream table index * @param tableNum CLI metadata stream table index
* @param rowNum table row number * @param rowNum table row number
* @return CLI metadata or null if specified tableNum not found * @return CLI metadata or null if specified tableNum not found
@ -1021,7 +1011,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Process all symbols. User should not then call other methods: * Process all symbols. User should not then call other methods:
* {@link #processGlobalSymbolsNoTypedefs()}, (@link #processPublicSymbols()}, and * {@link #processGlobalSymbolsNoTypedefs()}, (@link #processPublicSymbols()}, and
* {@link #processNonPublicOrGlobalSymbols()}. * {@link #processNonPublicOrGlobalSymbols()}
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon issue processing the request * @throws PdbException upon issue processing the request
*/ */
@ -1039,7 +1029,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
int totalCount = symbolGroup.size(); int totalCount = symbolGroup.size();
setMonitorMessage("PDB: Applying " + totalCount + " main symbol components..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying " + totalCount + " main symbol components...");
monitor.initialize(totalCount); monitor.initialize(totalCount);
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
processSymbolGroup(0, iter); processSymbolGroup(0, iter);
@ -1054,6 +1045,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
int totalCount = 0; int totalCount = 0;
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) { for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) {
monitor.checkCanceled(); monitor.checkCanceled();
SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber); SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber);
@ -1062,7 +1054,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
totalCount += symbolGroup.size(); totalCount += symbolGroup.size();
} }
setMonitorMessage("PDB: Applying " + totalCount + " module symbol components..."); monitor.setMessage("PDB: Applying " + totalCount + " module symbol components...");
monitor.initialize(totalCount); monitor.initialize(totalCount);
// Process symbols list for each module // Process symbols list for each module
@ -1098,6 +1090,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void processSymbolGroup(int moduleNumber, AbstractMsSymbolIterator iter) private void processSymbolGroup(int moduleNumber, AbstractMsSymbolIterator iter)
throws CancelledException { throws CancelledException {
iter.initGet(); iter.initGet();
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCanceled(); monitor.checkCanceled();
procSym(iter); procSym(iter);
@ -1108,8 +1101,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
/** /**
* Process public symbols. User should not then call {@link #processAllSymbols()}; but * Process public symbols. User should not then call {@link #processAllSymbols()}; but
* has these other methods available to supplement this one: {@link #processGlobalSymbolsNoTypedefs()} * has these other methods available to supplement this one:
* and {@link #processNonPublicOrGlobalSymbols()}. * {@link #processGlobalSymbolsNoTypedefs()} and {@link #processNonPublicOrGlobalSymbols()}
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon issue processing the request * @throws PdbException upon issue processing the request
*/ */
@ -1127,7 +1120,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation(); PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
setMonitorMessage("PDB: Applying " + offsets.size() + " public symbol components..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying " + offsets.size() + " public symbol components...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
@ -1146,7 +1140,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Process global symbols--no typedef. User should not then call {@link #processAllSymbols()}; * Process global symbols--no typedef. User should not then call {@link #processAllSymbols()};
* but has these other methods available to supplement this one: (@link #processPublicSymbols()} * but has these other methods available to supplement this one: (@link #processPublicSymbols()}
* and {@link #processNonPublicOrGlobalSymbols()}. * and {@link #processNonPublicOrGlobalSymbols()}
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon issue processing the request * @throws PdbException upon issue processing the request
*/ */
@ -1164,7 +1158,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
setMonitorMessage("PDB: Applying global symbols..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying global symbols...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
@ -1184,7 +1179,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
/** /**
* Process global typdef symbols. * Process global typdef symbols
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon issue processing the request * @throws PdbException upon issue processing the request
*/ */
@ -1202,7 +1197,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
setMonitorMessage("PDB: Applying typedefs..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying typedefs...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
@ -1223,7 +1219,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
/** /**
* Processing non-public, non-global symbols. User should not then call * Processing non-public, non-global symbols. User should not then call
* {@link #processAllSymbols()}; but has these other methods available to supplement this one: * {@link #processAllSymbols()}; but has these other methods available to supplement this one:
* {@link #processGlobalSymbolsNoTypedefs()} and (@link #processPublicSymbols()}. * {@link #processGlobalSymbolsNoTypedefs()} and (@link #processPublicSymbols()}
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
* @throws PdbException upon issue processing the request * @throws PdbException upon issue processing the request
*/ */
@ -1239,6 +1235,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
TaskMonitor monitor = getMonitor();
Set<Long> offsetsRemaining = symbolGroup.getOffsets(); Set<Long> offsetsRemaining = symbolGroup.getOffsets();
for (long off : debugInfo.getPublicSymbolInformation() for (long off : debugInfo.getPublicSymbolInformation()
.getModifiedHashRecordSymbolOffsets()) { .getModifiedHashRecordSymbolOffsets()) {
@ -1251,7 +1248,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
offsetsRemaining.remove(off); offsetsRemaining.remove(off);
} }
setMonitorMessage( monitor.setMessage(
"PDB: Applying " + offsetsRemaining.size() + " other symbol components..."); "PDB: Applying " + offsetsRemaining.size() + " other symbol components...");
monitor.initialize(offsetsRemaining.size()); monitor.initialize(offsetsRemaining.size());
//getCategoryUtils().setModuleTypedefsCategory(null); //getCategoryUtils().setModuleTypedefsCategory(null);
@ -1275,7 +1272,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
if (debugInfo != null) { if (debugInfo != null) {
int num = 1; int num = 1;
for (AbstractModuleInformation module : debugInfo.getModuleInformationList()) { for (ModuleInformation module : debugInfo.getModuleInformationList()) {
if (isLinkerModule(module.getModuleName())) { if (isLinkerModule(module.getModuleName())) {
return num; return num;
} }
@ -1300,12 +1297,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
return false; return false;
} }
setMonitorMessage("PDB: Applying " + symbolGroup.size() + " linker symbol components..."); TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying " + symbolGroup.size() + " linker symbol components...");
monitor.initialize(symbolGroup.size()); monitor.initialize(symbolGroup.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
checkCanceled(); monitor.checkCanceled();
pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek()); pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek());
procSym(iter); procSym(iter);
monitor.incrementProgress(1); monitor.incrementProgress(1);
@ -1340,12 +1338,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber); SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber);
if (symbolGroup != null) { if (symbolGroup != null) {
getMonitor().initialize(symbolGroup.size()); TaskMonitor monitor = getMonitor();
monitor.initialize(symbolGroup.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
int numCompileSymbols = 0; int numCompileSymbols = 0;
int compileSymbolNumForCoffSymbols = -1; int compileSymbolNumForCoffSymbols = -1;
while (iter.hasNext()) { while (iter.hasNext()) {
checkCanceled(); monitor.checkCanceled();
AbstractMsSymbol symbol = iter.next(); AbstractMsSymbol symbol = iter.next();
getPdbApplicatorMetrics().witnessLinkerSymbolType(symbol); getPdbApplicatorMetrics().witnessLinkerSymbolType(symbol);
if (symbol instanceof PeCoffSectionMsSymbol) { if (symbol instanceof PeCoffSectionMsSymbol) {
@ -1396,6 +1395,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
int totalCount = 0; int totalCount = 0;
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
for (int index = 1; index <= num; index++) { for (int index = 1; index <= num; index++) {
monitor.checkCanceled(); monitor.checkCanceled();
if (index == linkerModuleNumber) { if (index == linkerModuleNumber) {
@ -1407,7 +1407,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
totalCount += symbolGroup.size(); totalCount += symbolGroup.size();
} }
setMonitorMessage("PDB: Processing module thunks..."); monitor.setMessage("PDB: Processing module thunks...");
monitor.initialize(totalCount); monitor.initialize(totalCount);
// Process symbols list for each module // Process symbols list for each module
@ -1475,8 +1475,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void defineClasses() throws CancelledException { private void defineClasses() throws CancelledException {
// create namespace and classes in an ordered fashion use tree map // create namespace and classes in an ordered fashion use tree map
TaskMonitor monitor = getMonitor();
monitor.initialize(isClassByNamespace.size()); monitor.initialize(isClassByNamespace.size());
setMonitorMessage("PDB: Defining classes..."); monitor.setMessage("PDB: Defining classes...");
for (Map.Entry<SymbolPath, Boolean> entry : isClassByNamespace.entrySet()) { for (Map.Entry<SymbolPath, Boolean> entry : isClassByNamespace.entrySet()) {
monitor.checkCanceled(); monitor.checkCanceled();
SymbolPath path = entry.getKey(); SymbolPath path = entry.getKey();

View file

@ -31,11 +31,11 @@ public class NestedTypeApplier extends MsTypeApplier {
private MsTypeApplier nestedTypeDefinitionApplier = null; private MsTypeApplier nestedTypeDefinitionApplier = null;
/** /**
* Constructor for nested type applier. * Constructor for nested type applier
* @param applicator {@link DefaultPdbApplicator} for which this class is working. * @param applicator {@link DefaultPdbApplicator} for which this class is working
* @param msType {@link AbstractNestedTypeMsType} or {@link AbstractNestedTypeExtMsType} to * @param msType {@link AbstractNestedTypeMsType} or {@link AbstractNestedTypeExtMsType} to
* process. * process
* @throws IllegalArgumentException Upon invalid arguments. * @throws IllegalArgumentException upon invalid arguments
*/ */
public NestedTypeApplier(DefaultPdbApplicator applicator, AbstractMsType msType) public NestedTypeApplier(DefaultPdbApplicator applicator, AbstractMsType msType)
throws IllegalArgumentException { throws IllegalArgumentException {
@ -51,8 +51,8 @@ public class NestedTypeApplier extends MsTypeApplier {
} }
/** /**
* Returns the name of this nested type. * Returns the name of this nested type
* @return Name of the nested type. * @return name of the nested type
*/ */
String getTypeName() { String getTypeName() {
if (nestedTypeDefinitionApplier == null) { if (nestedTypeDefinitionApplier == null) {
@ -62,8 +62,8 @@ public class NestedTypeApplier extends MsTypeApplier {
} }
/** /**
* Returns the nested (member?) name for this nested type. * Returns the nested (member?) name for this nested type
* @return (Member?) Name for the nested type. * @return (member?) name for the nested type
*/ */
String getMemberName() { String getMemberName() {
if (nestedTypeDefinitionApplier == null) { if (nestedTypeDefinitionApplier == null) {
@ -87,8 +87,8 @@ public class NestedTypeApplier extends MsTypeApplier {
} }
/** /**
* Indicates if there are attributes. Returns false if not "applied" yet. * Indicates if there are attributes. Returns false if not "applied" yet
* @return [@code true} if there are attributes. * @return {@code true} if there are attributes
*/ */
boolean hasAttributes() { boolean hasAttributes() {
if (nestedTypeDefinitionApplier == null) { if (nestedTypeDefinitionApplier == null) {
@ -101,8 +101,8 @@ public class NestedTypeApplier extends MsTypeApplier {
} }
/** /**
* Returns the attributes if they exist. * Returns the attributes if they exist
* @return the attributes or null if they do not exist. * @return the attributes or null if they do not exist
*/ */
ClassFieldMsAttributes getAttributes() { ClassFieldMsAttributes getAttributes() {
AbstractMsType type = nestedTypeDefinitionApplier.getMsType(); AbstractMsType type = nestedTypeDefinitionApplier.getMsType();

View file

@ -34,19 +34,19 @@ import ghidra.util.exception.CancelledException;
public interface PdbApplicator { public interface PdbApplicator {
/** /**
* Returns the {@link AbstractPdb} being analyzed. * Returns the {@link AbstractPdb} being analyzed
* @return {@link AbstractPdb} being analyzed. * @return {@link AbstractPdb} being analyzed
*/ */
public AbstractPdb getPdb(); public AbstractPdb getPdb();
/** /**
* Returns the {@link Program} for which this analyzer is working. * Returns the {@link Program} for which this analyzer is working
* @return {@link Program} for which this analyzer is working. * @return {@link Program} for which this analyzer is working
*/ */
Program getProgram(); Program getProgram();
/** /**
* Returns the original image base value from the PE Header. * Returns the original image base value from the PE Header
* @return the original image base for the binary * @return the original image base for the binary
*/ */
public long getOriginalImageBase(); public long getOriginalImageBase();
@ -60,7 +60,7 @@ public interface PdbApplicator {
/** /**
* Returns the compile symbol seen in the "Linker" module. Should be one of * Returns the compile symbol seen in the "Linker" module. Should be one of
* {@link Compile3MsSymbol} or {@link AbstractCompile2MsSymbol}. * {@link Compile3MsSymbol} or {@link AbstractCompile2MsSymbol}
* @return the compile symbol * @return the compile symbol
* @throws CancelledException upon user cancellation * @throws CancelledException upon user cancellation
*/ */

View file

@ -334,7 +334,8 @@ public class PdbResearch {
static void checkBreak(int recordNumber, MsTypeApplier applier) { static void checkBreak(int recordNumber, MsTypeApplier applier) {
String nn = applier.getMsType().getName(); String nn = applier.getMsType().getName();
if ("std::__1::__map_value_compare<std::__1::basic_string<char>,std::__1::__value_type<std::__1::basic_string<char>,std::__1::basic_string<wchar_t> >,std::__1::less<void>,1>".equals( if ("std::__1::__map_value_compare<std::__1::basic_string<char>,std::__1::__value_type<std::__1::basic_string<char>,std::__1::basic_string<wchar_t> >,std::__1::less<void>,1>"
.equals(
nn)) { nn)) {
doNothingSetBreakPointHere(); doNothingSetBreakPointHere();
} }
@ -424,7 +425,7 @@ public class PdbResearch {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
applicator.setMonitorMessage("PDB: Applying typedefs..."); monitor.setMessage("PDB: Applying typedefs...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
@ -641,7 +642,7 @@ public class PdbResearch {
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation(); PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
applicator.setMonitorMessage( monitor.setMessage(
"PDB: Applying " + offsets.size() + " public symbol components..."); "PDB: Applying " + offsets.size() + " public symbol components...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
@ -676,7 +677,7 @@ public class PdbResearch {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
applicator.setMonitorMessage("PDB: Applying global symbols..."); monitor.setMessage("PDB: Applying global symbols...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();
@ -712,7 +713,7 @@ public class PdbResearch {
} }
totalCount += symbolGroup.size(); totalCount += symbolGroup.size();
} }
applicator.setMonitorMessage( monitor.setMessage(
"PDB: Applying " + totalCount + " module symbol components..."); "PDB: Applying " + totalCount + " module symbol components...");
monitor.initialize(totalCount); monitor.initialize(totalCount);
@ -900,7 +901,8 @@ public class PdbResearch {
// if count is zero for a definition, then, the field list record // if count is zero for a definition, then, the field list record
// number refers to an actual field list. // number refers to an actual field list.
// So... seems we can trust forward reference and ignore count. // So... seems we can trust forward reference and ignore count.
if (compType.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) { if (compType
.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) {
doNothingSetBreakPointHere(); doNothingSetBreakPointHere();
} }
} }
@ -945,7 +947,8 @@ public class PdbResearch {
// the field list record number refers to an actual field // the field list record number refers to an actual field
// list. So... seems we can trust forward reference and // list. So... seems we can trust forward reference and
// ignore count. // ignore count.
if (compType.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) { if (compType
.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) {
doNothingSetBreakPointHere(); doNothingSetBreakPointHere();
} }
} }

View file

@ -68,7 +68,7 @@ public class PdbVbtManager extends VbtManager {
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation(); PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
applicator.setMonitorMessage("PDB: Searching for virtual base table symbols..."); monitor.setMessage("PDB: Searching for virtual base table symbols...");
monitor.initialize(offsets.size()); monitor.initialize(offsets.size());
AbstractMsSymbolIterator iter = symbolGroup.iterator(); AbstractMsSymbolIterator iter = symbolGroup.iterator();

View file

@ -144,11 +144,11 @@ class LoadPdbTask extends Task {
try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse( try (AbstractPdb pdb = ghidra.app.util.bin.format.pdb2.pdbreader.PdbParser.parse(
pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) { pdbFile.getAbsolutePath(), pdbReaderOptions, monitor)) {
monitor.setMessage("PDB: Parsing " + pdbFile + "..."); monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize(monitor); pdb.deserialize();
DefaultPdbApplicator applicator = DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdbFile.getAbsolutePath(), pdb); new DefaultPdbApplicator(pdb);
applicator.applyTo(program, program.getDataTypeManager(), program.getImageBase(), applicator.applyTo(program, program.getDataTypeManager(), program.getImageBase(),
pdbApplicatorOptions, monitor, log); pdbApplicatorOptions, log);
return true; return true;
} }

View file

@ -33,17 +33,13 @@ public class DummyPdb700 extends Pdb700 {
//============================================================================================== //==============================================================================================
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a basic object. * IMPORTANT: This method is for testing only. It allows us to set a basic object.
* Note: not all values are initialized. Constructor for a dummy PDB used for testing. * Note: not all values are initialized. Constructor for a dummy PDB used for testing
* @param tpiIndexMin int. The IndexMin to set/use for the * @param tpiIndexMin int. The IndexMin to set/use for the {@link TypeProgramInterface}
* {@link AbstractTypeProgramInterface}. * @param tpiIndexMaxExclusive int. MaxIndex+1 to set/use for the {@link TypeProgramInterface}
* @param tpiIndexMaxExclusive int. MaxIndex+1 to set/use for the * @param ipiIndexMin int. The IndexMin to set/use for the {@link TypeProgramInterface}
* {@link AbstractTypeProgramInterface}. * @param ipiIndexMaxExclusive int. MaxIndex+1 to set/use for the {@link TypeProgramInterface}
* @param ipiIndexMin int. The IndexMin to set/use for the * @throws IOException upon file IO seek/read issues
* {@link AbstractTypeProgramInterface}. * @throws PdbException upon unknown value for configuration or error in processing components
* @param ipiIndexMaxExclusive int. MaxIndex+1 to set/use for the
* {@link AbstractTypeProgramInterface}.
* @throws IOException Upon file IO seek/read issues.
* @throws PdbException Upon unknown value for configuration or error in processing components.
*/ */
public DummyPdb700(int tpiIndexMin, int tpiIndexMaxExclusive, int ipiIndexMin, public DummyPdb700(int tpiIndexMin, int tpiIndexMaxExclusive, int ipiIndexMin,
int ipiIndexMaxExclusive) throws IOException, PdbException { int ipiIndexMaxExclusive) throws IOException, PdbException {
@ -58,9 +54,9 @@ public class DummyPdb700 extends Pdb700 {
} }
/** /**
* Set true to make existing debug information available; when set false {@link #getDebugInfo()} * Set @code true} to make existing debug information available; when set false,
* returns null (as though it does not exist) * {@link #getDebugInfo()} returns null (as though it does not exist)
* @param setAvailable true to return actual value; false to have it return null * @param setAvailable {@code true} to return actual value; @code false} to have it return null
*/ */
public void setDebugInfoAvailable(boolean setAvailable) { public void setDebugInfoAvailable(boolean setAvailable) {
debugInfoAvailable = setAvailable; debugInfoAvailable = setAvailable;
@ -73,10 +69,10 @@ public class DummyPdb700 extends Pdb700 {
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a "type" record for a * IMPORTANT: This method is for testing only. It allows us to set a "type" record for a
* particular record number. * particular record number
* @param recordNumber int record number for the "type" AbstractMsType to be inserted. * @param recordNumber record number for the "type" AbstractMsType to be inserted
* @param type AbstractMsType to be inserted. * @param type AbstractMsType to be inserted
* @return boolean true if successful. * @return {@code true} if successful
*/ */
public boolean setTypeRecord(int recordNumber, AbstractMsType type) { public boolean setTypeRecord(int recordNumber, AbstractMsType type) {
return typeProgramInterface.setRecord(recordNumber, type); return typeProgramInterface.setRecord(recordNumber, type);
@ -84,9 +80,9 @@ public class DummyPdb700 extends Pdb700 {
/** /**
* IMPORTANT: This method is for testing only. It allows us to add a "type" record that gets * IMPORTANT: This method is for testing only. It allows us to add a "type" record that gets
* its record number automatically assigned. * its record number automatically assigned
* @param type "type" AbstractMsType to be inserted. * @param type "type" AbstractMsType to be inserted
* @return int record number assigned. * @return record number assigned
*/ */
public int addTypeRecord(AbstractMsType type) { public int addTypeRecord(AbstractMsType type) {
return typeProgramInterface.addRecord(type); return typeProgramInterface.addRecord(type);
@ -94,10 +90,10 @@ public class DummyPdb700 extends Pdb700 {
/** /**
* IMPORTANT: This method is for testing only. It allows us to set a "item" record for a * IMPORTANT: This method is for testing only. It allows us to set a "item" record for a
* particular record number. * particular record number
* @param recordNumber int record number for the "item" AbstractMsType to be inserted. * @param recordNumber record number for the "item" AbstractMsType to be inserted
* @param type AbstractMsType to be inserted. * @param type AbstractMsType to be inserted
* @return boolean true if successful. * @return {@code true} if successful
*/ */
public boolean setItemRecord(int recordNumber, AbstractMsType type) { public boolean setItemRecord(int recordNumber, AbstractMsType type) {
return itemProgramInterface.setRecord(recordNumber, type); return itemProgramInterface.setRecord(recordNumber, type);
@ -105,9 +101,9 @@ public class DummyPdb700 extends Pdb700 {
/** /**
* IMPORTANT: This method is for testing only. It allows us to add a "item" record that gets * IMPORTANT: This method is for testing only. It allows us to add a "item" record that gets
* its record number automatically assigned. * its record number automatically assigned
* @param type "item" AbstractMsType to be inserted. * @param type "item" AbstractMsType to be inserted
* @return int record number assigned. * @return record number assigned
*/ */
public int addItemRecord(AbstractMsType type) { public int addItemRecord(AbstractMsType type) {
return itemProgramInterface.addRecord(type); return itemProgramInterface.addRecord(type);

View file

@ -57,7 +57,7 @@ public class MsfReaderUnitTest extends AbstractGenericTest {
//============================================================================================== //==============================================================================================
/** /**
* @throws IOException Upon file IO issues. * @throws IOException Upon file IO issues
*/ */
@BeforeClass @BeforeClass
public static void setUp() throws IOException { public static void setUp() throws IOException {
@ -90,13 +90,13 @@ public class MsfReaderUnitTest extends AbstractGenericTest {
//============================================================================================== //==============================================================================================
/** /**
* Dumps a number bytes of information from a Stream in the AbstractStreamFile to String. * Dumps a number bytes of information from a Stream in the AbstractStreamFile to String.
* for debug purposes. * for debug purposes
* @param streamFile The AbstractStreamFile to be used. * @param streamFile the AbstractStreamFile to be used
* @param streamNumber The streamNumber of the file to dump. * @param streamNumber the streamNumber of the file to dump
* @param maxOut Maximum number of bytes to dump. * @param maxOut maximum number of bytes to dump
* @return String containing the output. * @return string containing the output
*/ */
public static String dumpStream(AbstractMsf streamFile, int streamNumber, int maxOut) { public static String dumpStream(Msf streamFile, int streamNumber, int maxOut) {
MsfStream stream = streamFile.getStream(streamNumber); MsfStream stream = streamFile.getStream(streamNumber);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("Stream: " + streamNumber + "\n"); builder.append("Stream: " + streamNumber + "\n");
@ -109,7 +109,7 @@ public class MsfReaderUnitTest extends AbstractGenericTest {
//============================================================================================== //==============================================================================================
@Test @Test
public void testStreamFile200Header() { public void testStreamFile200Header() {
try (AbstractMsf streamFile = try (Msf streamFile =
MsfParser.parse(testFileName200, new PdbReaderOptions(), TaskMonitor.DUMMY)) { MsfParser.parse(testFileName200, new PdbReaderOptions(), TaskMonitor.DUMMY)) {
int numStreams = streamFile.getNumStreams(); int numStreams = streamFile.getNumStreams();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@ -127,7 +127,7 @@ public class MsfReaderUnitTest extends AbstractGenericTest {
@Test @Test
public void testStreamFile700Header() { public void testStreamFile700Header() {
try (AbstractMsf streamFile = try (Msf streamFile =
MsfParser.parse(testFileName700, new PdbReaderOptions(), TaskMonitor.DUMMY)) { MsfParser.parse(testFileName700, new PdbReaderOptions(), TaskMonitor.DUMMY)) {
int numStreams = streamFile.getNumStreams(); int numStreams = streamFile.getNumStreams();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();