mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-3995 - PDB perf: No long load large components, maps, and lists; use
iterators
This commit is contained in:
parent
c225fac124
commit
83ca81140a
47 changed files with 1139 additions and 982 deletions
|
@ -15,13 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package pdbquery;
|
package pdbquery;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
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;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.PrimitiveMsType;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.PrimitiveMsType;
|
||||||
|
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -184,9 +183,10 @@ public class PdbQuery {
|
||||||
* @param pdb the PDB to search
|
* @param pdb the PDB to search
|
||||||
* @param searchString the search string
|
* @param searchString the search string
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon issue creating an iterator
|
||||||
*/
|
*/
|
||||||
public static void searchSymbols(GhidraScript script, AbstractPdb pdb, String searchString)
|
public static void searchSymbols(GhidraScript script, AbstractPdb pdb, String searchString)
|
||||||
throws CancelledException {
|
throws CancelledException, PdbException {
|
||||||
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
|
@ -198,41 +198,26 @@ public class PdbQuery {
|
||||||
|
|
||||||
int numModules = debugInfo.getNumModules();
|
int numModules = debugInfo.getNumModules();
|
||||||
TaskMonitor monitor = script.getMonitor();
|
TaskMonitor monitor = script.getMonitor();
|
||||||
int numSymbols = 0;
|
|
||||||
for (int module = 0; module <= numModules; module++) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
try {
|
|
||||||
Map<Long, AbstractMsSymbol> symbols = debugInfo.getModuleSymbolsByOffset(module);
|
|
||||||
numSymbols += symbols.size();
|
|
||||||
}
|
|
||||||
catch (PdbException e) {
|
|
||||||
// just skip the module... logging this in the next loop.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor.initialize(numSymbols);
|
monitor.initialize(numModules);
|
||||||
println(script, "Searching " + numSymbols + " PDB symbol components...");
|
println(script, "Searching " + numModules + "PDB modules' symbol components...");
|
||||||
for (int module = 0; module <= numModules; module++) {
|
for (int module = 0; module <= numModules; module++) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
try {
|
SymbolGroup symbolGroup = new SymbolGroup(pdb, module);
|
||||||
Map<Long, AbstractMsSymbol> symbols = debugInfo.getModuleSymbolsByOffset(module);
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
numSymbols += symbols.size();
|
while (iter.hasNext()) {
|
||||||
for (Map.Entry<Long, AbstractMsSymbol> entry : symbols.entrySet()) {
|
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
AbstractMsSymbol symbol = entry.getValue();
|
AbstractMsSymbol symbol = iter.next();
|
||||||
String symbolString = symbol.toString();
|
String symbolString = symbol.toString();
|
||||||
if (symbolString.contains(searchString)) {
|
if (symbolString.contains(searchString)) {
|
||||||
results.append("Module " + module + ", Offset " + entry.getKey() + ":\n");
|
results.append(
|
||||||
|
"Module " + module + ", Offset " + iter.getCurrentOffset() + ":\n");
|
||||||
results.append(symbolString);
|
results.append(symbolString);
|
||||||
results.append('\n');
|
results.append('\n');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (PdbException e) {
|
|
||||||
Msg.debug(PdbQuery.class, "Skipping module " + module + " due to exception.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println(script, results.toString());
|
println(script, results.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
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);
|
debugInfo.initialize(true);
|
||||||
}
|
}
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
throw new AssertException(e); // unexpected
|
throw new AssertException(e); // unexpected
|
||||||
|
@ -328,9 +328,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
Class<T> typeClass) {
|
Class<T> typeClass) {
|
||||||
recordNumber = fixupTypeIndex(recordNumber, typeClass);
|
recordNumber = fixupTypeIndex(recordNumber, typeClass);
|
||||||
AbstractMsType msType =
|
AbstractMsType msType =
|
||||||
getTPI(recordNumber.getCategory()).getRecord(recordNumber.getNumber());
|
getTPI(recordNumber.getCategory()).getRandomAccessRecord(recordNumber.getNumber());
|
||||||
// AbstractMsType msType =
|
|
||||||
// getTPI(recordNumber.getCategory()).getRandomAccessRecord(recordNumber.getNumber());
|
|
||||||
if (!typeClass.isInstance(msType)) {
|
if (!typeClass.isInstance(msType)) {
|
||||||
if (!recordNumber.isNoType()) {
|
if (!recordNumber.isNoType()) {
|
||||||
PdbLog.logGetTypeClassMismatch(msType, typeClass);
|
PdbLog.logGetTypeClassMismatch(msType, typeClass);
|
||||||
|
@ -505,7 +503,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
|
|
||||||
typeProgramInterface = tpiParser.parse(this);
|
typeProgramInterface = tpiParser.parse(this);
|
||||||
if (typeProgramInterface != null) {
|
if (typeProgramInterface != null) {
|
||||||
typeProgramInterface.deserialize();
|
typeProgramInterface.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ipiStreamHasNoName = ItemProgramInterfaceParser.hackCheckNoNameForStream(nameTable);
|
boolean ipiStreamHasNoName = ItemProgramInterfaceParser.hackCheckNoNameForStream(nameTable);
|
||||||
|
@ -514,7 +512,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
ItemProgramInterfaceParser ipiParser = new ItemProgramInterfaceParser();
|
ItemProgramInterfaceParser ipiParser = new ItemProgramInterfaceParser();
|
||||||
itemProgramInterface = ipiParser.parse(this);
|
itemProgramInterface = ipiParser.parse(this);
|
||||||
if (itemProgramInterface != null) {
|
if (itemProgramInterface != null) {
|
||||||
itemProgramInterface.deserialize();
|
itemProgramInterface.initialize();
|
||||||
}
|
}
|
||||||
//processDependencyIndexPairList();
|
//processDependencyIndexPairList();
|
||||||
//dumpDependencyGraph();
|
//dumpDependencyGraph();
|
||||||
|
@ -522,7 +520,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
|
|
||||||
parseDBI();
|
parseDBI();
|
||||||
if (debugInfo != null) {
|
if (debugInfo != null) {
|
||||||
debugInfo.deserialize(false);
|
debugInfo.initialize(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
substreamsDeserialized = true;
|
substreamsDeserialized = true;
|
||||||
|
|
|
@ -19,7 +19,8 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,25 +38,31 @@ public abstract class AbstractSymbolInformation {
|
||||||
|
|
||||||
public static final int GSI70 = 0xeffe0000 + 19990810; // 0xf12f091a = -248575718
|
public static final int GSI70 = 0xeffe0000 + 19990810; // 0xf12f091a = -248575718
|
||||||
|
|
||||||
|
public static final int HASH_PRE70_HEADER_LENGTH = 0;
|
||||||
|
public static final int HASH_70_HEADER_LENGTH = 16;
|
||||||
|
public static final int HASH_HEADER_MIN_READ_LENGTH =
|
||||||
|
Integer.max(HASH_PRE70_HEADER_LENGTH, HASH_70_HEADER_LENGTH);
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Internals
|
// Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
protected AbstractPdb pdb;
|
protected AbstractPdb pdb;
|
||||||
protected int numHashRecords;
|
protected int streamNumber;
|
||||||
protected int numExtraBytes;
|
|
||||||
protected int hashRecordsBitMapLength;
|
|
||||||
|
|
||||||
|
protected int symbolHashLength;
|
||||||
|
protected int symbolHashOffset;
|
||||||
|
|
||||||
|
protected int hashHeaderLength;
|
||||||
protected int headerSignature;
|
protected int headerSignature;
|
||||||
protected int versionNumber;
|
protected int versionNumber;
|
||||||
protected int hashRecordsLength;
|
protected int hashRecordsLength;
|
||||||
protected int bucketsLength;
|
protected int bucketsLength;
|
||||||
|
protected int hashRecordsOffset;
|
||||||
|
protected int bucketsOffset;
|
||||||
|
|
||||||
// These are read from "buckets."
|
protected int numHashRecords;
|
||||||
protected List<Integer> hashBucketOffsets = new ArrayList<>();
|
protected int numExtraBytes;
|
||||||
protected Set<SymbolHashRecord> hashRecords = new TreeSet<>();
|
protected int hashRecordsBitMapLength;
|
||||||
protected List<Long> modifiedHashRecordSymbolOffsets = new ArrayList<>();
|
|
||||||
|
|
||||||
protected List<AbstractMsSymbol> symbols = new ArrayList<>();
|
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// API
|
// API
|
||||||
|
@ -63,41 +70,84 @@ public abstract class AbstractSymbolInformation {
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @param streamNumber the stream number containing the symbol information
|
||||||
*/
|
*/
|
||||||
public AbstractSymbolInformation(AbstractPdb pdbIn) {
|
public AbstractSymbolInformation(AbstractPdb pdbIn, int streamNumber) {
|
||||||
pdb = pdbIn;
|
pdb = pdbIn;
|
||||||
}
|
this.streamNumber = streamNumber;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of symbols for this {@link AbstractSymbolInformation}
|
|
||||||
* @return the symbols
|
|
||||||
*/
|
|
||||||
public List<AbstractMsSymbol> getSymbols() {
|
|
||||||
return symbols;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public List<Long> getModifiedHashRecordSymbolOffsets() {
|
public List<Long> getModifiedHashRecordSymbolOffsets() throws CancelledException, PdbException {
|
||||||
return modifiedHashRecordSymbolOffsets;
|
return generateModifiedSymbolOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Package-Protected Internals
|
// Package-Protected Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/**
|
/**
|
||||||
* Deserialize the {@link AbstractSymbolInformation} from the appropriate stream in the Pdb
|
* Parses and returns the hash bucket offsets
|
||||||
* @param streamNumber the stream number containing the information to deserialize
|
* @return the offsets
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
List<Integer> getHashBucketOffsets() throws CancelledException, PdbException {
|
||||||
|
try {
|
||||||
|
PdbByteReader reader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, bucketsOffset, bucketsLength);
|
||||||
|
if (headerSignature == HEADER_SIGNATURE) {
|
||||||
|
return deserializedCompressedHashBuckets(reader);
|
||||||
|
}
|
||||||
|
return deserializedHashBuckets(reader);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Msg.error(this, String.format(
|
||||||
|
"PDB: Error creating hash buckets while reading stream %d offset %d and length %d",
|
||||||
|
streamNumber, bucketsOffset, bucketsLength));
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses and returns the hash records
|
||||||
|
* @return the hash records
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
Set<SymbolHashRecord> getHashRecords() throws CancelledException, PdbException {
|
||||||
|
try {
|
||||||
|
PdbByteReader reader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, hashRecordsOffset, hashRecordsLength);
|
||||||
|
return deserializeHashRecords(reader);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Msg.error(this, String.format(
|
||||||
|
"PDB: Error creating hash records while reading stream %d offset %d and length %d",
|
||||||
|
streamNumber, hashRecordsOffset, hashRecordsLength));
|
||||||
|
return new TreeSet<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize basic {@link AbstractSymbolInformation} from the appropriate stream in the Pdb
|
||||||
|
* so that later queries can be made
|
||||||
* @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)
|
abstract void initialize() throws IOException, PdbException, CancelledException;
|
||||||
throws IOException, PdbException, CancelledException {
|
|
||||||
|
/**
|
||||||
|
* Initializes values such as offset, lengths, and numbers
|
||||||
|
*/
|
||||||
|
void initializeValues() {
|
||||||
if (pdb.hasMinimalDebugInfo()) {
|
if (pdb.hasMinimalDebugInfo()) {
|
||||||
hashRecordsBitMapLength = 0x8000;
|
hashRecordsBitMapLength = 0x8000;
|
||||||
numExtraBytes = 0; // I believe;
|
numExtraBytes = 0; // I believe;
|
||||||
|
@ -113,10 +163,11 @@ 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 issue reading PDB or upon 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
|
||||||
*/
|
*/
|
||||||
void dump(Writer writer) throws IOException, CancelledException {
|
void dump(Writer writer) throws IOException, CancelledException, PdbException {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("AbstractSymbolInformation-----------------------------------\n");
|
builder.append("AbstractSymbolInformation-----------------------------------\n");
|
||||||
dumpHashHeader(builder);
|
dumpHashHeader(builder);
|
||||||
|
@ -160,35 +211,34 @@ 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
|
||||||
* @throws PdbException upon PDB corruption
|
* @return the offsets
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
protected void generateSymbolsList()
|
protected List<Long> generateModifiedSymbolOffsets() throws PdbException, CancelledException {
|
||||||
throws PdbException, CancelledException {
|
List<Long> modifiedHashRecordSymbolOffsets = new ArrayList<>();
|
||||||
symbols = new ArrayList<>();
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
return;
|
return modifiedHashRecordSymbolOffsets;
|
||||||
}
|
}
|
||||||
Map<Long, AbstractMsSymbol> symbolsByOffset = debugInfo.getSymbolsByOffset();
|
Set<SymbolHashRecord> hashRecords = getHashRecords();
|
||||||
for (SymbolHashRecord record : hashRecords) {
|
for (SymbolHashRecord record : hashRecords) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
long offset = record.getOffset() - 2; // Modified offset
|
long offset = record.getOffset() - 2; // Modified offset
|
||||||
AbstractMsSymbol symbol = symbolsByOffset.get(offset);
|
|
||||||
modifiedHashRecordSymbolOffsets.add(offset);
|
modifiedHashRecordSymbolOffsets.add(offset);
|
||||||
if (symbol == null) {
|
|
||||||
throw new PdbException("PDB corrupted");
|
|
||||||
}
|
|
||||||
symbols.add(symbol);
|
|
||||||
}
|
}
|
||||||
|
return modifiedHashRecordSymbolOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 PdbException upon not enough data left to parse
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
protected void dumpHashRecords(StringBuilder builder) throws CancelledException {
|
protected void dumpHashRecords(StringBuilder builder)
|
||||||
|
throws CancelledException, PdbException {
|
||||||
|
Set<SymbolHashRecord> hashRecords = getHashRecords();
|
||||||
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) {
|
||||||
|
@ -199,31 +249,12 @@ public abstract class AbstractSymbolInformation {
|
||||||
builder.append("\nEnd HashRecords---------------------------------------------\n");
|
builder.append("\nEnd HashRecords---------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected void deserializeHashHeader() throws PdbException, CancelledException, IOException {
|
||||||
* Deserializes the hash table for the symbols
|
MsfStream stream = pdb.getMsf().getStream(streamNumber);
|
||||||
* @param reader {@link PdbByteReader} containing the data buffer to process
|
PdbByteReader reader =
|
||||||
* @throws PdbException upon not enough data left to parse
|
pdb.getReaderForStreamNumber(streamNumber, symbolHashOffset,
|
||||||
* @throws CancelledException upon user cancellation
|
HASH_HEADER_MIN_READ_LENGTH);
|
||||||
*/
|
deserializeHashHeader(reader, stream.getLength());
|
||||||
protected void deserializeHashTable(PdbByteReader reader)
|
|
||||||
throws PdbException, CancelledException {
|
|
||||||
|
|
||||||
deserializeHashHeader(reader);
|
|
||||||
|
|
||||||
if (headerSignature == HEADER_SIGNATURE) {
|
|
||||||
switch (versionNumber) {
|
|
||||||
case GSI70:
|
|
||||||
deserializeGsi70HashTable(reader);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new PdbException("Unknown GSI Version Number");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reader.reset(); // There was no header
|
|
||||||
deserializeGsiPre70HashTable(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -231,81 +262,28 @@ public abstract class AbstractSymbolInformation {
|
||||||
* @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, int streamLength) throws PdbException {
|
||||||
headerSignature = reader.parseInt();
|
headerSignature = reader.parseInt();
|
||||||
|
if (headerSignature == HEADER_SIGNATURE) {
|
||||||
|
hashHeaderLength = HASH_70_HEADER_LENGTH;
|
||||||
versionNumber = reader.parseInt();
|
versionNumber = reader.parseInt();
|
||||||
hashRecordsLength = reader.parseInt();
|
hashRecordsLength = reader.parseInt();
|
||||||
bucketsLength = reader.parseInt();
|
bucketsLength = reader.parseInt();
|
||||||
|
hashRecordsOffset = symbolHashOffset + reader.getIndex();
|
||||||
|
bucketsOffset = hashRecordsOffset + hashRecordsLength;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
/**
|
hashHeaderLength = HASH_PRE70_HEADER_LENGTH;
|
||||||
* Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI versions
|
reader.reset(); // There was no header
|
||||||
* prior to 7.00 specification
|
// Calculate the values
|
||||||
* @param reader {@link PdbByteReader} containing the data buffer to process
|
bucketsLength = 4 * (numHashRecords + 1);
|
||||||
* @throws PdbException upon unexpected fields
|
if (streamLength < bucketsLength) {
|
||||||
* @throws CancelledException upon user cancellation
|
throw new PdbException("Not enough data for symbol hash buckets.");
|
||||||
*/
|
|
||||||
private void deserializeGsiPre70HashTable(PdbByteReader reader)
|
|
||||||
throws PdbException, CancelledException {
|
|
||||||
|
|
||||||
int numBucketsBytes = 4 * (numHashRecords + 1);
|
|
||||||
if (reader.numRemaining() < numBucketsBytes) {
|
|
||||||
throw new PdbException("Not enough data for GSI");
|
|
||||||
}
|
}
|
||||||
int numRecordsBytes = (reader.numRemaining() - numBucketsBytes);
|
hashRecordsLength = streamLength - bucketsLength;
|
||||||
|
hashRecordsOffset = symbolHashOffset + 0;
|
||||||
PdbByteReader hashRecordsReader = reader.getSubPdbByteReader(numRecordsBytes);
|
bucketsOffset = hashRecordsOffset + hashRecordsLength;
|
||||||
PdbByteReader bucketsReader = reader.getSubPdbByteReader(numBucketsBytes);
|
|
||||||
if (reader.hasMore()) {
|
|
||||||
throw new PdbException("Unexpected extra information at and of GSI stream");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashBucketOffsets = new ArrayList<>();
|
|
||||||
while (bucketsReader.hasMore()) {
|
|
||||||
pdb.checkCancelled();
|
|
||||||
hashBucketOffsets.add(bucketsReader.parseInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: each offset value is into an array of structures that are 12 bytes in length, but
|
|
||||||
// whose on-disk size is 8 bytes. These are the structures in the hashRecordsReader. So
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
deserializeHashRecords(hashRecordsReader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserialize the body of the {@link AbstractSymbolInformation} according to the GSI 7.00
|
|
||||||
* specification
|
|
||||||
* @param reader {@link PdbByteReader} containing the data buffer to process
|
|
||||||
* @throws PdbException upon unexpected fields
|
|
||||||
* @throws CancelledException upon user cancellation
|
|
||||||
*/
|
|
||||||
private void deserializeGsi70HashTable(PdbByteReader reader)
|
|
||||||
throws PdbException, CancelledException {
|
|
||||||
|
|
||||||
if (reader.numRemaining() != hashRecordsLength + bucketsLength) {
|
|
||||||
throw new PdbException("Data count mismatch in GSI stream");
|
|
||||||
}
|
|
||||||
if (hashRecordsLength == 0 || bucketsLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PdbByteReader hashRecordsReader = reader.getSubPdbByteReader(hashRecordsLength);
|
|
||||||
PdbByteReader bucketsReader = reader.getSubPdbByteReader(bucketsLength);
|
|
||||||
|
|
||||||
deserializedCompressedHashBuckets(bucketsReader);
|
|
||||||
|
|
||||||
// int i = 0;
|
|
||||||
// for (int x : hashBucketOffsets) {
|
|
||||||
// System.out.println(String.format("0x%04x: 0x%08x", i++, x));
|
|
||||||
// }
|
|
||||||
// Note: each offset value is into an array of structures that are 12 bytes in length, but
|
|
||||||
// whose on-disk size is 8 bytes. These are the structures in the hashRecordsReader. So
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
deserializeHashRecords(hashRecordsReader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -316,9 +294,11 @@ public abstract class AbstractSymbolInformation {
|
||||||
* @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)
|
private List<Integer> deserializedCompressedHashBuckets(PdbByteReader reader)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
|
|
||||||
|
List<Integer> hashBucketOffsets = new ArrayList<>();
|
||||||
|
|
||||||
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);
|
||||||
|
@ -349,24 +329,154 @@ public abstract class AbstractSymbolInformation {
|
||||||
throw new PdbException("Compressed GSI Hash Buckets corrupt");
|
throw new PdbException("Compressed GSI Hash Buckets corrupt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return hashBucketOffsets;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes the hash records
|
* Deserializes a normal/non-compressed set of hash buckets 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
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
private void deserializeHashRecords(PdbByteReader reader)
|
private List<Integer> deserializedHashBuckets(PdbByteReader reader)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
hashRecords = new TreeSet<>();
|
List<Integer> hashBucketOffsets = new ArrayList<>();
|
||||||
|
while (reader.hasMore()) {
|
||||||
|
pdb.checkCancelled();
|
||||||
|
hashBucketOffsets.add(reader.parseInt());
|
||||||
|
}
|
||||||
|
return hashBucketOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following note is from previous incantation of this code (before changing to on-demand
|
||||||
|
// reading of components). It still might be applicable here or elsewhere.
|
||||||
|
//
|
||||||
|
// Note: each offset value is into an array of structures that are 12 bytes in length, but
|
||||||
|
// whose on-disk size is 8 bytes. These are the structures in the hashRecordsReader. So
|
||||||
|
// 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.
|
||||||
|
/**
|
||||||
|
* Deserializes and returns the hash records
|
||||||
|
* @param reader {@link PdbByteReader} containing the data buffer to process
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
private Set<SymbolHashRecord> deserializeHashRecords(PdbByteReader reader)
|
||||||
|
throws PdbException, CancelledException {
|
||||||
|
Set<SymbolHashRecord> hashRecords = new TreeSet<>();
|
||||||
while (reader.hasMore()) {
|
while (reader.hasMore()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
SymbolHashRecord record = new SymbolHashRecord();
|
SymbolHashRecord record = new SymbolHashRecord();
|
||||||
record.parse(reader);
|
record.parse(reader);
|
||||||
hashRecords.add(record);
|
hashRecords.add(record);
|
||||||
}
|
}
|
||||||
|
return hashRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE Iterator below is not good at this point in time, as we had been working with
|
||||||
|
// a TreeSet, which is ordered. The iterator below is acting on hash bins which are
|
||||||
|
// as random as the hash key makes them. TODO: consider other options. For now going back
|
||||||
|
// to creating the whole TreeSet.
|
||||||
|
|
||||||
|
// public ModifiedOffsetIterator iterator() {
|
||||||
|
// return new ModifiedOffsetIterator();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //==============================================================================================
|
||||||
|
// /**
|
||||||
|
// * Iterator for {@link SymbolGroup} that iterates through {@link AbstractMsSymbol
|
||||||
|
// * AbstractMsSymbols}
|
||||||
|
// */
|
||||||
|
// public class ModifiedOffsetIterator implements Iterator<Long> {
|
||||||
|
//
|
||||||
|
// private int streamOffset;
|
||||||
|
// private int streamOffsetLimit;
|
||||||
|
// private float factor;
|
||||||
|
//
|
||||||
|
// private Long value;
|
||||||
|
//
|
||||||
|
// public ModifiedOffsetIterator() {
|
||||||
|
// initGet();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean hasNext() {
|
||||||
|
// return (value != null);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Peeks at and returns the next symbol without incrementing to the next. If none are
|
||||||
|
// * left, then throws NoSuchElementException and reinitializes the state for a new
|
||||||
|
// * iteration.
|
||||||
|
// * @see #initGet()
|
||||||
|
// * @return the next symbol
|
||||||
|
// * @throws NoSuchElementException if there are no more elements
|
||||||
|
// */
|
||||||
|
// public Long peek() throws NoSuchElementException {
|
||||||
|
// if (value == null) {
|
||||||
|
// throw new NoSuchElementException();
|
||||||
|
// }
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public Long next() {
|
||||||
|
// if (value == null) {
|
||||||
|
// throw new NoSuchElementException();
|
||||||
|
// }
|
||||||
|
// Long offer = value;
|
||||||
|
// value = retrieveNext();
|
||||||
|
// return offer;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private Long retrieveNext() {
|
||||||
|
// if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// if (streamOffset >= streamOffsetLimit) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, streamOffset,
|
||||||
|
// SymbolHashRecord.RECORD_SIZE);
|
||||||
|
// SymbolHashRecord record = new SymbolHashRecord();
|
||||||
|
// record.parse(reader);
|
||||||
|
// streamOffset += SymbolHashRecord.RECORD_SIZE;
|
||||||
|
// // Minus 2 for the "modified" offset points to the length field in the "other"
|
||||||
|
// // stream
|
||||||
|
// return record.getOffset() - 2;
|
||||||
|
// }
|
||||||
|
// catch (CancelledException | PdbException | IOException e) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Initialized the mechanism for requesting the symbols in sequence.
|
||||||
|
// * @see #hasNext()
|
||||||
|
// */
|
||||||
|
// void initGet() {
|
||||||
|
// if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
// streamOffset = 0;
|
||||||
|
// streamOffsetLimit = 0;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// streamOffset = hashRecordsOffset;
|
||||||
|
// streamOffsetLimit = hashRecordsLength;
|
||||||
|
// value = retrieveNext();
|
||||||
|
// long num = streamOffsetLimit - hashRecordsOffset;
|
||||||
|
// float factor = num <= 0 ? 0.0F : 1.0F / (num);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Returns value from 0 to 100 as a rough percentage of having iterated through all records
|
||||||
|
// * @return the percentage
|
||||||
|
// */
|
||||||
|
// public long getPercentageDone() {
|
||||||
|
// long num = streamOffset - hashRecordsOffset;
|
||||||
|
// return (long) (factor * num);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,17 +66,6 @@ public class DebugData {
|
||||||
private AbstractPdb pdb;
|
private AbstractPdb pdb;
|
||||||
private List<Integer> debugStreams = new ArrayList<>();
|
private List<Integer> debugStreams = new ArrayList<>();
|
||||||
|
|
||||||
private List<FramePointerOmissionRecord> framePointerOmissionData;
|
|
||||||
// private SortedMap<Long, Long> omapToSource;
|
|
||||||
private SortedMap<Long, Long> omapFromSource;
|
|
||||||
private List<ImageSectionHeader> imageSectionHeaders;
|
|
||||||
private List<ImageSectionHeader> imageSectionHeadersOrig;
|
|
||||||
|
|
||||||
private List<ImageFunctionEntry> pData;
|
|
||||||
|
|
||||||
private RvaVaDebugHeader xDataHeader;
|
|
||||||
private PdbByteReader xDataReader;
|
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// API
|
// API
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -92,9 +81,18 @@ 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
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
public List<FramePointerOmissionRecord> getFramePointerOmissionData() {
|
public List<FramePointerOmissionRecord> getFramePointerOmissionData()
|
||||||
return framePointerOmissionData;
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.FRAME_POINTER_OMISSION.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeFramePointerOmissionData(streamNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
|
@ -108,17 +106,74 @@ public class DebugData {
|
||||||
/**
|
/**
|
||||||
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
|
* Returns the OMAP_FROM_SOURCE mapping of RVA to RVA
|
||||||
* @return the omapFromSource or null if does not exist.
|
* @return the omapFromSource or null if does not exist.
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
public SortedMap<Long, Long> getOmapFromSource() {
|
public SortedMap<Long, Long> getOmapFromSource()
|
||||||
return omapFromSource;
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.OMAP_FROM_SOURCE.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeOMap(streamNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link List}<{@link ImageSectionHeader}>
|
* Returns the {@link List}<{@link ImageSectionHeader}>
|
||||||
* @return the imageSectionHeaders or null if does not exist
|
* @return the imageSectionHeaders or null if does not exist
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
public List<ImageSectionHeader> getImageSectionHeaders() {
|
public List<ImageSectionHeader> getImageSectionHeaders()
|
||||||
return imageSectionHeaders;
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.SECTION_HEADER.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeSectionHeaders(streamNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns XData
|
||||||
|
* When this returns a non-null list the OMAP_FROM_SRC should be
|
||||||
|
* used for remapping global symbols
|
||||||
|
* @return the imageSectionHeadersOrig or null if does not exist
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
*/
|
||||||
|
// TODO: just put a return of null Integer for now until figured out.
|
||||||
|
public Integer getXData()
|
||||||
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeXData(streamNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns PData
|
||||||
|
* When this returns a non-null list the OMAP_FROM_SRC should be
|
||||||
|
* used for remapping global symbols
|
||||||
|
* @return the imageSectionHeadersOrig or null if does not exist
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
*/
|
||||||
|
public List<ImageFunctionEntry> getPData()
|
||||||
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializePData(streamNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,9 +181,18 @@ public class DebugData {
|
||||||
* When this returns 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
|
||||||
|
* @throws PdbException PdbException upon error in processing components
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
public List<ImageSectionHeader> getImageSectionHeadersOrig() {
|
public List<ImageSectionHeader> getImageSectionHeadersOrig()
|
||||||
return imageSectionHeadersOrig;
|
throws CancelledException, PdbException, IOException {
|
||||||
|
int streamNum = debugStreams.get(DebugType.SECTION_HEADER_ORIG.getValue());
|
||||||
|
if (streamNum == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deserializeSectionHeaders(streamNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,6 +229,7 @@ public class DebugData {
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void deserialize()
|
public void deserialize()
|
||||||
throws PdbException, CancelledException, IOException {
|
throws PdbException, CancelledException, IOException {
|
||||||
if (debugStreams.isEmpty()) {
|
if (debugStreams.isEmpty()) {
|
||||||
|
@ -178,7 +243,7 @@ public class DebugData {
|
||||||
}
|
}
|
||||||
switch (dbg) {
|
switch (dbg) {
|
||||||
case FRAME_POINTER_OMISSION:
|
case FRAME_POINTER_OMISSION:
|
||||||
deserializeFramePointerOmissionData(streamNum);
|
// framePointerOmissionData = deserializeFramePointerOmissionData(streamNum);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
// TODO: implement.
|
// TODO: implement.
|
||||||
|
@ -190,42 +255,44 @@ public class DebugData {
|
||||||
// omapToSource = deserializeOMap(streamNum);
|
// omapToSource = deserializeOMap(streamNum);
|
||||||
break;
|
break;
|
||||||
case OMAP_FROM_SOURCE:
|
case OMAP_FROM_SOURCE:
|
||||||
omapFromSource = deserializeOMap(streamNum);
|
// omapFromSource = deserializeOMap(streamNum);
|
||||||
break;
|
break;
|
||||||
case SECTION_HEADER:
|
case SECTION_HEADER:
|
||||||
imageSectionHeaders = deserializeSectionHeaders(streamNum);
|
// 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);
|
// DUMMY Integer return value for now
|
||||||
|
// Integer xData = deserializeXData(streamNum);
|
||||||
break;
|
break;
|
||||||
case P_DATA:
|
case P_DATA:
|
||||||
deserializePData(streamNum);
|
// pData = 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);
|
// imageSectionHeadersOrig = deserializeSectionHeaders(streamNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deserializeFramePointerOmissionData(int streamNum)
|
private List<FramePointerOmissionRecord> 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);
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
|
||||||
framePointerOmissionData = new ArrayList<>();
|
List<FramePointerOmissionRecord> fpOmissionData = new ArrayList<>();
|
||||||
while (reader.hasMore()) {
|
while (reader.hasMore()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
FramePointerOmissionRecord framePointerOmissionRecord =
|
FramePointerOmissionRecord framePointerOmissionRecord =
|
||||||
new FramePointerOmissionRecord();
|
new FramePointerOmissionRecord();
|
||||||
framePointerOmissionRecord.parse(reader);
|
framePointerOmissionRecord.parse(reader);
|
||||||
framePointerOmissionData.add(framePointerOmissionRecord);
|
fpOmissionData.add(framePointerOmissionRecord);
|
||||||
}
|
}
|
||||||
|
return fpOmissionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SortedMap<Long, Long> deserializeOMap(int streamNum)
|
private SortedMap<Long, Long> deserializeOMap(int streamNum)
|
||||||
|
@ -259,17 +326,18 @@ public class DebugData {
|
||||||
* 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)
|
// TODO: just put a return of null Integer for now until figured out.
|
||||||
|
private Integer deserializeXData(int streamNum)
|
||||||
throws PdbException, CancelledException, IOException {
|
throws PdbException, CancelledException, IOException {
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
|
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();
|
||||||
xDataHeader = header;
|
|
||||||
header.deserialize(reader);
|
header.deserialize(reader);
|
||||||
//System.out.println(header.dump());
|
//System.out.println(header.dump());
|
||||||
if (header.getHeaderVersion() != 1) {
|
if (header.getHeaderVersion() != 1) {
|
||||||
return; // Silent... TODO: add logging event.
|
return null; // Silent... TODO: add logging event.
|
||||||
}
|
}
|
||||||
long headerLength = header.getHeaderLength();
|
long headerLength = header.getHeaderLength();
|
||||||
long dataLength = header.getDataLength();
|
long dataLength = header.getDataLength();
|
||||||
|
@ -278,25 +346,27 @@ public class DebugData {
|
||||||
}
|
}
|
||||||
reader.setIndex((int) headerLength);
|
reader.setIndex((int) headerLength);
|
||||||
//System.out.println(reader.dump());
|
//System.out.println(reader.dump());
|
||||||
xDataReader = reader.getSubPdbByteReader(reader.numRemaining());
|
PdbByteReader xDataReader = reader.getSubPdbByteReader(reader.numRemaining());
|
||||||
// TODO: This is a partial implementation. We need to figure out more to know
|
// TODO: This is a partial implementation. We need to figure out more to know
|
||||||
// how to deal with it. The only API information regarding the XData is with
|
// how to deal with it. The only API information regarding the XData is with
|
||||||
// regard to processing PData when the "machine" is IA64 or AMD64. The interpretation
|
// regard to processing PData when the "machine" is IA64 or AMD64. The interpretation
|
||||||
// for these machines is not real clear (or a bit of work), and there is no other
|
// for these machines is not real clear (or a bit of work), and there is no other
|
||||||
// interpretation available when the machine is different.
|
// interpretation available when the machine is different.
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is incomplete.
|
// TODO: This is incomplete.
|
||||||
private void deserializePData(int streamNum)
|
private List<ImageFunctionEntry> deserializePData(int streamNum)
|
||||||
throws PdbException, CancelledException, IOException {
|
throws PdbException, CancelledException, IOException {
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNum);
|
||||||
pData = new ArrayList<>();
|
List<ImageFunctionEntry> myPData = new ArrayList<>();
|
||||||
int streamLength = reader.getLimit();
|
int streamLength = reader.getLimit();
|
||||||
RvaVaDebugHeader header = new RvaVaDebugHeader();
|
RvaVaDebugHeader header = new RvaVaDebugHeader();
|
||||||
header.deserialize(reader);
|
header.deserialize(reader);
|
||||||
//System.out.println(header.dump());
|
//System.out.println(header.dump());
|
||||||
if (header.getHeaderVersion() != 1) {
|
if (header.getHeaderVersion() != 1) {
|
||||||
return; // Silent... TODO: add logging event.
|
return myPData; // Silent... TODO: add logging event.
|
||||||
}
|
}
|
||||||
long headerLength = header.getHeaderLength();
|
long headerLength = header.getHeaderLength();
|
||||||
long dataLength = header.getDataLength();
|
long dataLength = header.getDataLength();
|
||||||
|
@ -335,6 +405,7 @@ public class DebugData {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return myPData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -342,12 +413,14 @@ public class DebugData {
|
||||||
* @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
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon error in processing components
|
||||||
*/
|
*/
|
||||||
void dump(Writer writer) throws IOException, CancelledException {
|
void dump(Writer writer) throws IOException, CancelledException, PdbException {
|
||||||
writer.write("DebugData---------------------------------------------------\n");
|
writer.write("DebugData---------------------------------------------------\n");
|
||||||
dumpDebugStreamList(writer);
|
dumpDebugStreamList(writer);
|
||||||
|
|
||||||
writer.write("FramePointerOmissionData------------------------------------\n");
|
writer.write("FramePointerOmissionData------------------------------------\n");
|
||||||
|
List<FramePointerOmissionRecord> framePointerOmissionData = getFramePointerOmissionData();
|
||||||
if (framePointerOmissionData != null) {
|
if (framePointerOmissionData != null) {
|
||||||
for (FramePointerOmissionRecord framePointerOmissionRecord : framePointerOmissionData) {
|
for (FramePointerOmissionRecord framePointerOmissionRecord : framePointerOmissionData) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
|
@ -368,6 +441,7 @@ public class DebugData {
|
||||||
// writer.write("End OmapToSource--------------------------------------------\n");
|
// writer.write("End OmapToSource--------------------------------------------\n");
|
||||||
//
|
//
|
||||||
writer.write("OmapFromSource----------------------------------------------\n");
|
writer.write("OmapFromSource----------------------------------------------\n");
|
||||||
|
SortedMap<Long, Long> omapFromSource = getOmapFromSource();
|
||||||
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()) {
|
||||||
|
@ -379,6 +453,7 @@ public class DebugData {
|
||||||
writer.write("End OmapFromSource------------------------------------------\n");
|
writer.write("End OmapFromSource------------------------------------------\n");
|
||||||
|
|
||||||
writer.write("ImageSectionHeaders-----------------------------------------\n");
|
writer.write("ImageSectionHeaders-----------------------------------------\n");
|
||||||
|
List<ImageSectionHeader> imageSectionHeaders = getImageSectionHeaders();
|
||||||
if (imageSectionHeaders != null) {
|
if (imageSectionHeaders != null) {
|
||||||
int sectionNum = 0;
|
int sectionNum = 0;
|
||||||
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
|
for (ImageSectionHeader imageSectionHeader : imageSectionHeaders) {
|
||||||
|
@ -389,6 +464,7 @@ public class DebugData {
|
||||||
writer.write("End ImageSectionHeaders-------------------------------------\n");
|
writer.write("End ImageSectionHeaders-------------------------------------\n");
|
||||||
|
|
||||||
writer.write("ImageSectionHeadersOrig-------------------------------------\n");
|
writer.write("ImageSectionHeadersOrig-------------------------------------\n");
|
||||||
|
List<ImageSectionHeader> imageSectionHeadersOrig = getImageSectionHeadersOrig();
|
||||||
if (imageSectionHeadersOrig != null) {
|
if (imageSectionHeadersOrig != null) {
|
||||||
int sectionNum = 0;
|
int sectionNum = 0;
|
||||||
for (ImageSectionHeader imageSectionHeader : imageSectionHeadersOrig) {
|
for (ImageSectionHeader imageSectionHeader : imageSectionHeadersOrig) {
|
||||||
|
@ -399,6 +475,7 @@ public class DebugData {
|
||||||
writer.write("End ImageSectionHeadersOrig---------------------------------\n");
|
writer.write("End ImageSectionHeadersOrig---------------------------------\n");
|
||||||
|
|
||||||
writer.write("PData-------------------------------------------------------\n");
|
writer.write("PData-------------------------------------------------------\n");
|
||||||
|
List<ImageFunctionEntry> pData = getPData();
|
||||||
if (pData != null) {
|
if (pData != null) {
|
||||||
for (ImageFunctionEntry entry : pData) {
|
for (ImageFunctionEntry entry : pData) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
|
|
|
@ -15,12 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
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.Msg;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,17 +91,10 @@ class GlobalReferenceIterator implements ParsingIterator<MsSymbolIterator> {
|
||||||
currentGlobalSymbolIterator = null;
|
currentGlobalSymbolIterator = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
Long offset = offsetIterator.next();
|
Long offset = offsetIterator.next();
|
||||||
PdbByteReader reader =
|
currentGlobalSymbolIterator =
|
||||||
pdb.getReaderForStreamNumber(symbolsStreamNumber, offset.intValue(),
|
new MsSymbolIterator(pdb, symbolsStreamNumber, offset.intValue(),
|
||||||
MsfStream.MAX_STREAM_LENGTH);
|
MsfStream.MAX_STREAM_LENGTH);
|
||||||
currentGlobalSymbolIterator = new MsSymbolIterator(pdb, reader);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
Msg.error(this, "Problem seen in find()", e);
|
|
||||||
currentGlobalSymbolIterator = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +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.MsfStream;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,38 +35,42 @@ public class GlobalSymbolInformation extends AbstractSymbolInformation {
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param pdbIn {@link AbstractPdb} that owns the Global Symbol Information to process.
|
* @param pdbIn {@link AbstractPdb} that owns the Global Symbol Information to process.
|
||||||
|
* @param streamNumber the stream number containing the symbol information
|
||||||
*/
|
*/
|
||||||
public GlobalSymbolInformation(AbstractPdb pdbIn) {
|
public GlobalSymbolInformation(AbstractPdb pdbIn, int streamNumber) {
|
||||||
super(pdbIn);
|
super(pdbIn, streamNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize the {@link GlobalSymbolInformation} from the appropriate stream in the Pdb
|
* Deserializes and intializes {@link GlobalSymbolInformation} basic information from the
|
||||||
* @param streamNumber the stream number containing the information to deserialize
|
* appropriate stream in the Pdb so that later queries can be made
|
||||||
* @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)
|
void initialize() throws IOException, PdbException, CancelledException {
|
||||||
throws IOException, PdbException, CancelledException {
|
initializeValues();
|
||||||
super.deserialize(streamNumber);
|
initializeGlobalOffsetsAndLengths();
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
deserializeHashHeader();
|
||||||
deserializeHashTable(reader);
|
}
|
||||||
|
|
||||||
// Organize the information
|
private void initializeGlobalOffsetsAndLengths() {
|
||||||
generateSymbolsList();
|
symbolHashOffset = 0;
|
||||||
|
MsfStream stream = pdb.getMsf().getStream(streamNumber);
|
||||||
|
symbolHashLength = (stream == null) ? 0 : stream.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 issue reading PDBor upon 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
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void dump(Writer writer) throws IOException, CancelledException {
|
void dump(Writer writer) throws IOException, CancelledException, PdbException {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("GlobalSymbolInformation-------------------------------------\n");
|
builder.append("GlobalSymbolInformation-------------------------------------\n");
|
||||||
dumpHashHeader(builder);
|
dumpHashHeader(builder);
|
||||||
|
|
|
@ -126,13 +126,13 @@ public class Module {
|
||||||
* Returns an MsSymbolIterator for the symbols of this module
|
* Returns an MsSymbolIterator for the symbols of this module
|
||||||
* @return the iterator
|
* @return the iterator
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException upon error reading stream
|
||||||
* @throws PdbException upon invalid cvSignature
|
* @throws PdbException upon invalid cvSignature
|
||||||
*/
|
*/
|
||||||
public MsSymbolIterator getSymbolIterator() throws CancelledException, PdbException {
|
public MsSymbolIterator iterator() throws CancelledException, IOException, PdbException {
|
||||||
PdbByteReader symbolsReader = getSymbolsReader();
|
int startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber);
|
||||||
parseSignature(symbolsReader);
|
int lengthSymbols = moduleInformation.getSizeLocalSymbolsDebugInformation();
|
||||||
MsSymbolIterator iterator = new MsSymbolIterator(pdb, symbolsReader);
|
return new MsSymbolIterator(pdb, streamNumber, startingOffset, lengthSymbols);
|
||||||
return iterator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseSignature(PdbByteReader symbolsReader) throws PdbException {
|
private void parseSignature(PdbByteReader symbolsReader) throws PdbException {
|
||||||
|
@ -333,13 +333,14 @@ public class Module {
|
||||||
|
|
||||||
private void dumpSymbols(Writer writer)
|
private void dumpSymbols(Writer writer)
|
||||||
throws IOException, CancelledException, PdbException {
|
throws IOException, CancelledException, PdbException {
|
||||||
writer.write("Symbols-----------------------------------------------------\n");
|
writer.write("Symbols-----------------------------------------------------");
|
||||||
MsSymbolIterator symbolIterator = getSymbolIterator();
|
MsSymbolIterator symbolIter = iterator();
|
||||||
while (symbolIterator.hasNext()) {
|
while (symbolIter.hasNext()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
AbstractMsSymbol symbol = symbolIterator.next();
|
AbstractMsSymbol symbol = symbolIter.next();
|
||||||
|
writer.append("\n------------------------------------------------------------\n");
|
||||||
|
writer.append(String.format("Offset: 0X%08X\n", symbolIter.getCurrentOffset()));
|
||||||
writer.append(symbol.toString());
|
writer.append(symbol.toString());
|
||||||
writer.append("\n");
|
|
||||||
}
|
}
|
||||||
writer.write("End Symbols-------------------------------------------------\n");
|
writer.write("End Symbols-------------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,71 +15,136 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
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.app.util.pdb.pdbapplicator.SymbolGroup;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator for {@link AbstractMsSymbol AbstractMsSymbols} being read from a stream.
|
* Iterator for {@link SymbolGroup} that iterates through {@link AbstractMsSymbol
|
||||||
|
* AbstractMsSymbols}
|
||||||
*/
|
*/
|
||||||
class MsSymbolIterator implements ParsingIterator<AbstractMsSymbol> {
|
public class MsSymbolIterator implements Iterator<AbstractMsSymbol> {
|
||||||
|
|
||||||
private AbstractPdb pdb;
|
private int streamNumber;
|
||||||
private PdbByteReader reader;
|
private int startOffset;
|
||||||
|
private SymbolRecords symbolRecords;
|
||||||
|
private int lengthSymbols;
|
||||||
|
private int nextRetrieveOffset;
|
||||||
|
private int currentOffset;
|
||||||
|
private SymbolRecords.SymLen symLen;
|
||||||
|
|
||||||
private AbstractMsSymbol currentSymbol = null;
|
public MsSymbolIterator(AbstractPdb pdb, int streamNumber, int startOffset, int lengthSymbols) {
|
||||||
|
this.streamNumber = streamNumber;
|
||||||
|
this.startOffset = startOffset;
|
||||||
|
this.lengthSymbols = lengthSymbols;
|
||||||
|
symbolRecords = pdb.getDebugInfo().getSymbolRecords();
|
||||||
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
symLen = null;
|
||||||
|
nextRetrieveOffset = 0;
|
||||||
|
currentOffset = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return (symLen != null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Peeks at and returns the next symbol without incrementing to the next. If none are
|
||||||
* @param pdb {@link AbstractPdb} that owns the Symbols to be parsed
|
* left, then throws NoSuchElementException and reinitializes the state for a new
|
||||||
* @param reader for the stream section containing the symbol information
|
* iteration.
|
||||||
* @throws CancelledException upon user cancellation
|
* @see #initGet()
|
||||||
|
* @return the next symbol
|
||||||
|
* @throws NoSuchElementException if there are no more elements
|
||||||
*/
|
*/
|
||||||
public MsSymbolIterator(AbstractPdb pdb, PdbByteReader reader) throws CancelledException {
|
public AbstractMsSymbol peek() throws NoSuchElementException {
|
||||||
this.pdb = pdb;
|
if (symLen == null) {
|
||||||
this.reader = reader;
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
return symLen.symbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() throws CancelledException {
|
public AbstractMsSymbol next() {
|
||||||
if (currentSymbol == null) {
|
if (symLen == null) {
|
||||||
find();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
return (currentSymbol != null);
|
SymbolRecords.SymLen offer = symLen;
|
||||||
|
currentOffset = nextRetrieveOffset;
|
||||||
|
symLen = retrieveRecord();
|
||||||
|
return offer.symbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private SymbolRecords.SymLen retrieveRecord() {
|
||||||
public AbstractMsSymbol next() throws CancelledException, NoSuchElementException {
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
if (hasNext()) {
|
return null;
|
||||||
AbstractMsSymbol returnSymbol = currentSymbol;
|
|
||||||
currentSymbol = null;
|
|
||||||
return returnSymbol;
|
|
||||||
}
|
}
|
||||||
throw new NoSuchElementException("next() called with no more elements");
|
if (nextRetrieveOffset >= lengthSymbols) {
|
||||||
}
|
return null;
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractMsSymbol peek() throws CancelledException, NoSuchElementException {
|
|
||||||
if (hasNext()) {
|
|
||||||
return currentSymbol;
|
|
||||||
}
|
|
||||||
throw new NoSuchElementException("peek() called with no more elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void find() throws CancelledException {
|
|
||||||
if (!reader.hasMore()) {
|
|
||||||
currentSymbol = null;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
currentSymbol = SymbolParser.parseLengthAndSymbol(pdb, reader);
|
SymbolRecords.SymLen retrieved =
|
||||||
|
symbolRecords.getRandomAccessRecord(streamNumber, nextRetrieveOffset);
|
||||||
|
if (retrieved != null) {
|
||||||
|
nextRetrieveOffset += retrieved.length();
|
||||||
}
|
}
|
||||||
catch (PdbException e) {
|
return retrieved;
|
||||||
Msg.error(this, "Problem seen in find()", e);
|
}
|
||||||
currentSymbol = null;
|
catch (PdbException | CancelledException e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next symbol. If none are left, then throws NoSuchElementException and
|
||||||
|
* reinitializes the state for a new iteration.
|
||||||
|
* @see #initGet()
|
||||||
|
* @return the next symbol
|
||||||
|
* @throws NoSuchElementException if there are no more elements
|
||||||
|
*/
|
||||||
|
public long getCurrentOffset() {
|
||||||
|
return currentOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialized the mechanism for requesting the symbols in sequence.
|
||||||
|
* @see #hasNext()
|
||||||
|
*/
|
||||||
|
public void initGet() {
|
||||||
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nextRetrieveOffset = startOffset;
|
||||||
|
currentOffset = nextRetrieveOffset;
|
||||||
|
symLen = retrieveRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialized the mechanism for requesting the symbols in sequence.
|
||||||
|
* @param offset the offset to which to initialize the mechanism.
|
||||||
|
* @see #hasNext()
|
||||||
|
*/
|
||||||
|
public void initGetByOffset(long offset) {
|
||||||
|
Long l = offset;
|
||||||
|
nextRetrieveOffset = l.intValue();
|
||||||
|
currentOffset = nextRetrieveOffset;
|
||||||
|
symLen = retrieveRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the stream number
|
||||||
|
* @return the stream number
|
||||||
|
*/
|
||||||
|
public int getStreamNumber() {
|
||||||
|
return streamNumber;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,14 +69,10 @@ public abstract class PdbDebugInfo {
|
||||||
protected List<SectionContribution> 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 = null;
|
||||||
protected GlobalSymbolInformation globalSymbolInformation;
|
protected GlobalSymbolInformation globalSymbolInformation = null;
|
||||||
protected PublicSymbolInformation publicSymbolInformation;
|
protected PublicSymbolInformation publicSymbolInformation = null;
|
||||||
|
|
||||||
//==============================================================================================
|
|
||||||
// NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)... might be turned off
|
|
||||||
// during development.
|
|
||||||
private boolean doNewStuff = false;
|
|
||||||
private List<Module> modules = new ArrayList<>();
|
private List<Module> modules = new ArrayList<>();
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -91,9 +87,6 @@ public abstract class PdbDebugInfo {
|
||||||
Objects.requireNonNull(pdb, "pdb cannot be null");
|
Objects.requireNonNull(pdb, "pdb cannot be null");
|
||||||
this.pdb = pdb;
|
this.pdb = pdb;
|
||||||
this.streamNumber = streamNumber;
|
this.streamNumber = streamNumber;
|
||||||
globalSymbolInformation = new GlobalSymbolInformation(pdb);
|
|
||||||
publicSymbolInformation = new PublicSymbolInformation(pdb);
|
|
||||||
symbolRecords = new SymbolRecords(pdb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +98,7 @@ public abstract class PdbDebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes the {@link PdbDebugInfo}-based instance.
|
* Deserializes and initializes some basic {@link PdbDebugInfo}-based information
|
||||||
* 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
|
||||||
|
@ -115,24 +108,24 @@ public abstract class PdbDebugInfo {
|
||||||
* @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)
|
public long initialize(boolean headerOnly)
|
||||||
throws IOException, PdbException, CancelledException {
|
throws IOException, PdbException, CancelledException {
|
||||||
if (headerOnly) {
|
if (headerOnly) {
|
||||||
PdbByteReader reader =
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, getHeaderLength());
|
||||||
pdb.getReaderForStreamNumber(streamNumber, 0, getHeaderLength());
|
|
||||||
deserializeHeader(reader);
|
deserializeHeader(reader);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
||||||
deserializeHeader(reader);
|
deserializeHeader(reader);
|
||||||
deserializeInternalSubstreams(reader);
|
deserializeInternalSubstreams(reader);
|
||||||
deserializeAdditionalSubstreams();
|
globalSymbolInformation =
|
||||||
// BELOW: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)
|
new GlobalSymbolInformation(pdb, getGlobalSymbolsHashMaybeStreamNumber());
|
||||||
if (doNewStuff) {
|
publicSymbolInformation =
|
||||||
parseModules();
|
new PublicSymbolInformation(pdb, getPublicStaticSymbolsHashMaybeStreamNumber());
|
||||||
compareSymbols(); //temporary to ensure same results with previous work.
|
symbolRecords = new SymbolRecords(pdb);
|
||||||
}
|
initializeAdditionalComponentsForSubstreams();
|
||||||
// ABOVE: NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)
|
initializeModules();
|
||||||
|
//compareSymbols(); //temporary to ensure same results with previous work.
|
||||||
}
|
}
|
||||||
return versionNumber;
|
return versionNumber;
|
||||||
}
|
}
|
||||||
|
@ -170,63 +163,6 @@ public abstract class PdbDebugInfo {
|
||||||
return moduleInfo;
|
return moduleInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of combined global/public symbols
|
|
||||||
* @return {@link Map}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
|
||||||
* symbols
|
|
||||||
*/
|
|
||||||
public Map<Long, AbstractMsSymbol> getSymbolsByOffset() {
|
|
||||||
return symbolRecords.getSymbolsByOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* @return {@link Map}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
|
||||||
* symbols for the specified module
|
|
||||||
* @throws PdbException upon moduleNumber out of range or no module information
|
|
||||||
*/
|
|
||||||
public Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber)
|
|
||||||
throws PdbException {
|
|
||||||
if (moduleNumber < 0 || moduleNumber > moduleInformationList.size()) {
|
|
||||||
throw new PdbException("ModuleNumber out of range: " + moduleNumber);
|
|
||||||
}
|
|
||||||
if (moduleNumber == 0) {
|
|
||||||
return getSymbolsByOffset();
|
|
||||||
}
|
|
||||||
return symbolRecords.getModuleSymbolsByOffset(moduleNumber - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link AbstractMsSymbol} from the main symbols for the
|
|
||||||
* 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
|
|
||||||
* offset value specified by many symbol type records
|
|
||||||
* @return the symbol group for the module or null if not found
|
|
||||||
*/
|
|
||||||
public AbstractMsSymbol getSymbolForOffsetOfRecord(long offset) {
|
|
||||||
return getSymbolsByOffset().get(offset - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
* @param moduleNumber the number ID of the module (1 to {@link #getNumModules()}) for
|
|
||||||
* which to return the list
|
|
||||||
* @param offset the offset of the symbol (beyond length and symbol type fields); this is the
|
|
||||||
* offset value specified by many symbol type records
|
|
||||||
* @return the symbol group for the module or null if not found
|
|
||||||
* @throws PdbException upon moduleNumber out of range or no module information
|
|
||||||
*/
|
|
||||||
public AbstractMsSymbol getSymbolForModuleAndOffsetOfRecord(int moduleNumber, long offset)
|
|
||||||
throws PdbException {
|
|
||||||
Map<Long, AbstractMsSymbol> symbols = getModuleSymbolsByOffset(moduleNumber);
|
|
||||||
if (symbols == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return symbols.get(offset - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns list of {@link SectionContribution} for this debug info
|
* Returns list of {@link SectionContribution} for this debug info
|
||||||
* @return list of {@link SectionContribution}
|
* @return list of {@link SectionContribution}
|
||||||
|
@ -278,6 +214,12 @@ public abstract class PdbDebugInfo {
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Package-Protected Internals
|
// Package-Protected Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
|
||||||
|
void deserializeHeaderOnly() throws CancelledException, IOException, PdbException {
|
||||||
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, getHeaderLength());
|
||||||
|
deserializeHeader(reader);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the stream number for the GlobalSymbols component
|
* Returns the stream number for the GlobalSymbols component
|
||||||
* @return stream number
|
* @return stream number
|
||||||
|
@ -326,7 +268,7 @@ public abstract class PdbDebugInfo {
|
||||||
* @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()
|
protected abstract void initializeAdditionalComponentsForSubstreams()
|
||||||
throws IOException, PdbException, CancelledException;
|
throws IOException, PdbException, CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -351,9 +293,10 @@ public abstract class PdbDebugInfo {
|
||||||
* @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
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
*/
|
*/
|
||||||
protected abstract void dumpInternalSubstreams(Writer writer)
|
protected abstract void dumpInternalSubstreams(Writer writer)
|
||||||
throws IOException, CancelledException;
|
throws IOException, CancelledException, PdbException;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Internal Data Methods
|
// Internal Data Methods
|
||||||
|
@ -556,14 +499,12 @@ public abstract class PdbDebugInfo {
|
||||||
globalSymbolInformation.dump(writer);
|
globalSymbolInformation.dump(writer);
|
||||||
writer.write("\n");
|
writer.write("\n");
|
||||||
publicSymbolInformation.dump(writer);
|
publicSymbolInformation.dump(writer);
|
||||||
if (doNewStuff) {
|
|
||||||
dumpSymbols(writer);
|
dumpSymbols(writer);
|
||||||
for (Module module : modules) {
|
for (Module module : modules) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
module.dump(writer);
|
module.dump(writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug method for dumping module information for all of the {@link ModuleInformation}
|
* Debug method for dumping module information for all of the {@link ModuleInformation}
|
||||||
|
@ -611,9 +552,11 @@ public abstract class PdbDebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// NEW STUFF FROM REFACTOR/REWORK (can be duplicative with other stuff)... might be turned off
|
/**
|
||||||
// during development.
|
* Initializes modules with some basic information, enabling later queries of the modules
|
||||||
private void parseModules() throws CancelledException {
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
private void initializeModules() throws CancelledException {
|
||||||
for (ModuleInformation moduleInformation : moduleInformationList) {
|
for (ModuleInformation moduleInformation : moduleInformationList) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
Module module = new Module(pdb, moduleInformation);
|
Module module = new Module(pdb, moduleInformation);
|
||||||
|
@ -634,21 +577,14 @@ public abstract class PdbDebugInfo {
|
||||||
return modules.get(moduleNum);
|
return modules.get(moduleNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 main symbols
|
||||||
* @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 PdbException upon not enough data left to parse
|
||||||
*/
|
*/
|
||||||
public MsSymbolIterator getSymbolIterator()
|
MsSymbolIterator getSymbolIterator() throws CancelledException, PdbException {
|
||||||
throws CancelledException, IOException {
|
return new MsSymbolIterator(pdb, streamNumberSymbolRecords, 0, MsfStream.MAX_STREAM_LENGTH);
|
||||||
if (streamNumberSymbolRecords == MsfStream.NIL_STREAM_NUMBER) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumberSymbolRecords);
|
|
||||||
MsSymbolIterator iterator = new MsSymbolIterator(pdb, reader);
|
|
||||||
return iterator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -657,25 +593,26 @@ public abstract class PdbDebugInfo {
|
||||||
* @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
|
||||||
|
* @throws IOException upon issue reading the stream
|
||||||
*/
|
*/
|
||||||
MsSymbolIterator getSymbolIterator(int moduleNum) throws CancelledException, PdbException {
|
MsSymbolIterator getSymbolIterator(int moduleNum)
|
||||||
|
throws CancelledException, PdbException, IOException {
|
||||||
Module module = modules.get(moduleNum);
|
Module module = modules.get(moduleNum);
|
||||||
return module.getSymbolIterator();
|
return module.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpSymbols(Writer writer) throws CancelledException, IOException {
|
private void dumpSymbols(Writer writer) throws CancelledException, IOException, PdbException {
|
||||||
MsSymbolIterator iterator = getSymbolIterator();
|
MsSymbolIterator iteratorx = getSymbolIterator();
|
||||||
List<AbstractMsSymbol> symbols = new ArrayList<>();
|
List<AbstractMsSymbol> symbols = new ArrayList<>();
|
||||||
while (iterator.hasNext()) {
|
while (iteratorx.hasNext()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
symbols.add(iterator.next());
|
symbols.add(iteratorx.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()
|
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) {
|
||||||
return;
|
return;
|
||||||
|
@ -713,7 +650,7 @@ public abstract class PdbDebugInfo {
|
||||||
for (int modnum = 0; modnum < numModules(); modnum++) {
|
for (int modnum = 0; modnum < numModules(); modnum++) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
Module module = modules.get(modnum);
|
Module module = modules.get(modnum);
|
||||||
MsSymbolIterator moduleSymbolsIterator = module.getSymbolIterator();
|
MsSymbolIterator moduleSymbolsIterator = getSymbolIterator(modnum);
|
||||||
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<>();
|
||||||
|
|
|
@ -146,16 +146,15 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deserializeAdditionalSubstreams()
|
protected void initializeAdditionalComponentsForSubstreams()
|
||||||
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();
|
symbolRecords.initialize();
|
||||||
globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber());
|
globalSymbolInformation.initialize();
|
||||||
publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber());
|
publicSymbolInformation.initialize();
|
||||||
//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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -229,7 +228,8 @@ public class PdbNewDebugInfo extends PdbDebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dumpInternalSubstreams(Writer writer) throws IOException, CancelledException {
|
protected void dumpInternalSubstreams(Writer writer)
|
||||||
|
throws IOException, CancelledException, PdbException {
|
||||||
writer.write("ModuleInformationList---------------------------------------\n");
|
writer.write("ModuleInformationList---------------------------------------\n");
|
||||||
dumpModuleInformation(writer);
|
dumpModuleInformation(writer);
|
||||||
writer.write("\nEnd ModuleInformationList-----------------------------------\n");
|
writer.write("\nEnd ModuleInformationList-----------------------------------\n");
|
||||||
|
|
|
@ -70,13 +70,13 @@ public class PdbOldDebugInfo extends PdbDebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deserializeAdditionalSubstreams()
|
protected void initializeAdditionalComponentsForSubstreams()
|
||||||
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();
|
symbolRecords.initialize();
|
||||||
globalSymbolInformation.deserialize(getGlobalSymbolsHashMaybeStreamNumber());
|
globalSymbolInformation.initialize();
|
||||||
publicSymbolInformation.deserialize(getPublicStaticSymbolsHashMaybeStreamNumber());
|
publicSymbolInformation.initialize();
|
||||||
//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.
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.MsfStream;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,10 +34,11 @@ import ghidra.util.exception.CancelledException;
|
||||||
*/
|
*/
|
||||||
public class PublicSymbolInformation extends AbstractSymbolInformation {
|
public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
|
|
||||||
|
public static final int PUB_HEADER_SIZE = 28;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Internals
|
// Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private int symbolHashLength;
|
|
||||||
private int addressMapLength;
|
private int addressMapLength;
|
||||||
private int numThunks; // unsigned int
|
private int numThunks; // unsigned int
|
||||||
private int thunkSize;
|
private int thunkSize;
|
||||||
|
@ -46,10 +49,9 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
private int thunkTableLength;
|
private int thunkTableLength;
|
||||||
private int sectionMapLength;
|
private int sectionMapLength;
|
||||||
|
|
||||||
// These should correspond with symbolOffsets that come from HashRecords.
|
private int addressMapOffset;
|
||||||
private List<Long> addressMapSymbolOffsets = new ArrayList<>();
|
private int thunkMapOffset;
|
||||||
private Map<Integer, Integer> thunkTargetOffsetsByTableOffset = new HashMap<>();
|
private int sectionMapOffset;
|
||||||
private Map<Integer, Integer> absoluteOffsetsBySectionNumber = new HashMap<>();
|
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// API
|
// API
|
||||||
|
@ -57,9 +59,10 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @param streamNumber the stream number containing the symbol information
|
||||||
*/
|
*/
|
||||||
public PublicSymbolInformation(AbstractPdb pdbIn) {
|
public PublicSymbolInformation(AbstractPdb pdbIn, int streamNumber) {
|
||||||
super(pdbIn);
|
super(pdbIn, streamNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,65 +117,92 @@ 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
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public List<Long> getAddressMapSymbolOffsets() {
|
public List<Long> getAddressMapSymbolOffsets() throws CancelledException, PdbException {
|
||||||
return addressMapSymbolOffsets;
|
try {
|
||||||
|
PdbByteReader reader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, addressMapOffset, addressMapLength);
|
||||||
|
return deserializeAddressMap(reader);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Msg.error(this, String.format(
|
||||||
|
"PDB: Error creating address map symbol offsets while reading stream %d at offset %d and length %d",
|
||||||
|
streamNumber, addressMapOffset, addressMapLength));
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Thunk Target Offsets by Table Offset
|
||||||
|
* @return the map
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
public Map<Integer, Integer> getThunkTargetOffsetsByTableOffset()
|
||||||
|
throws CancelledException, PdbException {
|
||||||
|
try {
|
||||||
|
PdbByteReader reader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, thunkMapOffset, thunkMapLength);
|
||||||
|
return deserializeThunkMap(reader);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Msg.error(this, String.format(
|
||||||
|
"PDB: Error creating thunk target offsets by table offset while reading stream %d offset %d and length %d",
|
||||||
|
streamNumber, thunkMapOffset, thunkMapLength));
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Absolute Offsets by Section Number map
|
||||||
|
* @return the map
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
public Map<Integer, Integer> getAbsoluteOffsetsBySectionNumber()
|
||||||
|
throws CancelledException, PdbException {
|
||||||
|
try {
|
||||||
|
PdbByteReader reader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, sectionMapOffset, sectionMapLength);
|
||||||
|
return deserializeSectionMap(reader);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Msg.error(this, String.format(
|
||||||
|
"PDB: Error creating absolute offsets by section number while reading stream %d offset %d and length %d",
|
||||||
|
streamNumber, sectionMapOffset, sectionMapLength));
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Package-Protected Internals
|
// Package-Protected Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/**
|
/**
|
||||||
* Deserialize the {@link PublicSymbolInformation} from the appropriate stream in the Pdb
|
* Deserializes and intializes {@link PublicSymbolInformation} basic information from the
|
||||||
* @param streamNumber the stream number containing the information to deserialize
|
* appropriate stream in the Pdb so that later queries can be made
|
||||||
* @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)
|
void initialize() throws IOException, PdbException, CancelledException {
|
||||||
throws IOException, PdbException, CancelledException {
|
initializeValues();
|
||||||
super.deserialize(streamNumber);
|
deserializePubHeader();
|
||||||
|
deserializeHashHeader();
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
|
||||||
|
|
||||||
deserializePubHeader(reader);
|
|
||||||
|
|
||||||
PdbByteReader hashReader = reader.getSubPdbByteReader(symbolHashLength);
|
|
||||||
deserializeHashTable(hashReader);
|
|
||||||
|
|
||||||
PdbByteReader addressMapReader = reader.getSubPdbByteReader(addressMapLength);
|
|
||||||
deserializeAddressMap(addressMapReader);
|
|
||||||
|
|
||||||
PdbByteReader thunkMapReader = reader.getSubPdbByteReader(thunkMapLength);
|
|
||||||
deserializeThunkMap(thunkMapReader);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See note in {@link #deserializePubHeader(PdbByteReader)} regarding spurious data
|
|
||||||
* for numSections. Because of this, we will assume the rest of the data in the
|
|
||||||
* reader belongs to the section map and set the appropriate variable values here.
|
|
||||||
*/
|
|
||||||
sectionMapLength = reader.numRemaining();
|
|
||||||
if (sectionMapLength % 8 != 0) {
|
|
||||||
throw new PdbException("sectionMapLength size not multiple of 8");
|
|
||||||
}
|
|
||||||
numSections = sectionMapLength / 8;
|
|
||||||
PdbByteReader sectionMapReader = reader.getSubPdbByteReader(sectionMapLength);
|
|
||||||
deserializeSectionMap(sectionMapReader);
|
|
||||||
|
|
||||||
// Organize the information
|
|
||||||
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 issue reading PDBor upon 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
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void dump(Writer writer) throws IOException, CancelledException {
|
void dump(Writer writer) throws IOException, CancelledException, PdbException {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("PublicSymbolInformation-------------------------------------\n");
|
builder.append("PublicSymbolInformation-------------------------------------\n");
|
||||||
dumpPubHeader(builder);
|
dumpPubHeader(builder);
|
||||||
|
@ -197,23 +227,31 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
* @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)
|
private List<Long> deserializeAddressMap(PdbByteReader reader)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
|
List<Long> myAddressMapSymbolOffsets = new ArrayList<>();
|
||||||
while (reader.hasMore()) {
|
while (reader.hasMore()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
addressMapSymbolOffsets.add((long) reader.parseInt());
|
myAddressMapSymbolOffsets.add((long) reader.parseInt());
|
||||||
}
|
}
|
||||||
|
return myAddressMapSymbolOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
private void dumpAddressMap(StringBuilder builder) {
|
private void dumpAddressMap(StringBuilder builder)
|
||||||
|
throws CancelledException, IOException, PdbException {
|
||||||
builder.append("AddressMapSymbolOffsets-------------------------------------\n");
|
builder.append("AddressMapSymbolOffsets-------------------------------------\n");
|
||||||
builder.append("numAddressMapSymbolOffsets: " + addressMapSymbolOffsets.size() + "\n");
|
List<Long> myAddressMapSymbolOffsets = getAddressMapSymbolOffsets();
|
||||||
|
builder.append("numAddressMapSymbolOffsets: " + myAddressMapSymbolOffsets.size() + "\n");
|
||||||
int num = 0;
|
int num = 0;
|
||||||
for (Long val : addressMapSymbolOffsets) {
|
for (Long val : myAddressMapSymbolOffsets) {
|
||||||
builder.append(String.format("0X%08X: 0X%012X\n", num++, val));
|
builder.append(String.format("0X%08X: 0X%012X\n", num++, val));
|
||||||
}
|
}
|
||||||
builder.append("\nEnd AddressMapSymbolOffsets---------------------------------\n");
|
builder.append("\nEnd AddressMapSymbolOffsets---------------------------------\n");
|
||||||
|
@ -225,26 +263,35 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
* @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)
|
private Map<Integer, Integer> deserializeThunkMap(PdbByteReader reader)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
Map<Integer, Integer> myThunkTargetOffsetsByTableOffset = new HashMap<>();
|
||||||
while (reader.hasMore()) {
|
while (reader.hasMore()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
int targetOffset = reader.parseInt();
|
int targetOffset = reader.parseInt();
|
||||||
int mapTableOffset = count * thunkSize + offsetThunkTable;
|
int mapTableOffset = count * thunkSize + offsetThunkTable;
|
||||||
thunkTargetOffsetsByTableOffset.put(mapTableOffset, targetOffset);
|
myThunkTargetOffsetsByTableOffset.put(mapTableOffset, targetOffset);
|
||||||
}
|
}
|
||||||
|
return myThunkTargetOffsetsByTableOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
private void dumpThunkMap(StringBuilder builder) {
|
private void dumpThunkMap(StringBuilder builder)
|
||||||
|
throws CancelledException, IOException, PdbException {
|
||||||
|
Map<Integer, Integer> myThunkTargetOffsetsByTableOffset =
|
||||||
|
getThunkTargetOffsetsByTableOffset();
|
||||||
builder.append("ThunkMap----------------------------------------------------\n");
|
builder.append("ThunkMap----------------------------------------------------\n");
|
||||||
builder.append(
|
builder.append("numThunkTargetOffsetsByTableOffset: " +
|
||||||
"numThunkTargetOffsetsByTableOffset: " + thunkTargetOffsetsByTableOffset.size() + "\n");
|
myThunkTargetOffsetsByTableOffset.size() + "\n");
|
||||||
for (Map.Entry<Integer, Integer> entry : thunkTargetOffsetsByTableOffset.entrySet()) {
|
for (Map.Entry<Integer, Integer> entry : myThunkTargetOffsetsByTableOffset.entrySet()) {
|
||||||
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 ThunkMap------------------------------------------------\n");
|
builder.append("\nEnd ThunkMap------------------------------------------------\n");
|
||||||
|
@ -256,27 +303,35 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
* @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)
|
private Map<Integer, Integer> deserializeSectionMap(PdbByteReader reader)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
|
Map<Integer, Integer> myAbsoluteOffsetsBySectionNumber = new HashMap<>();
|
||||||
while (reader.hasMore()) {
|
while (reader.hasMore()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
int offset = reader.parseInt();
|
int offset = reader.parseInt();
|
||||||
int section = reader.parseUnsignedShortVal();
|
int section = reader.parseUnsignedShortVal();
|
||||||
reader.skip(2); // padding
|
reader.skip(2); // padding
|
||||||
absoluteOffsetsBySectionNumber.put(section, offset);
|
myAbsoluteOffsetsBySectionNumber.put(section, offset);
|
||||||
}
|
}
|
||||||
|
return myAbsoluteOffsetsBySectionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
private void dumpSectionMap(StringBuilder builder) throws CancelledException {
|
private void dumpSectionMap(StringBuilder builder)
|
||||||
|
throws CancelledException, IOException, PdbException {
|
||||||
|
Map<Integer, Integer> myAbsoluteOffsetsBySectionNumber =
|
||||||
|
getAbsoluteOffsetsBySectionNumber();
|
||||||
builder.append("SectionMap--------------------------------------------------\n");
|
builder.append("SectionMap--------------------------------------------------\n");
|
||||||
builder.append(
|
builder.append(
|
||||||
"numAbsoluteOffsetsBySectionNumber: " + absoluteOffsetsBySectionNumber.size() + "\n");
|
"numAbsoluteOffsetsBySectionNumber: " + myAbsoluteOffsetsBySectionNumber.size() + "\n");
|
||||||
for (Map.Entry<Integer, Integer> entry : absoluteOffsetsBySectionNumber.entrySet()) {
|
for (Map.Entry<Integer, Integer> entry : myAbsoluteOffsetsBySectionNumber.entrySet()) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
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()));
|
||||||
}
|
}
|
||||||
|
@ -310,11 +365,17 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
builder.append("\nEnd PublicSymbolInformationHeader---------------------------\n");
|
builder.append("\nEnd PublicSymbolInformationHeader---------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deserializePubHeader() throws PdbException, CancelledException, IOException {
|
||||||
|
MsfStream stream = pdb.getMsf().getStream(streamNumber);
|
||||||
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, PUB_HEADER_SIZE);
|
||||||
|
deserializePubHeader(reader, stream.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
// Issue: MSFT does not initialize PSGSIHDR with nSects(0) (our numSections), so spurious
|
// Issue: MSFT does not initialize PSGSIHDR with nSects(0) (our numSections), so spurious
|
||||||
// data can be seen for this field. We cannot do sanity checks on the value. The only
|
// data can be seen for this field. We cannot do sanity checks on the value. The only
|
||||||
// effective thing we can do is to check if any data is left in the reader. Whatever amount
|
// effective thing we can do is to check if any data is left in the reader. Whatever amount
|
||||||
// is left is what we will use.
|
// is left is what we will use.
|
||||||
private void deserializePubHeader(PdbByteReader reader) throws PdbException {
|
private void deserializePubHeader(PdbByteReader reader, int streamLength) throws PdbException {
|
||||||
symbolHashLength = reader.parseInt();
|
symbolHashLength = reader.parseInt();
|
||||||
addressMapLength = reader.parseInt();
|
addressMapLength = reader.parseInt();
|
||||||
long val = reader.parseUnsignedIntVal();
|
long val = reader.parseUnsignedIntVal();
|
||||||
|
@ -349,12 +410,21 @@ public class PublicSymbolInformation extends AbstractSymbolInformation {
|
||||||
throw new PdbException("Cannot support large unsigned integer for thunk table length");
|
throw new PdbException("Cannot support large unsigned integer for thunk table length");
|
||||||
}
|
}
|
||||||
thunkTableLength = (int) val;
|
thunkTableLength = (int) val;
|
||||||
// See note above regarding MSFT numSections issue
|
|
||||||
//val = 8 * numSections;
|
// Do some additional calculations
|
||||||
//if (val > Integer.MAX_VALUE) {
|
symbolHashOffset = PUB_HEADER_SIZE; // reader.getIndex();
|
||||||
// throw new PdbException("Cannot support long value for section map length");
|
addressMapOffset = symbolHashOffset + symbolHashLength;
|
||||||
//}
|
thunkMapOffset = addressMapOffset + addressMapLength;
|
||||||
//sectionMapLength = (int) val;
|
sectionMapOffset = thunkMapOffset + thunkMapLength;
|
||||||
|
// Due to the possibility of spurious data for sections (noted above), we will assume
|
||||||
|
// the rest of the data belongs to the section map and set the appropriate variable
|
||||||
|
// values here.
|
||||||
|
sectionMapLength = streamLength - sectionMapOffset;
|
||||||
|
if (sectionMapLength % 8 != 0) {
|
||||||
|
throw new PdbException("sectionMapLength size not multiple of 8");
|
||||||
|
}
|
||||||
|
numSections = sectionMapLength / 8;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ public class SymbolHashRecord implements Comparable<SymbolHashRecord> {
|
||||||
private long offsetVal;
|
private long offsetVal;
|
||||||
private int referenceCount;
|
private int referenceCount;
|
||||||
|
|
||||||
|
public static int RECORD_SIZE = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the contents of of this record.
|
* Parses the contents of of this record.
|
||||||
* @param reader {@link PdbByteReader} from which to deserialize the data.
|
* @param reader {@link PdbByteReader} from which to deserialize the data.
|
||||||
|
|
|
@ -34,8 +34,6 @@ import ghidra.util.exception.CancelledException;
|
||||||
public class SymbolRecords {
|
public class SymbolRecords {
|
||||||
|
|
||||||
private AbstractPdb pdb;
|
private AbstractPdb pdb;
|
||||||
private Map<Long, AbstractMsSymbol> symbolsByOffset;
|
|
||||||
private List<Map<Long, AbstractMsSymbol>> moduleSymbolsByOffset = new ArrayList<>();
|
|
||||||
|
|
||||||
// Used for CvSig part of streams. See methods below.
|
// Used for CvSig part of streams. See methods below.
|
||||||
private boolean getSig = true;
|
private boolean getSig = true;
|
||||||
|
@ -59,9 +57,24 @@ public class SymbolRecords {
|
||||||
* Returns the list of symbols
|
* Returns the list of symbols
|
||||||
* @return {@link Map}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
* @return {@link Map}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
||||||
* symbols
|
* symbols
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
protected Map<Long, AbstractMsSymbol> getSymbolsByOffset() {
|
@Deprecated
|
||||||
return symbolsByOffset;
|
protected Map<Long, AbstractMsSymbol> getSymbolsByOffset()
|
||||||
|
throws CancelledException, PdbException, IOException {
|
||||||
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
|
if (debugInfo == null) {
|
||||||
|
return new TreeMap<>();
|
||||||
|
}
|
||||||
|
int streamNumber = debugInfo.getSymbolRecordsStreamNumber();
|
||||||
|
if (streamNumber <= 0) {
|
||||||
|
return new TreeMap<>();
|
||||||
|
}
|
||||||
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
||||||
|
return deserializeSymbolRecords(pdb, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,103 +82,41 @@ public class SymbolRecords {
|
||||||
* @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}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
* @return {@link Map}<{@link Long},{@link AbstractMsSymbol}> of buffer offsets to
|
||||||
* symbols for the specified module
|
* symbols for the specified module
|
||||||
*/
|
|
||||||
protected Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber) {
|
|
||||||
return moduleSymbolsByOffset.get(moduleNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserializes the {@link SymbolRecords} from the stream noted in the DBI header
|
|
||||||
* @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() throws IOException, PdbException, CancelledException {
|
@Deprecated
|
||||||
|
protected Map<Long, AbstractMsSymbol> getModuleSymbolsByOffset(int moduleNumber)
|
||||||
|
throws CancelledException, IOException, PdbException {
|
||||||
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
|
if (debugInfo == null) {
|
||||||
|
return new TreeMap<>();
|
||||||
|
}
|
||||||
|
ModuleInformation moduleInfo = debugInfo.moduleInformationList.get(moduleNumber);
|
||||||
|
int streamNumber = moduleInfo.getStreamNumberDebugInformation();
|
||||||
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
|
return new TreeMap<>();
|
||||||
|
}
|
||||||
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
||||||
|
int sizeSymbolsSection = moduleInfo.getSizeLocalSymbolsDebugInformation();
|
||||||
|
PdbByteReader symbolsReader = reader.getSubPdbByteReader(sizeSymbolsSection);
|
||||||
|
symbolsReader.skip(getCvSigLength(streamNumber));
|
||||||
|
return deserializeSymbolRecords(pdb, symbolsReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes and initializes basic {@link SymbolRecords} information from the stream noted
|
||||||
|
* in the DBI header so that later symbol queries can be done
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
* @throws PdbException upon not enough data left to parse
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
*/
|
||||||
|
void initialize() throws IOException, PdbException, CancelledException {
|
||||||
initializeCache(0.001);
|
initializeCache(0.001);
|
||||||
determineCvSigValues(); // new method for random-access symbol work
|
determineCvSigValues(); // new method for random-access symbol work
|
||||||
processSymbols();
|
|
||||||
processModuleSymbols();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processSymbols()
|
|
||||||
throws IOException, PdbException, CancelledException {
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
|
||||||
if (debugInfo == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int streamNumber = debugInfo.getSymbolRecordsStreamNumber();
|
|
||||||
if (streamNumber <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
|
||||||
symbolsByOffset = deserializeSymbolRecords(pdb, reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// skip over the symbols.
|
|
||||||
private void processModuleSymbols()
|
|
||||||
throws IOException, PdbException, CancelledException {
|
|
||||||
// cvSignature:
|
|
||||||
// >64K = C6
|
|
||||||
// 1 = C7
|
|
||||||
// 2 = C11 (vc5.x)
|
|
||||||
// 3 = ??? (not specified, and not marked as reserved)
|
|
||||||
// 4 = C13 (vc7.x)
|
|
||||||
// 5-64K = RESERVED
|
|
||||||
//
|
|
||||||
// Both cvdump (1660 and 1668) and mod.cpp (575) seem to indicate that the first module
|
|
||||||
// might have the cvSignature of C7 or C11 (when C7/C11), but modules thereafter will not
|
|
||||||
// or may not have the value. C13 would always have the C13 signature.
|
|
||||||
boolean getSig = true;
|
|
||||||
int cvSignature = 0;
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
|
||||||
if (debugInfo == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ModuleInformation module : debugInfo.moduleInformationList) {
|
|
||||||
pdb.checkCancelled();
|
|
||||||
int streamNumber = module.getStreamNumberDebugInformation();
|
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
|
||||||
moduleSymbolsByOffset.add(new TreeMap<>());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
|
||||||
|
|
||||||
int sizeSymbolsSection = module.getSizeLocalSymbolsDebugInformation();
|
|
||||||
PdbByteReader symbolsReader = reader.getSubPdbByteReader(sizeSymbolsSection);
|
|
||||||
// See comment above regarding getSig boolean
|
|
||||||
if (getSig) {
|
|
||||||
cvSignature = symbolsReader.parseInt();
|
|
||||||
}
|
|
||||||
switch (cvSignature) {
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
// We have no 1,2 examples to test this logic for cvSignature. Confirming
|
|
||||||
// or rejecting this logic is important for simplifying/refactoring this
|
|
||||||
// method or writing new methods to allow for extraction of information from
|
|
||||||
// individual modules. The current implementation has cross-module logic
|
|
||||||
// (setting state in the processing of the first and using this state in the
|
|
||||||
// processing of follow-on modules).
|
|
||||||
getSig = false;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (cvSignature < 0x10000) {
|
|
||||||
throw new PdbException(
|
|
||||||
"Invalid module CV signature in stream " + streamNumber);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Long, AbstractMsSymbol> oneModuleSymbolsByOffset =
|
|
||||||
deserializeSymbolRecords(pdb, symbolsReader);
|
|
||||||
moduleSymbolsByOffset.add(oneModuleSymbolsByOffset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These methods are trying to adapt the logic of the previous method here (which attempted
|
// These methods are trying to adapt the logic of the previous method here (which attempted
|
||||||
|
@ -189,7 +140,6 @@ public class SymbolRecords {
|
||||||
ModuleInformation moduleInfo = debugInfo.getModuleInformationList().get(0);
|
ModuleInformation moduleInfo = debugInfo.getModuleInformationList().get(0);
|
||||||
int streamNumber = moduleInfo.getStreamNumberDebugInformation();
|
int streamNumber = moduleInfo.getStreamNumberDebugInformation();
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
moduleSymbolsByOffset.add(new TreeMap<>());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber);
|
||||||
|
@ -230,11 +180,11 @@ public class SymbolRecords {
|
||||||
*/
|
*/
|
||||||
public int getCvSigLength(int streamNumber)
|
public int getCvSigLength(int streamNumber)
|
||||||
throws CancelledException, IOException, PdbException {
|
throws CancelledException, IOException, PdbException {
|
||||||
if (cvSignatureCase1and2Stream == MsfStream.NIL_STREAM_NUMBER) {
|
// if (cvSignatureCase1and2Stream == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
throw new PdbException("CvSignLength not initialized");
|
// throw new PdbException("CvSigLength not initialized");
|
||||||
}
|
// }
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
||||||
throw new PdbException("Attempting to read unassigned stream");
|
return 0; // returning inconsequential value; fact of NIL will be dealt with elsewhere
|
||||||
}
|
}
|
||||||
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, 4);
|
PdbByteReader reader = pdb.getReaderForStreamNumber(streamNumber, 0, 4);
|
||||||
if (getSig) {
|
if (getSig) {
|
||||||
|
@ -253,7 +203,7 @@ public class SymbolRecords {
|
||||||
size = 4;
|
size = 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new PdbException("PDB Error: Bad CvSsigLength state");
|
throw new PdbException("PDB Error: Bad CvSigLength state");
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +256,7 @@ public class SymbolRecords {
|
||||||
|
|
||||||
// TODO: consider pre-storing the lengths with one build stream read. However, that would
|
// TODO: consider pre-storing the lengths with one build stream read. However, that would
|
||||||
// consume more memory, so only do this if willing to improve process performance at
|
// consume more memory, so only do this if willing to improve process performance at
|
||||||
// cost of memroy.
|
// cost of memory.
|
||||||
//Map<Long, Integer> recordLengths = new TreeMap<>();
|
//Map<Long, Integer> recordLengths = new TreeMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -384,13 +334,19 @@ public class SymbolRecords {
|
||||||
* @param writer {@link Writer} to which to dump the information
|
* @param writer {@link Writer} to which to dump the information
|
||||||
* @throws IOException upon issue writing to the {@link Writer}
|
* @throws IOException upon issue writing to the {@link Writer}
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon not enough data to parse
|
||||||
*/
|
*/
|
||||||
protected void dump(Writer writer) throws IOException, CancelledException {
|
protected void dump(Writer writer) throws IOException, CancelledException, PdbException {
|
||||||
writer.write("SymbolRecords-----------------------------------------------\n");
|
writer.write("SymbolRecords-----------------------------------------------\n");
|
||||||
|
Map<Long, AbstractMsSymbol> symbolsByOffset = getSymbolsByOffset();
|
||||||
dumpSymbolMap(symbolsByOffset, writer);
|
dumpSymbolMap(symbolsByOffset, writer);
|
||||||
for (int i = 0; i < moduleSymbolsByOffset.size(); i++) {
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
|
if (debugInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < debugInfo.getNumModules(); i++) {
|
||||||
pdb.checkCancelled();
|
pdb.checkCancelled();
|
||||||
Map<Long, AbstractMsSymbol> map = moduleSymbolsByOffset.get(i);
|
Map<Long, AbstractMsSymbol> map = getModuleSymbolsByOffset(i);
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
writer.write("Module(" + i + ") List:\n");
|
writer.write("Module(" + i + ") List:\n");
|
||||||
dumpSymbolMap(map, writer);
|
dumpSymbolMap(map, writer);
|
||||||
|
|
|
@ -22,8 +22,6 @@ public interface TPI {
|
||||||
|
|
||||||
int getTypeIndexMaxExclusive();
|
int getTypeIndexMaxExclusive();
|
||||||
|
|
||||||
AbstractMsType getRecord(int recordNumber);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Random access of {@link AbstractMsType} record indicated by {@code recordNumber}
|
* Random access of {@link AbstractMsType} record indicated by {@code recordNumber}
|
||||||
* @param recordNumber record number of the record to retrieve
|
* @param recordNumber record number of the record to retrieve
|
||||||
|
|
|
@ -120,48 +120,22 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the {@link AbstractMsType} record indicated by the recordNumber. The record must
|
* Retrieves the {@link AbstractMsType} record indicated by the recordNumber
|
||||||
* already have been parsed and inserted into the list
|
|
||||||
* @param recordNumber record number to look up
|
* @param recordNumber record number to look up
|
||||||
* @return {@link AbstractMsType} pertaining to the record number
|
* @return {@link AbstractMsType} pertaining to the record number
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public AbstractMsType getRecord(int recordNumber) {
|
|
||||||
if (recordNumber < 0 || recordNumber - typeIndexMin > typeList.size()) {
|
|
||||||
// This should not happen, but we have seen it and cannot yet explain it.
|
|
||||||
// So, for now, we are creating and returning a new BadMsType.
|
|
||||||
PdbLog.logBadTypeRecordIndex(this, recordNumber);
|
|
||||||
BadMsType type = new BadMsType(pdb, 0);
|
|
||||||
type.setRecordNumber(RecordNumber.make(recordCategory, recordNumber));
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
if (recordNumber < typeIndexMin) {
|
|
||||||
PrimitiveMsType primitive = primitiveTypesByRecordNumber.get(recordNumber);
|
|
||||||
if (primitive == null) {
|
|
||||||
primitive = new PrimitiveMsType(pdb, recordNumber);
|
|
||||||
primitiveTypesByRecordNumber.put(recordNumber, primitive);
|
|
||||||
}
|
|
||||||
return primitive;
|
|
||||||
}
|
|
||||||
return typeList.get(recordNumber - typeIndexMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractMsType getRandomAccessRecord(int recordNumber) {
|
public AbstractMsType getRandomAccessRecord(int recordNumber) {
|
||||||
if (recordNumber < 0 || recordNumber - typeIndexMin > typeList.size()) {
|
if (recordNumber < 0 || recordNumber - typeIndexMin > offLenRecords.size()) {
|
||||||
// This should not happen, but we have seen it and cannot yet explain it.
|
// This should not happen, but we have seen it and cannot yet explain it.
|
||||||
// So, for now, we are creating and returning a new BadMsType.
|
// So, for now, we are creating and returning a new BadMsType.
|
||||||
PdbLog.logBadTypeRecordIndex(this, recordNumber);
|
PdbLog.logBadTypeRecordIndex(this, recordNumber);
|
||||||
BadMsType type = new BadMsType(pdb, 0);
|
BadMsType badType = new BadMsType(pdb, 0);
|
||||||
type.setRecordNumber(RecordNumber.make(recordCategory, recordNumber));
|
badType.setRecordNumber(RecordNumber.make(recordCategory, recordNumber));
|
||||||
return type;
|
return badType;
|
||||||
}
|
|
||||||
if (recordNumber < typeIndexMin) {
|
|
||||||
PrimitiveMsType primitive = primitiveTypesByRecordNumber.get(recordNumber);
|
|
||||||
if (primitive == null) {
|
|
||||||
primitive = new PrimitiveMsType(pdb, recordNumber);
|
|
||||||
primitiveTypesByRecordNumber.put(recordNumber, primitive);
|
|
||||||
}
|
}
|
||||||
|
PrimitiveMsType primitive = getPrimitiveRecord(recordNumber);
|
||||||
|
if (primitive != null) {
|
||||||
return primitive;
|
return primitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +145,7 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
try {
|
try {
|
||||||
PdbByteReader recordReader =
|
PdbByteReader recordReader =
|
||||||
pdb.getReaderForStreamNumber(streamNumber, offLen.offset(), offLen.length());
|
pdb.getReaderForStreamNumber(streamNumber, offLen.offset(), offLen.length());
|
||||||
|
recordReader.markAlign(2);
|
||||||
return TypeParser.parseRecord(pdb, recordReader, rn);
|
return TypeParser.parseRecord(pdb, recordReader, rn);
|
||||||
}
|
}
|
||||||
catch (PdbException | IOException | CancelledException e) {
|
catch (PdbException | IOException | CancelledException e) {
|
||||||
|
@ -180,18 +155,31 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PrimitiveMsType getPrimitiveRecord(int recordNumber) {
|
||||||
|
if (recordNumber >= typeIndexMin) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PrimitiveMsType primitive = primitiveTypesByRecordNumber.get(recordNumber);
|
||||||
|
if (primitive == null) {
|
||||||
|
primitive = new PrimitiveMsType(pdb, recordNumber);
|
||||||
|
primitiveTypesByRecordNumber.put(recordNumber, primitive);
|
||||||
|
}
|
||||||
|
return primitive;
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Package-Protected Internals
|
// Package-Protected Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/**
|
/**
|
||||||
* Deserializes this {@link TypeProgramInterface}
|
* Deserializes and initializes {@link TypeProgramInterface} basic information so that later
|
||||||
|
* queries can be made
|
||||||
* @return version number of the {@link TypeProgramInterface}
|
* @return version number of the {@link TypeProgramInterface}
|
||||||
* @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() throws IOException, PdbException, CancelledException {
|
int initialize() 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.");
|
||||||
|
@ -205,10 +193,10 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
// we have this commented out.
|
// we have this commented out.
|
||||||
//hash.deserializeHashStreams(pdb.getMonitor());
|
//hash.deserializeHashStreams(pdb.getMonitor());
|
||||||
|
|
||||||
|
// TODO: consider other mechanisms than offset/length values for use by an iterator.
|
||||||
|
// Need to be able to access by record number, so might not have much choice.
|
||||||
createOffLenRecords(reader);
|
createOffLenRecords(reader);
|
||||||
|
|
||||||
deserializeTypeRecords(reader);
|
|
||||||
|
|
||||||
return versionNumber;
|
return versionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,36 +232,6 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
this.typeIndexMaxExclusive = typeIndexMaxExclusive;
|
this.typeIndexMaxExclusive = typeIndexMaxExclusive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* IMPORTANT: This method is for testing only. It allows us to set a record for a particular
|
|
||||||
* record number
|
|
||||||
* @param recordNumber record number for the {@link AbstractMsType} to be inserted
|
|
||||||
* @param type {@link AbstractMsType} to be inserted
|
|
||||||
* @return {@code true} if successful
|
|
||||||
*/
|
|
||||||
boolean setRecord(int recordNumber, AbstractMsType type) {
|
|
||||||
if (recordNumber < typeIndexMin) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = typeList.size() + typeIndexMin; i <= recordNumber; i++) {
|
|
||||||
// Add the same record for each index up to the one needed.
|
|
||||||
typeList.add(type);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IMPORTANT: This method is for testing only. It allows us to add a record that gets its
|
|
||||||
* record number automatically assigned
|
|
||||||
* @param type {@link AbstractMsType} to be inserted
|
|
||||||
* @return record number assigned
|
|
||||||
*/
|
|
||||||
int addRecord(AbstractMsType type) {
|
|
||||||
int newRecordNum = typeList.size() + typeIndexMin;
|
|
||||||
typeList.add(type);
|
|
||||||
return newRecordNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Abstract Methods
|
// Abstract Methods
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -308,40 +266,6 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
reader.setIndex(savedIndex); // restore reader to original state
|
reader.setIndex(savedIndex); // restore reader to original state
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserializes the Type Records of this class
|
|
||||||
* @param reader {@link PdbByteReader} from which to deserialize the data
|
|
||||||
* @throws PdbException upon not enough data left to parse
|
|
||||||
* @throws CancelledException upon user cancellation
|
|
||||||
*/
|
|
||||||
protected void deserializeTypeRecords(PdbByteReader reader)
|
|
||||||
throws PdbException, CancelledException {
|
|
||||||
int recordLength;
|
|
||||||
int recordNumber = typeIndexMin;
|
|
||||||
|
|
||||||
while (reader.hasMore()) {
|
|
||||||
pdb.checkCancelled();
|
|
||||||
|
|
||||||
recordLength = reader.parseUnsignedShortVal();
|
|
||||||
PdbByteReader recordReader = reader.getSubPdbByteReader(recordLength);
|
|
||||||
recordReader.markAlign(2);
|
|
||||||
|
|
||||||
// No need to call either of these, because we do not expect the record number
|
|
||||||
// to have a high bit set here. If we did, we would have to check 'category' to
|
|
||||||
// know which of the two to call, and we'd have to create an AbstractTypeIndex:
|
|
||||||
// parseTypeRecordNumber(recordReader, recordNumber);
|
|
||||||
// parseItemRecordNumber(recordReader, recordNumber);
|
|
||||||
AbstractMsType type = TypeParser.parseRecord(pdb, recordReader,
|
|
||||||
RecordNumber.make(recordCategory, recordNumber));
|
|
||||||
typeList.add(type);
|
|
||||||
recordNumber++;
|
|
||||||
}
|
|
||||||
if (recordNumber != typeIndexMaxExclusive) {
|
|
||||||
PdbLog.message(this.getClass().getSimpleName() + ": Header max records: " +
|
|
||||||
typeIndexMaxExclusive + "; parsed records: " + recordNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//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).
|
||||||
/**
|
/**
|
||||||
|
@ -350,8 +274,8 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
* @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;
|
for (int recordNum = typeIndexMin; recordNum < typeIndexMaxExclusive; recordNum++) {
|
||||||
for (AbstractMsType type : typeList) {
|
AbstractMsType type = getRandomAccessRecord(recordNum);
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("------------------------------------------------------------\n");
|
builder.append("------------------------------------------------------------\n");
|
||||||
builder.append("Record: ");
|
builder.append("Record: ");
|
||||||
|
@ -367,7 +291,6 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
builder.append("(null)\n"); //Temporary output value.
|
builder.append("(null)\n"); //Temporary output value.
|
||||||
}
|
}
|
||||||
writer.write(builder.toString());
|
writer.write(builder.toString());
|
||||||
recordNum++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractBlockMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractBlockMsSymbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -35,7 +35,7 @@ public class BlockSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public BlockSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public BlockSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractBlockMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractBlockMsSymbol)) {
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class ComplexTypeMapper {
|
||||||
// to TYPE as we could get using applicator.getPdb().getTypeRecord(recordNumber)
|
// to TYPE as we could get using applicator.getPdb().getTypeRecord(recordNumber)
|
||||||
// where recordNumber is a RecordNumber. This is because we are not expecting
|
// where recordNumber is a RecordNumber. This is because we are not expecting
|
||||||
// a remap for Complex types.
|
// a remap for Complex types.
|
||||||
AbstractMsType type = typeProgramInterface.getRecord(indexNumber);
|
AbstractMsType type = typeProgramInterface.getRandomAccessRecord(indexNumber);
|
||||||
if (type instanceof AbstractCompositeMsType compositeType) {
|
if (type instanceof AbstractCompositeMsType compositeType) {
|
||||||
mapComplexTypesByPath(compositeFIFOsByPath, indexNumber, compositeType);
|
mapComplexTypesByPath(compositeFIFOsByPath, indexNumber, compositeType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractDataMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractDataMsSymbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -40,7 +38,7 @@ public class DataSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public DataSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public DataSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractDataMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractDataMsSymbol)) {
|
||||||
|
@ -170,10 +168,14 @@ public class DataSymbolApplier extends MsSymbolApplier {
|
||||||
}
|
}
|
||||||
if (existingData == null) {
|
if (existingData == null) {
|
||||||
try {
|
try {
|
||||||
applicator.getProgram().getListing().clearCodeUnits(address,
|
applicator.getProgram()
|
||||||
|
.getListing()
|
||||||
|
.clearCodeUnits(address,
|
||||||
address.add(dataTypeLength - 1), false);
|
address.add(dataTypeLength - 1), false);
|
||||||
if (dataType.getLength() == -1) {
|
if (dataType.getLength() == -1) {
|
||||||
applicator.getProgram().getListing().createData(address, dataType,
|
applicator.getProgram()
|
||||||
|
.getListing()
|
||||||
|
.createData(address, dataType,
|
||||||
dataTypeLength);
|
dataTypeLength);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -187,7 +189,9 @@ public class DataSymbolApplier extends MsSymbolApplier {
|
||||||
}
|
}
|
||||||
else if (isDataReplaceable(existingData)) {
|
else if (isDataReplaceable(existingData)) {
|
||||||
try {
|
try {
|
||||||
applicator.getProgram().getListing().clearCodeUnits(address,
|
applicator.getProgram()
|
||||||
|
.getListing()
|
||||||
|
.clearCodeUnits(address,
|
||||||
address.add(dataTypeLength - 1), false);
|
address.add(dataTypeLength - 1), false);
|
||||||
applicator.getProgram().getListing().createData(address, dataType, dataTypeLength);
|
applicator.getProgram().getListing().createData(address, dataType, dataTypeLength);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -33,7 +34,6 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
||||||
import ghidra.app.util.bin.format.pe.cli.tables.CliAbstractTableRow;
|
import ghidra.app.util.bin.format.pe.cli.tables.CliAbstractTableRow;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.app.util.pdb.PdbCategories;
|
import ghidra.app.util.pdb.PdbCategories;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.graph.*;
|
import ghidra.graph.*;
|
||||||
import ghidra.graph.algo.GraphNavigator;
|
import ghidra.graph.algo.GraphNavigator;
|
||||||
|
@ -172,6 +172,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
AddressSet disassembleAddresses;
|
AddressSet disassembleAddresses;
|
||||||
List<DeferrableFunctionSymbolApplier> deferredFunctionWorkAppliers;
|
List<DeferrableFunctionSymbolApplier> deferredFunctionWorkAppliers;
|
||||||
|
|
||||||
|
//==============================================================================================
|
||||||
|
private int currentModuleNumber = 0;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
public DefaultPdbApplicator(AbstractPdb pdb) {
|
public DefaultPdbApplicator(AbstractPdb pdb) {
|
||||||
Objects.requireNonNull(pdb, "pdb cannot be null");
|
Objects.requireNonNull(pdb, "pdb cannot be null");
|
||||||
|
@ -193,10 +196,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
* @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
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
public void applyTo(Program programParam, DataTypeManager dataTypeManagerParam,
|
public void applyTo(Program programParam, DataTypeManager dataTypeManagerParam,
|
||||||
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
|
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
|
||||||
MessageLog logParam) throws PdbException, CancelledException {
|
MessageLog logParam) throws PdbException, CancelledException, IOException {
|
||||||
|
|
||||||
// FIXME: should not support use of DataTypeManager-only since it will not have the correct
|
// FIXME: should not support use of DataTypeManager-only since it will not have the correct
|
||||||
// data organization if it corresponds to a data type archive. Need to evaluate archive
|
// data organization if it corresponds to a data type archive. Need to evaluate archive
|
||||||
|
@ -397,9 +402,16 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
/**
|
||||||
|
* Initializes helper classes and data items used for applying the PDB
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon error in processing components
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
*/
|
||||||
private void initializeApplyTo(Program programParam, DataTypeManager dataTypeManagerParam,
|
private void initializeApplyTo(Program programParam, DataTypeManager dataTypeManagerParam,
|
||||||
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
|
Address imageBaseParam, PdbApplicatorOptions applicatorOptionsParam,
|
||||||
MessageLog logParam) throws PdbException, CancelledException {
|
MessageLog logParam) throws PdbException, CancelledException, IOException {
|
||||||
|
|
||||||
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
|
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
|
||||||
applicatorOptionsParam, logParam);
|
applicatorOptionsParam, logParam);
|
||||||
|
@ -759,8 +771,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
throw new PdbException("PDB: DebugInfo is null");
|
throw new PdbException("PDB: DebugInfo is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SectionContribution sectionContribution : debugInfo
|
for (SectionContribution sectionContribution : debugInfo.getSectionContributionList()) {
|
||||||
.getSectionContributionList()) {
|
|
||||||
int sectionContributionOffset = sectionContribution.getOffset();
|
int sectionContributionOffset = sectionContribution.getOffset();
|
||||||
int maxSectionContributionOffset =
|
int maxSectionContributionOffset =
|
||||||
sectionContributionOffset + sectionContribution.getLength();
|
sectionContributionOffset + sectionContribution.getLength();
|
||||||
|
@ -781,8 +792,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.initialize(num);
|
monitor.initialize(num);
|
||||||
monitor.setMessage("PDB: Processing " + num + " data type components...");
|
monitor.setMessage("PDB: Processing " + num + " data type components...");
|
||||||
for (int indexNumber =
|
for (int indexNumber = tpi.getTypeIndexMin(); indexNumber < tpi
|
||||||
tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) {
|
.getTypeIndexMaxExclusive(); indexNumber++) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
//PdbResearch.checkBreak(indexNumber);
|
//PdbResearch.checkBreak(indexNumber);
|
||||||
MsTypeApplier applier = getTypeApplier(RecordNumber.typeRecordNumber(indexNumber));
|
MsTypeApplier applier = getTypeApplier(RecordNumber.typeRecordNumber(indexNumber));
|
||||||
|
@ -849,8 +860,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.initialize(num);
|
monitor.initialize(num);
|
||||||
monitor.setMessage("PDB: Processing " + num + " item type components...");
|
monitor.setMessage("PDB: Processing " + num + " item type components...");
|
||||||
for (int indexNumber =
|
for (int indexNumber = ipi.getTypeIndexMin(); indexNumber < ipi
|
||||||
ipi.getTypeIndexMin(); indexNumber < ipi.getTypeIndexMaxExclusive(); indexNumber++) {
|
.getTypeIndexMaxExclusive(); indexNumber++) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
MsTypeApplier applier = getTypeApplier(RecordNumber.itemRecordNumber(indexNumber));
|
MsTypeApplier applier = getTypeApplier(RecordNumber.itemRecordNumber(indexNumber));
|
||||||
applier.apply();
|
applier.apply();
|
||||||
|
@ -893,8 +904,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
monitor.initialize(num);
|
monitor.initialize(num);
|
||||||
monitor.setMessage("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
|
||||||
tpi.getTypeIndexMin(); indexNumber < tpi.getTypeIndexMaxExclusive(); indexNumber++) {
|
.getTypeIndexMaxExclusive(); indexNumber++) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
//PdbResearch.checkBreak(indexNumber);
|
//PdbResearch.checkBreak(indexNumber);
|
||||||
MsTypeApplier applier = getTypeApplier(RecordNumber.typeRecordNumber(indexNumber));
|
MsTypeApplier applier = getTypeApplier(RecordNumber.typeRecordNumber(indexNumber));
|
||||||
|
@ -937,8 +948,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateFunctionCmd funCmd = new CreateFunctionCmd(null, normalizedAddress,
|
CreateFunctionCmd funCmd = new CreateFunctionCmd(null, normalizedAddress,
|
||||||
new AddressSet(normalizedAddress, normalizedAddress),
|
new AddressSet(normalizedAddress, normalizedAddress), SourceType.DEFAULT);
|
||||||
SourceType.DEFAULT);
|
|
||||||
if (!funCmd.applyTo(program, cancelOnlyWrappingMonitor)) {
|
if (!funCmd.applyTo(program, cancelOnlyWrappingMonitor)) {
|
||||||
appendLogMsg("Failed to apply function at address " + address.toString() +
|
appendLogMsg("Failed to apply function at address " + address.toString() +
|
||||||
"; attempting to use possible existing function");
|
"; attempting to use possible existing function");
|
||||||
|
@ -1154,12 +1164,20 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.setMessage("PDB: Applying " + totalCount + " main symbol components...");
|
monitor.setMessage("PDB: Applying " + totalCount + " main symbol components...");
|
||||||
monitor.initialize(totalCount);
|
monitor.initialize(totalCount);
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
processSymbolGroup(0, iter);
|
processSymbolGroup(0, iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private void processModuleSymbols() throws CancelledException {
|
int getCurrentModuleNumber() {
|
||||||
|
return currentModuleNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCurrentModuleNumber(int moduleNumber) {
|
||||||
|
currentModuleNumber = moduleNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processModuleSymbols() throws CancelledException, PdbException {
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1184,12 +1202,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
// Process symbols list for each module
|
// Process symbols list for each module
|
||||||
for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) {
|
for (int moduleNumber = 1; moduleNumber <= num; moduleNumber++) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
setCurrentModuleNumber(moduleNumber);
|
||||||
// Process module symbols list
|
// Process module symbols list
|
||||||
SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber);
|
SymbolGroup symbolGroup = getSymbolGroupForModule(moduleNumber);
|
||||||
if (symbolGroup == null) {
|
if (symbolGroup == null) {
|
||||||
continue; // should not happen
|
continue; // should not happen
|
||||||
}
|
}
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
processSymbolGroup(moduleNumber, iter);
|
processSymbolGroup(moduleNumber, iter);
|
||||||
monitor.increment();
|
monitor.increment();
|
||||||
// catelogSymbols(index, symbolGroup);
|
// catelogSymbols(index, symbolGroup);
|
||||||
|
@ -1212,7 +1231,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private void processSymbolGroup(int moduleNumber, AbstractMsSymbolIterator iter)
|
private void processSymbolGroup(int moduleNumber, MsSymbolIterator iter)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
iter.initGet();
|
iter.initGet();
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
|
@ -1244,12 +1263,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
|
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
|
||||||
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.setMessage("PDB: Applying " + offsets.size() + " public symbol components...");
|
monitor.setMessage("PDB: Applying public symbols...");
|
||||||
monitor.initialize(offsets.size());
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
||||||
|
monitor.initialize(offsets.size());
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -1260,6 +1279,26 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
procSym(iter);
|
procSym(iter);
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AbstractSymbolInformation.ModifiedOffsetIterator publicsIter =
|
||||||
|
// publicSymbolInformation.iterator();
|
||||||
|
// monitor.initialize(100L);
|
||||||
|
// long percentDone = 0;
|
||||||
|
// while (publicsIter.hasNext()) {
|
||||||
|
// monitor.checkCancelled();
|
||||||
|
// Long offset = publicsIter.next();
|
||||||
|
// iter.initGetByOffset(offset);
|
||||||
|
// if (!iter.hasNext()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// pdbApplicatorMetrics.witnessPublicSymbolType(iter.peek());
|
||||||
|
// procSym(iter);
|
||||||
|
// // Increment progress
|
||||||
|
// long delta = publicsIter.getPercentageDone() - percentDone;
|
||||||
|
// monitor.incrementProgress(delta);
|
||||||
|
// percentDone += delta;
|
||||||
|
// }
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1281,13 +1320,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
|
|
||||||
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.setMessage("PDB: Applying global symbols...");
|
monitor.setMessage("PDB: Applying global symbols...");
|
||||||
monitor.initialize(offsets.size());
|
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
|
||||||
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
||||||
|
monitor.initialize(offsets.size());
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -1301,6 +1340,28 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
|
||||||
|
// globalSymbolInformation.iterator();
|
||||||
|
// monitor.initialize(100L);
|
||||||
|
// long percentDone = 0;
|
||||||
|
// while (globalsIter.hasNext()) {
|
||||||
|
// monitor.checkCancelled();
|
||||||
|
// Long offset = globalsIter.next();
|
||||||
|
// iter.initGetByOffset(offset);
|
||||||
|
// if (!iter.hasNext()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// AbstractMsSymbol symbol = iter.peek();
|
||||||
|
// pdbApplicatorMetrics.witnessGlobalSymbolType(symbol);
|
||||||
|
// if (!(symbol instanceof AbstractUserDefinedTypeMsSymbol)) { // Not doing typedefs here
|
||||||
|
// procSym(iter);
|
||||||
|
// }
|
||||||
|
// // Increment progress
|
||||||
|
// long delta = globalsIter.getPercentageDone() - percentDone;
|
||||||
|
// monitor.incrementProgress(delta);
|
||||||
|
// percentDone += delta;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1320,13 +1381,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
|
|
||||||
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.setMessage("PDB: Applying typedefs...");
|
monitor.setMessage("PDB: Applying typedefs...");
|
||||||
monitor.initialize(offsets.size());
|
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
|
||||||
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
||||||
|
monitor.initialize(offsets.size());
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -1339,6 +1400,28 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
|
||||||
|
// globalSymbolInformation.iterator();
|
||||||
|
// monitor.initialize(100L);
|
||||||
|
// long percentDone = 0;
|
||||||
|
// while (globalsIter.hasNext()) {
|
||||||
|
// monitor.checkCancelled();
|
||||||
|
// Long offset = globalsIter.next();
|
||||||
|
// iter.initGetByOffset(offset);
|
||||||
|
// if (!iter.hasNext()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// AbstractMsSymbol symbol = iter.peek();
|
||||||
|
// pdbApplicatorMetrics.witnessGlobalSymbolType(symbol);
|
||||||
|
// if (symbol instanceof AbstractUserDefinedTypeMsSymbol) { // Doing typedefs here
|
||||||
|
// procSym(iter);
|
||||||
|
// }
|
||||||
|
// // Increment progress
|
||||||
|
// long delta = globalsIter.getPercentageDone() - percentDone;
|
||||||
|
// monitor.incrementProgress(delta);
|
||||||
|
// percentDone += delta;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1378,7 +1461,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
monitor.initialize(offsetsRemaining.size());
|
monitor.initialize(offsetsRemaining.size());
|
||||||
//getCategoryUtils().setModuleTypedefsCategory(null);
|
//getCategoryUtils().setModuleTypedefsCategory(null);
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
for (long offset : offsetsRemaining) {
|
for (long offset : offsetsRemaining) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -1414,7 +1497,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
@SuppressWarnings("unused") // for method not being called.
|
@SuppressWarnings("unused") // for method not being called.
|
||||||
private boolean processLinkerSymbols() throws CancelledException {
|
private boolean processLinkerSymbols() throws CancelledException, PdbException {
|
||||||
|
|
||||||
SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber);
|
SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber);
|
||||||
if (symbolGroup == null) {
|
if (symbolGroup == null) {
|
||||||
|
@ -1426,7 +1509,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
monitor.setMessage("PDB: Applying " + symbolGroup.size() + " linker symbol components...");
|
monitor.setMessage("PDB: Applying " + symbolGroup.size() + " linker symbol components...");
|
||||||
monitor.initialize(symbolGroup.size());
|
monitor.initialize(symbolGroup.size());
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek());
|
pdbApplicatorMetrics.witnessLinkerSymbolType(iter.peek());
|
||||||
|
@ -1438,20 +1521,21 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
@Override
|
@Override
|
||||||
public List<PeCoffSectionMsSymbol> getLinkerPeCoffSectionSymbols() throws CancelledException {
|
public List<PeCoffSectionMsSymbol> getLinkerPeCoffSectionSymbols()
|
||||||
|
throws CancelledException, PdbException {
|
||||||
processLinkerModuleSpecialInformation();
|
processLinkerModuleSpecialInformation();
|
||||||
return linkerPeCoffSectionSymbols;
|
return linkerPeCoffSectionSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
@Override
|
@Override
|
||||||
public AbstractMsSymbol getLinkerModuleCompileSymbol() throws CancelledException {
|
public AbstractMsSymbol getLinkerModuleCompileSymbol() throws CancelledException, PdbException {
|
||||||
processLinkerModuleSpecialInformation();
|
processLinkerModuleSpecialInformation();
|
||||||
return compileSymbolForLinkerModule;
|
return compileSymbolForLinkerModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private void processLinkerModuleSpecialInformation() throws CancelledException {
|
private void processLinkerModuleSpecialInformation() throws CancelledException, PdbException {
|
||||||
|
|
||||||
if (processedLinkerModule) {
|
if (processedLinkerModule) {
|
||||||
return;
|
return;
|
||||||
|
@ -1465,7 +1549,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
|
|
||||||
TaskMonitor monitor = getMonitor();
|
TaskMonitor monitor = getMonitor();
|
||||||
monitor.initialize(symbolGroup.size());
|
monitor.initialize(symbolGroup.size());
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
int numCompileSymbols = 0;
|
int numCompileSymbols = 0;
|
||||||
int compileSymbolNumForCoffSymbols = -1;
|
int compileSymbolNumForCoffSymbols = -1;
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
|
@ -1511,7 +1595,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
private void processThunkSymbolsFromNonLinkerModules() throws CancelledException {
|
private void processThunkSymbolsFromNonLinkerModules() throws CancelledException, PdbException {
|
||||||
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
|
@ -1546,7 +1630,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
if (symbolGroup == null) {
|
if (symbolGroup == null) {
|
||||||
continue; // should not happen
|
continue; // should not happen
|
||||||
}
|
}
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
AbstractMsSymbol symbol = iter.peek();
|
AbstractMsSymbol symbol = iter.peek();
|
||||||
|
@ -1566,12 +1650,12 @@ public class DefaultPdbApplicator implements PdbApplicator {
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
MsSymbolApplier getSymbolApplier(AbstractMsSymbolIterator iter) throws CancelledException {
|
MsSymbolApplier getSymbolApplier(MsSymbolIterator iter) throws CancelledException {
|
||||||
return symbolApplierParser.getSymbolApplier(iter);
|
return symbolApplierParser.getSymbolApplier(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
void procSym(AbstractMsSymbolIterator iter) throws CancelledException {
|
void procSym(MsSymbolIterator iter) throws CancelledException {
|
||||||
try {
|
try {
|
||||||
MsSymbolApplier applier = getSymbolApplier(iter);
|
MsSymbolApplier applier = getSymbolApplier(iter);
|
||||||
applier.apply();
|
applier.apply();
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public class DefinedSingleAddressRangeSymbolApplier extends MsSymbolApplier {
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public DefinedSingleAddressRangeSymbolApplier(DefaultPdbApplicator applicator,
|
public DefinedSingleAddressRangeSymbolApplier(DefaultPdbApplicator applicator,
|
||||||
AbstractMsSymbolIterator iter) {
|
MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractDefinedSingleAddressRangeMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractDefinedSingleAddressRangeMsSymbol)) {
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +30,7 @@ public class EndSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public EndSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public EndSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof EndMsSymbol ||
|
if (!(abstractSymbol instanceof EndMsSymbol ||
|
||||||
|
@ -43,8 +43,8 @@ public class EndSymbolApplier extends MsSymbolApplier {
|
||||||
@Override
|
@Override
|
||||||
void apply() throws PdbException {
|
void apply() throws PdbException {
|
||||||
pdbLogAndInfoMessage(this,
|
pdbLogAndInfoMessage(this,
|
||||||
String.format("Cannot apply %s directly to program (module:0X%04X, offset:0X%08X)",
|
String.format("Cannot apply %s directly to program (stream:0X%04X, offset:0X%08X)",
|
||||||
this.getClass().getSimpleName(), iter.getModuleNumber(), iter.getCurrentOffset()));
|
this.getClass().getSimpleName(), iter.getStreamNumber(), iter.getCurrentOffset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.ExtraFrameAndProcedureInformationMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.ExtraFrameAndProcedureInformationMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class FrameAndProcedureInformationSymbolApplier extends MsSymbolApplier {
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public FrameAndProcedureInformationSymbolApplier(DefaultPdbApplicator applicator,
|
public FrameAndProcedureInformationSymbolApplier(DefaultPdbApplicator applicator,
|
||||||
AbstractMsSymbolIterator iter) {
|
MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof ExtraFrameAndProcedureInformationMsSymbol)) {
|
if (!(abstractSymbol instanceof ExtraFrameAndProcedureInformationMsSymbol)) {
|
||||||
|
|
|
@ -19,10 +19,8 @@ import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
import ghidra.app.cmd.function.ApplyFunctionSignatureCmd;
|
||||||
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
@ -69,7 +67,7 @@ public class FunctionSymbolApplier extends MsSymbolApplier
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public FunctionSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter)
|
public FunctionSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
|
|
|
@ -18,10 +18,10 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractLabelMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractLabelMsSymbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
@ -42,7 +42,7 @@ public class LabelSymbolApplier extends MsSymbolApplier implements DeferrableFun
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public LabelSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public LabelSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractLabelMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractLabelMsSymbol)) {
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -33,8 +33,7 @@ public class LocalOptimizedSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public LocalOptimizedSymbolApplier(DefaultPdbApplicator applicator,
|
public LocalOptimizedSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
AbstractMsSymbolIterator iter) {
|
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractLocalSymbolInOptimizedCodeMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractLocalSymbolInOptimizedCodeMsSymbol)) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
import ghidra.app.cmd.function.CallDepthChangeInfo;
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractManagedProcedureMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractManagedProcedureMsSymbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
|
@ -26,7 +27,6 @@ import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodDef.CliMethodDefRo
|
||||||
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodImpl.CliMethodImplRow;
|
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodImpl.CliMethodImplRow;
|
||||||
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodSemantics.CliMethodSemanticsRow;
|
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodSemantics.CliMethodSemanticsRow;
|
||||||
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodSpec.CliMethodSpecRow;
|
import ghidra.app.util.bin.format.pe.cli.tables.CliTableMethodSpec.CliMethodSpecRow;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
@ -80,8 +80,8 @@ public class ManagedProcedureSymbolApplier extends MsSymbolApplier
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator,
|
public ManagedProcedureSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter)
|
||||||
AbstractMsSymbolIterator iter) throws CancelledException {
|
throws CancelledException {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
symbolBlockNestingLevel = 0;
|
symbolBlockNestingLevel = 0;
|
||||||
|
|
|
@ -18,10 +18,8 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.symbol.Symbol;
|
import ghidra.app.plugin.processors.sleigh.symbol.Symbol;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbLog;
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +31,7 @@ import ghidra.util.exception.CancelledException;
|
||||||
*/
|
*/
|
||||||
public abstract class MsSymbolApplier {
|
public abstract class MsSymbolApplier {
|
||||||
protected DefaultPdbApplicator applicator;
|
protected DefaultPdbApplicator applicator;
|
||||||
protected AbstractMsSymbolIterator iter;
|
protected MsSymbolIterator iter;
|
||||||
protected long currentOffset;
|
protected long currentOffset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +39,7 @@ public abstract class MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public MsSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public MsSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
Objects.requireNonNull(applicator, "applicator cannot be null");
|
Objects.requireNonNull(applicator, "applicator cannot be null");
|
||||||
Objects.requireNonNull(iter, "iter cannot be null");
|
Objects.requireNonNull(iter, "iter cannot be null");
|
||||||
this.applicator = applicator;
|
this.applicator = applicator;
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dummy {@link MsSymbolApplier}, which, at a minimum, reads the symbol from the
|
* A dummy {@link MsSymbolApplier}, which, at a minimum, reads the symbol from the
|
||||||
|
@ -32,7 +32,7 @@ public class NoSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public NoSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public NoSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
symbol = iter.next();
|
symbol = iter.next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
@ -35,7 +36,7 @@ abstract class PdbAddressCalculator {
|
||||||
private int maxSegment;
|
private int maxSegment;
|
||||||
|
|
||||||
static PdbAddressCalculator chooseAddressCalculator(PdbApplicator applicator, Address imageBase)
|
static PdbAddressCalculator chooseAddressCalculator(PdbApplicator applicator, Address imageBase)
|
||||||
throws CancelledException {
|
throws CancelledException, PdbException, IOException {
|
||||||
|
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
PdbDebugInfo dbi = pdb.getDebugInfo();
|
PdbDebugInfo dbi = pdb.getDebugInfo();
|
||||||
|
@ -91,7 +92,7 @@ abstract class PdbAddressCalculator {
|
||||||
// We wouldn't have this method if we hadn't found an example where what is supposed to be
|
// We wouldn't have this method if we hadn't found an example where what is supposed to be
|
||||||
// an RVA in PeCoffSection is instead a VA. Issue found in one Delphi example. All other
|
// an RVA in PeCoffSection is instead a VA. Issue found in one Delphi example. All other
|
||||||
// non-Delphi examples seem to have RVA.
|
// non-Delphi examples seem to have RVA.
|
||||||
static long getCorrection(PdbApplicator applicator) throws CancelledException {
|
static long getCorrection(PdbApplicator applicator) throws CancelledException, PdbException {
|
||||||
|
|
||||||
AbstractMsSymbol symbol = applicator.getLinkerModuleCompileSymbol();
|
AbstractMsSymbol symbol = applicator.getLinkerModuleCompileSymbol();
|
||||||
String name = "";
|
String name = "";
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
|
@ -79,9 +80,11 @@ public class PdbAddressManager {
|
||||||
* @param imageBase Address from which all other addresses are based.
|
* @param imageBase Address from which all other addresses are based.
|
||||||
* @throws PdbException If Program is null;
|
* @throws PdbException If Program is null;
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
*/
|
*/
|
||||||
PdbAddressManager(DefaultPdbApplicator applicator, Address imageBase)
|
PdbAddressManager(DefaultPdbApplicator applicator, Address imageBase)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException, IOException {
|
||||||
Objects.requireNonNull(applicator, "applicator may not be null");
|
Objects.requireNonNull(applicator, "applicator may not be null");
|
||||||
Objects.requireNonNull(imageBase, "imageBase may not be null");
|
Objects.requireNonNull(imageBase, "imageBase may not be null");
|
||||||
this.applicator = applicator;
|
this.applicator = applicator;
|
||||||
|
@ -336,7 +339,14 @@ public class PdbAddressManager {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private void determineMemoryBlocks() {
|
/**
|
||||||
|
* Determines memory blocks
|
||||||
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon error in processing components
|
||||||
|
* @throws IOException on file seek or read, invalid parameters, bad file configuration, or
|
||||||
|
* inability to read required bytes
|
||||||
|
*/
|
||||||
|
private void determineMemoryBlocks() throws CancelledException, PdbException, IOException {
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
segmentMapList = debugInfo.getSegmentMapList();
|
segmentMapList = debugInfo.getSegmentMapList();
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.AbstractPdb;
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -62,15 +63,18 @@ public interface PdbApplicator {
|
||||||
* Returns the {@link PeCoffSectionMsSymbol}s from the "Linker" module
|
* Returns the {@link PeCoffSectionMsSymbol}s from the "Linker" module
|
||||||
* @return list of symbols
|
* @return list of symbols
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
|
* @throws PdbException upon issue creating an iterator
|
||||||
*/
|
*/
|
||||||
public List<PeCoffSectionMsSymbol> getLinkerPeCoffSectionSymbols() throws CancelledException;
|
public List<PeCoffSectionMsSymbol> getLinkerPeCoffSectionSymbols()
|
||||||
|
throws CancelledException, PdbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
* @throws PdbException upon issue creating an iterator
|
||||||
*/
|
*/
|
||||||
public AbstractMsSymbol getLinkerModuleCompileSymbol() throws CancelledException;
|
public AbstractMsSymbol getLinkerModuleCompileSymbol() throws CancelledException, PdbException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.CompilerSpec;
|
import ghidra.program.model.lang.CompilerSpec;
|
||||||
|
@ -337,8 +336,7 @@ public class PdbResearch {
|
||||||
|
|
||||||
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>"
|
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(
|
.equals(nn)) {
|
||||||
nn)) {
|
|
||||||
doNothingSetBreakPointHere();
|
doNothingSetBreakPointHere();
|
||||||
}
|
}
|
||||||
if ("class std::__1::__iostream_category".equals(nn)) {
|
if ("class std::__1::__iostream_category".equals(nn)) {
|
||||||
|
@ -430,7 +428,7 @@ public class PdbResearch {
|
||||||
monitor.setMessage("PDB: Applying typedefs...");
|
monitor.setMessage("PDB: Applying typedefs...");
|
||||||
monitor.initialize(offsets.size());
|
monitor.initialize(offsets.size());
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -441,8 +439,8 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static private boolean childWalkSym(DefaultPdbApplicator applicator, int moduleNumber,
|
static private boolean childWalkSym(DefaultPdbApplicator applicator, int streamNumber,
|
||||||
AbstractMsSymbolIterator iter) throws PdbException, CancelledException {
|
MsSymbolIterator iter) throws PdbException, CancelledException {
|
||||||
if (!iter.hasNext()) {
|
if (!iter.hasNext()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -459,18 +457,18 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
else if (applier instanceof ReferenceSymbolApplier) {
|
else if (applier instanceof ReferenceSymbolApplier) {
|
||||||
ReferenceSymbolApplier refSymbolApplier = (ReferenceSymbolApplier) applier;
|
ReferenceSymbolApplier refSymbolApplier = (ReferenceSymbolApplier) applier;
|
||||||
AbstractMsSymbolIterator refIter =
|
MsSymbolIterator refIter =
|
||||||
refSymbolApplier.getInitializedReferencedSymbolGroupIterator();
|
refSymbolApplier.getInitializedReferencedSymbolGroupIterator();
|
||||||
if (refIter == null) {
|
if (refIter == null) {
|
||||||
throw new PdbException("PDB: Referenced Symbol Error - not refIter");
|
throw new PdbException("PDB: Referenced Symbol Error - not refIter");
|
||||||
}
|
}
|
||||||
// recursion
|
// recursion
|
||||||
childWalkSym(applicator, refIter.getModuleNumber(), refIter);
|
childWalkSym(applicator, refIter.getStreamNumber(), refIter);
|
||||||
}
|
}
|
||||||
else if (applier instanceof DataSymbolApplier) {
|
else if (applier instanceof DataSymbolApplier) {
|
||||||
DataSymbolApplier dataSymbolApplier = (DataSymbolApplier) applier;
|
DataSymbolApplier dataSymbolApplier = (DataSymbolApplier) applier;
|
||||||
MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier();
|
MsTypeApplier typeApplier = dataSymbolApplier.getTypeApplier();
|
||||||
childWalkType(moduleNumber, typeApplier);
|
childWalkType(streamNumber, typeApplier);
|
||||||
}
|
}
|
||||||
else if (applier instanceof FunctionSymbolApplier) {
|
else if (applier instanceof FunctionSymbolApplier) {
|
||||||
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applier;
|
FunctionSymbolApplier functionSymbolApplier = (FunctionSymbolApplier) applier;
|
||||||
|
@ -620,7 +618,7 @@ public class PdbResearch {
|
||||||
* reuse caused by Templates and/or Identical Code Folding.
|
* reuse caused by Templates and/or Identical Code Folding.
|
||||||
*/
|
*/
|
||||||
static void studyAggregateSymbols(DefaultPdbApplicator applicator, TaskMonitor monitor)
|
static void studyAggregateSymbols(DefaultPdbApplicator applicator, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException, PdbException {
|
||||||
Map<Address, List<Stuff>> mapByAddress = new HashMap<>();
|
Map<Address, List<Stuff>> mapByAddress = new HashMap<>();
|
||||||
processPublicSymbols(applicator, mapByAddress, monitor);
|
processPublicSymbols(applicator, mapByAddress, monitor);
|
||||||
processGlobalSymbols(applicator, mapByAddress, monitor);
|
processGlobalSymbols(applicator, mapByAddress, monitor);
|
||||||
|
@ -629,7 +627,8 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processPublicSymbols(DefaultPdbApplicator applicator,
|
private static void processPublicSymbols(DefaultPdbApplicator applicator,
|
||||||
Map<Address, List<Stuff>> map, TaskMonitor monitor) throws CancelledException {
|
Map<Address, List<Stuff>> map, TaskMonitor monitor)
|
||||||
|
throws CancelledException, PdbException {
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
|
@ -644,11 +643,10 @@ public class PdbResearch {
|
||||||
|
|
||||||
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
|
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
|
||||||
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
List<Long> offsets = publicSymbolInformation.getModifiedHashRecordSymbolOffsets();
|
||||||
monitor.setMessage(
|
monitor.setMessage("PDB: Applying " + offsets.size() + " public symbol components...");
|
||||||
"PDB: Applying " + offsets.size() + " public symbol components...");
|
|
||||||
monitor.initialize(offsets.size());
|
monitor.initialize(offsets.size());
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -664,7 +662,8 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processGlobalSymbols(DefaultPdbApplicator applicator,
|
private static void processGlobalSymbols(DefaultPdbApplicator applicator,
|
||||||
Map<Address, List<Stuff>> map, TaskMonitor monitor) throws CancelledException {
|
Map<Address, List<Stuff>> map, TaskMonitor monitor)
|
||||||
|
throws CancelledException, PdbException {
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
|
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
|
@ -682,7 +681,7 @@ public class PdbResearch {
|
||||||
monitor.setMessage("PDB: Applying global symbols...");
|
monitor.setMessage("PDB: Applying global symbols...");
|
||||||
monitor.initialize(offsets.size());
|
monitor.initialize(offsets.size());
|
||||||
|
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
@ -698,7 +697,8 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processModuleSymbols(DefaultPdbApplicator applicator,
|
private static void processModuleSymbols(DefaultPdbApplicator applicator,
|
||||||
Map<Address, List<Stuff>> map, TaskMonitor monitor) throws CancelledException {
|
Map<Address, List<Stuff>> map, TaskMonitor monitor)
|
||||||
|
throws CancelledException, PdbException {
|
||||||
AbstractPdb pdb = applicator.getPdb();
|
AbstractPdb pdb = applicator.getPdb();
|
||||||
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
PdbDebugInfo debugInfo = pdb.getDebugInfo();
|
||||||
if (debugInfo == null) {
|
if (debugInfo == null) {
|
||||||
|
@ -715,8 +715,7 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
totalCount += symbolGroup.size();
|
totalCount += symbolGroup.size();
|
||||||
}
|
}
|
||||||
monitor.setMessage(
|
monitor.setMessage("PDB: Applying " + totalCount + " module symbol components...");
|
||||||
"PDB: Applying " + totalCount + " module symbol components...");
|
|
||||||
monitor.initialize(totalCount);
|
monitor.initialize(totalCount);
|
||||||
|
|
||||||
// Process symbols list for each module
|
// Process symbols list for each module
|
||||||
|
@ -731,7 +730,7 @@ public class PdbResearch {
|
||||||
if (symbolGroup == null) {
|
if (symbolGroup == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
AbstractMsSymbolIterator iter = symbolGroup.iterator();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
processSymbolGroup(applicator, map, moduleNumber, iter, monitor);
|
processSymbolGroup(applicator, map, moduleNumber, iter, monitor);
|
||||||
// do not call monitor.incrementProgress(1) here, as it is updated inside of
|
// do not call monitor.incrementProgress(1) here, as it is updated inside of
|
||||||
// processSymbolGroup.
|
// processSymbolGroup.
|
||||||
|
@ -739,7 +738,7 @@ public class PdbResearch {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processSymbolGroup(DefaultPdbApplicator applicator,
|
private static void processSymbolGroup(DefaultPdbApplicator applicator,
|
||||||
Map<Address, List<Stuff>> map, int moduleNumber, AbstractMsSymbolIterator iter,
|
Map<Address, List<Stuff>> map, int moduleNumber, MsSymbolIterator iter,
|
||||||
TaskMonitor monitor) throws CancelledException {
|
TaskMonitor monitor) throws CancelledException {
|
||||||
iter.initGet();
|
iter.initGet();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.util.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
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.symbol.AbstractPublicMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractPublicMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
import ghidra.program.model.data.DataTypeManager;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -50,7 +49,7 @@ public class PdbVbtManager extends VbtManager {
|
||||||
// If we find some this way, then need to modify PdbVbtManager to also look
|
// If we find some this way, then need to modify PdbVbtManager to also look
|
||||||
// through the loader symbol for them.
|
// through the loader symbol for them.
|
||||||
private static Map<String, Address> findVirtualBaseTableSymbols(DefaultPdbApplicator applicator)
|
private static Map<String, Address> findVirtualBaseTableSymbols(DefaultPdbApplicator applicator)
|
||||||
throws CancelledException {
|
throws CancelledException, PdbException {
|
||||||
|
|
||||||
TaskMonitor monitor = applicator.getMonitor();
|
TaskMonitor monitor = applicator.getMonitor();
|
||||||
Map<String, Address> myAddressByMangledName = new HashMap<>();
|
Map<String, Address> myAddressByMangledName = new HashMap<>();
|
||||||
|
@ -71,7 +70,7 @@ public class PdbVbtManager extends VbtManager {
|
||||||
monitor.setMessage("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();
|
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
|
||||||
for (long offset : offsets) {
|
for (long offset : offsets) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
iter.initGetByOffset(offset);
|
iter.initGetByOffset(offset);
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.PeCoffGroupMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.PeCoffGroupMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -35,8 +35,7 @@ public class PeCoffGroupSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator,
|
public PeCoffGroupSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
AbstractMsSymbolIterator iter) {
|
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof PeCoffGroupMsSymbol)) {
|
if (!(abstractSymbol instanceof PeCoffGroupMsSymbol)) {
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.PeCoffSectionMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.PeCoffSectionMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -34,8 +34,7 @@ public class PeCoffSectionSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public PeCoffSectionSymbolApplier(DefaultPdbApplicator applicator,
|
public PeCoffSectionSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
AbstractMsSymbolIterator iter) {
|
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof PeCoffSectionMsSymbol)) {
|
if (!(abstractSymbol instanceof PeCoffSectionMsSymbol)) {
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.AbstractPublicMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractPublicMsSymbol;
|
||||||
import ghidra.app.util.datatype.microsoft.GuidDataType;
|
import ghidra.app.util.datatype.microsoft.GuidDataType;
|
||||||
import ghidra.app.util.datatype.microsoft.GuidUtil;
|
import ghidra.app.util.datatype.microsoft.GuidUtil;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.DataUtilities;
|
import ghidra.program.model.data.DataUtilities;
|
||||||
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
|
@ -43,7 +43,7 @@ public class PublicSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public PublicSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public PublicSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractPublicMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractPublicMsSymbol)) {
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.AbstractReferenceMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractReferenceMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public class ReferenceSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public ReferenceSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public ReferenceSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractReferenceMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractReferenceMsSymbol)) {
|
||||||
|
@ -52,19 +52,19 @@ public class ReferenceSymbolApplier extends MsSymbolApplier {
|
||||||
@Override
|
@Override
|
||||||
void apply() throws CancelledException, PdbException {
|
void apply() throws CancelledException, PdbException {
|
||||||
// Potential recursive call via applicator.procSym().
|
// Potential recursive call via applicator.procSym().
|
||||||
AbstractMsSymbolIterator refIter = getInitializedReferencedSymbolGroupIterator();
|
MsSymbolIterator refIter = getInitializedReferencedSymbolGroupIterator();
|
||||||
if (refIter == null) {
|
if (refIter == null) {
|
||||||
throw new PdbException("PDB: Referenced Symbol Error - null refIter");
|
throw new PdbException("PDB: Referenced Symbol Error - null refIter");
|
||||||
}
|
}
|
||||||
applicator.procSym(refIter);
|
applicator.procSym(refIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractMsSymbolIterator getInitializedReferencedSymbolGroupIterator() {
|
MsSymbolIterator getInitializedReferencedSymbolGroupIterator() throws PdbException {
|
||||||
SymbolGroup refSymbolGroup = getReferencedSymbolGroup();
|
SymbolGroup refSymbolGroup = getReferencedSymbolGroup();
|
||||||
if (refSymbolGroup == null) {
|
if (refSymbolGroup == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
AbstractMsSymbolIterator refIter = refSymbolGroup.iterator();
|
MsSymbolIterator refIter = refSymbolGroup.getSymbolIterator();
|
||||||
refIter.initGetByOffset(getOffsetInReferencedSymbolGroup());
|
refIter.initGetByOffset(getOffsetInReferencedSymbolGroup());
|
||||||
return refIter;
|
return refIter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.AbstractRegisterRelativeAddressMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractRegisterRelativeAddressMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -40,7 +40,7 @@ public class RegisterRelativeSymbolApplier extends MsSymbolApplier {
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public RegisterRelativeSymbolApplier(DefaultPdbApplicator applicator,
|
public RegisterRelativeSymbolApplier(DefaultPdbApplicator applicator,
|
||||||
AbstractMsSymbolIterator iter) {
|
MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractRegisterRelativeAddressMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractRegisterRelativeAddressMsSymbol)) {
|
||||||
|
|
|
@ -19,9 +19,9 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.cmd.comments.SetCommentCmd;
|
import ghidra.app.cmd.comments.SetCommentCmd;
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.SeparatedCodeFromCompilerSupportMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.SeparatedCodeFromCompilerSupportMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.CodeUnit;
|
import ghidra.program.model.listing.CodeUnit;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -46,7 +46,7 @@ public class SeparatedCodeSymbolApplier extends MsSymbolApplier {
|
||||||
|
|
||||||
private List<MsSymbolApplier> allAppliers = new ArrayList<>();
|
private List<MsSymbolApplier> allAppliers = new ArrayList<>();
|
||||||
|
|
||||||
private static AbstractMsSymbolIterator validateSymbol(AbstractMsSymbolIterator iter) {
|
private static MsSymbolIterator validateSymbol(MsSymbolIterator iter) {
|
||||||
if (!(iter.peek() instanceof SeparatedCodeFromCompilerSupportMsSymbol)) {
|
if (!(iter.peek() instanceof SeparatedCodeFromCompilerSupportMsSymbol)) {
|
||||||
throw new IllegalArgumentException("Not a SeparatedCodeFromCompilerSupportMsSymbol");
|
throw new IllegalArgumentException("Not a SeparatedCodeFromCompilerSupportMsSymbol");
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class SeparatedCodeSymbolApplier extends MsSymbolApplier {
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public SeparatedCodeSymbolApplier(DefaultPdbApplicator applicator,
|
public SeparatedCodeSymbolApplier(DefaultPdbApplicator applicator,
|
||||||
AbstractMsSymbolIterator iter) throws CancelledException {
|
MsSymbolIterator iter) throws CancelledException {
|
||||||
super(applicator, validateSymbol(iter));
|
super(applicator, validateSymbol(iter));
|
||||||
|
|
||||||
symbol = (SeparatedCodeFromCompilerSupportMsSymbol) iter.next();
|
symbol = (SeparatedCodeFromCompilerSupportMsSymbol) iter.next();
|
||||||
|
@ -111,7 +111,9 @@ public class SeparatedCodeSymbolApplier extends MsSymbolApplier {
|
||||||
|
|
||||||
private void setComments(boolean enabled) {
|
private void setComments(boolean enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
String existingComment = applicator.getProgram().getListing().getComment(
|
String existingComment = applicator.getProgram()
|
||||||
|
.getListing()
|
||||||
|
.getComment(
|
||||||
CodeUnit.PRE_COMMENT, specifiedAddress);
|
CodeUnit.PRE_COMMENT, specifiedAddress);
|
||||||
String p = "*************************************************************\n";
|
String p = "*************************************************************\n";
|
||||||
String newComment =
|
String newComment =
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +36,7 @@ public class SymbolApplierFactory {
|
||||||
// the AbstractMsSymbol (do one for AbstractMsType as well)? Symbols are different in that
|
// the AbstractMsSymbol (do one for AbstractMsType as well)? Symbols are different in that
|
||||||
// we are using SymbolGroup as a member instead of MsType.
|
// we are using SymbolGroup as a member instead of MsType.
|
||||||
|
|
||||||
MsSymbolApplier getSymbolApplier(AbstractMsSymbolIterator iter) throws CancelledException {
|
MsSymbolApplier getSymbolApplier(MsSymbolIterator iter) throws CancelledException {
|
||||||
|
|
||||||
AbstractMsSymbol symbol = iter.peek();
|
AbstractMsSymbol symbol = iter.peek();
|
||||||
if (symbol == null) {
|
if (symbol == null) {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.io.Writer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
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;
|
||||||
|
@ -157,28 +156,14 @@ public class SymbolGroup {
|
||||||
writer.write("\nEnd SymbolGroup---------------------------------------------\n");
|
writer.write("\nEnd SymbolGroup---------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractMsSymbolIterator iterator() {
|
|
||||||
return new AbstractMsSymbolIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
/**
|
public MsSymbolIterator getSymbolIterator() throws PdbException {
|
||||||
* Iterator for {@link SymbolGroup} that iterates through {@link AbstractMsSymbol
|
int streamNumber;
|
||||||
* AbstractMsSymbols}
|
int startingOffset;
|
||||||
*/
|
int lengthSymbols;
|
||||||
class AbstractMsSymbolIterator implements Iterator<AbstractMsSymbol> {
|
|
||||||
|
|
||||||
private SymbolRecords symbolRecords;
|
|
||||||
private int streamNumber;
|
|
||||||
private int lengthSymbols;
|
|
||||||
private int nextRetrieveOffset;
|
|
||||||
private SymbolRecords.SymLen symLen;
|
|
||||||
|
|
||||||
public AbstractMsSymbolIterator() {
|
|
||||||
symbolRecords = pdb.getDebugInfo().getSymbolRecords();
|
|
||||||
try {
|
|
||||||
if (moduleNumber == 0) {
|
if (moduleNumber == 0) {
|
||||||
streamNumber = pdb.getDebugInfo().getSymbolRecordsStreamNumber();
|
streamNumber = pdb.getDebugInfo().getSymbolRecordsStreamNumber();
|
||||||
|
startingOffset = 0;
|
||||||
lengthSymbols = Integer.MAX_VALUE;
|
lengthSymbols = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -186,123 +171,23 @@ public class SymbolGroup {
|
||||||
pdb.getDebugInfo().getModuleInformation(moduleNumber);
|
pdb.getDebugInfo().getModuleInformation(moduleNumber);
|
||||||
streamNumber = moduleInfo.getStreamNumberDebugInformation();
|
streamNumber = moduleInfo.getStreamNumberDebugInformation();
|
||||||
lengthSymbols = moduleInfo.getSizeLocalSymbolsDebugInformation();
|
lengthSymbols = moduleInfo.getSizeLocalSymbolsDebugInformation();
|
||||||
|
|
||||||
}
|
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
|
||||||
int a = 1;
|
|
||||||
a = a + 1;
|
|
||||||
symLen = null;
|
|
||||||
nextRetrieveOffset = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
initGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (PdbException e) {
|
|
||||||
symLen = null;
|
|
||||||
nextRetrieveOffset = 0;
|
|
||||||
Msg.warn(this, "Could not retrieve moduleInfo for module number: " + moduleNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return (symLen != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Peeks at and returns the next symbol without incrementing to the next. If none are
|
|
||||||
* left, then throws NoSuchElementException and reinitializes the state for a new
|
|
||||||
* iteration.
|
|
||||||
* @see #initGet()
|
|
||||||
* @return the next symbol
|
|
||||||
* @throws NoSuchElementException if there are no more elements
|
|
||||||
*/
|
|
||||||
public AbstractMsSymbol peek() throws NoSuchElementException {
|
|
||||||
if (symLen == null) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
return symLen.symbol();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbstractMsSymbol next() {
|
|
||||||
if (symLen == null) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
SymbolRecords.SymLen offer = symLen;
|
|
||||||
symLen = retrieveRecord();
|
|
||||||
return offer.symbol();
|
|
||||||
}
|
|
||||||
|
|
||||||
private SymbolRecords.SymLen retrieveRecord() {
|
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (nextRetrieveOffset >= lengthSymbols) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
SymbolRecords.SymLen retrieved =
|
startingOffset = pdb.getDebugInfo().getSymbolRecords().getCvSigLength(streamNumber);
|
||||||
symbolRecords.getRandomAccessRecord(streamNumber, nextRetrieveOffset);
|
|
||||||
nextRetrieveOffset += retrieved.length();
|
|
||||||
return retrieved;
|
|
||||||
}
|
}
|
||||||
catch (PdbException | CancelledException e) {
|
catch (IOException e) {
|
||||||
return null;
|
Msg.warn(this, "PDB issue reading stream when initializing iterator for stream " +
|
||||||
|
streamNumber);
|
||||||
|
startingOffset = 0;
|
||||||
|
lengthSymbols = 0; // essentially null out iterator with zero length
|
||||||
}
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
startingOffset = 0;
|
||||||
|
lengthSymbols = 0; // essentially null out iterator with zero length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new MsSymbolIterator(pdb, streamNumber, startingOffset, lengthSymbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//==============================================================================================
|
||||||
* Returns the next symbol. If none are left, then throws NoSuchElementException and
|
|
||||||
* reinitializes the state for a new iteration.
|
|
||||||
* @see #initGet()
|
|
||||||
* @return the next symbol
|
|
||||||
* @throws NoSuchElementException if there are no more elements
|
|
||||||
*/
|
|
||||||
long getCurrentOffset() {
|
|
||||||
if (symLen == null) {
|
|
||||||
throw new NoSuchElementException();
|
|
||||||
}
|
|
||||||
return nextRetrieveOffset - symLen.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialized the mechanism for requesting the symbols in sequence.
|
|
||||||
* @see #hasNext()
|
|
||||||
*/
|
|
||||||
void initGet() {
|
|
||||||
if (streamNumber == MsfStream.NIL_STREAM_NUMBER) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
nextRetrieveOffset = symbolRecords.getCvSigLength(streamNumber);
|
|
||||||
symLen = retrieveRecord();
|
|
||||||
}
|
|
||||||
catch (PdbException | CancelledException | IOException e) {
|
|
||||||
nextRetrieveOffset = 0;
|
|
||||||
symLen = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialized the mechanism for requesting the symbols in sequence.
|
|
||||||
* @param offset the offset to which to initialize the mechanism.
|
|
||||||
* @see #hasNext()
|
|
||||||
*/
|
|
||||||
void initGetByOffset(long offset) {
|
|
||||||
Long l = offset;
|
|
||||||
nextRetrieveOffset = l.intValue();
|
|
||||||
symLen = retrieveRecord();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the module number.
|
|
||||||
* @return the module number.
|
|
||||||
*/
|
|
||||||
int getModuleNumber() {
|
|
||||||
return moduleNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.TrampolineMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.TrampolineMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
@ -38,7 +38,7 @@ public class TrampolineSymbolApplier extends MsSymbolApplier
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public TrampolineSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public TrampolineSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof TrampolineMsSymbol)) {
|
if (!(abstractSymbol instanceof TrampolineMsSymbol)) {
|
||||||
|
|
|
@ -16,11 +16,9 @@
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
import ghidra.app.util.SymbolPath;
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
|
|
||||||
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.symbol.AbstractUserDefinedTypeMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractUserDefinedTypeMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -38,7 +36,7 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public TypedefSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public TypedefSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractUserDefinedTypeMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractUserDefinedTypeMsSymbol)) {
|
||||||
|
@ -120,7 +118,7 @@ public class TypedefSymbolApplier extends MsSymbolApplier {
|
||||||
|
|
||||||
SymbolPath symbolPath = new SymbolPath(name);
|
SymbolPath symbolPath = new SymbolPath(name);
|
||||||
CategoryPath categoryPath =
|
CategoryPath categoryPath =
|
||||||
applicator.getTypedefsCategory(iter.getModuleNumber(), symbolPath);
|
applicator.getTypedefsCategory(applicator.getCurrentModuleNumber(), symbolPath);
|
||||||
DataType typedef = new TypedefDataType(categoryPath.getParent(), categoryPath.getName(),
|
DataType typedef = new TypedefDataType(categoryPath.getParent(), categoryPath.getName(),
|
||||||
dataType, applicator.getDataTypeManager());
|
dataType, applicator.getDataTypeManager());
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.pdb.pdbapplicator;
|
package ghidra.app.util.pdb.pdbapplicator;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.format.pdb2.pdbreader.MsSymbolIterator;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
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.symbol.AbstractWithMsSymbol;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.AbstractWithMsSymbol;
|
||||||
import ghidra.app.util.pdb.pdbapplicator.SymbolGroup.AbstractMsSymbolIterator;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -37,7 +37,7 @@ public class WithSymbolApplier extends MsSymbolApplier {
|
||||||
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
* @param applicator the {@link DefaultPdbApplicator} for which we are working.
|
||||||
* @param iter the Iterator containing the symbol sequence being processed
|
* @param iter the Iterator containing the symbol sequence being processed
|
||||||
*/
|
*/
|
||||||
public WithSymbolApplier(DefaultPdbApplicator applicator, AbstractMsSymbolIterator iter) {
|
public WithSymbolApplier(DefaultPdbApplicator applicator, MsSymbolIterator iter) {
|
||||||
super(applicator, iter);
|
super(applicator, iter);
|
||||||
AbstractMsSymbol abstractSymbol = iter.next();
|
AbstractMsSymbol abstractSymbol = iter.next();
|
||||||
if (!(abstractSymbol instanceof AbstractWithMsSymbol)) {
|
if (!(abstractSymbol instanceof AbstractWithMsSymbol)) {
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
package ghidra.app.util.bin.format.pdb2.pdbreader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.StubMsf;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.msf.StubMsf;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
|
||||||
|
@ -29,6 +31,9 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
|
|
||||||
private boolean debugInfoAvailable = true;
|
private boolean debugInfoAvailable = true;
|
||||||
|
|
||||||
|
private Map<RecordNumber, AbstractMsType> dummyTypes = new HashMap<>();
|
||||||
|
private Map<RecordNumber, AbstractMsType> dummyItems = new HashMap<>();
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// API
|
// API
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -42,8 +47,8 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
public DummyPdb700(int tpiIndexMin, int tpiIndexMaxExclusive,
|
public DummyPdb700(int tpiIndexMin, int tpiIndexMaxExclusive, int ipiIndexMin,
|
||||||
int ipiIndexMin, int ipiIndexMaxExclusive) throws IOException, PdbException {
|
int ipiIndexMaxExclusive) throws IOException, PdbException {
|
||||||
super(new StubMsf(), new PdbReaderOptions());
|
super(new StubMsf(), new PdbReaderOptions());
|
||||||
typeProgramInterface =
|
typeProgramInterface =
|
||||||
new DummyTypeProgramInterface800(this, tpiIndexMin, tpiIndexMaxExclusive);
|
new DummyTypeProgramInterface800(this, tpiIndexMin, tpiIndexMaxExclusive);
|
||||||
|
@ -76,7 +81,13 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
* @return {@code 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);
|
int typeIndexMin = typeProgramInterface.getTypeIndexMin();
|
||||||
|
if (recordNumber < typeIndexMin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RecordNumber record = RecordNumber.typeRecordNumber(recordNumber);
|
||||||
|
dummyTypes.put(record, type);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +97,10 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
* @return record number assigned
|
* @return record number assigned
|
||||||
*/
|
*/
|
||||||
public int addTypeRecord(AbstractMsType type) {
|
public int addTypeRecord(AbstractMsType type) {
|
||||||
return typeProgramInterface.addRecord(type);
|
int newRecordNum = dummyTypes.size() + typeProgramInterface.getTypeIndexMin();
|
||||||
|
RecordNumber record = RecordNumber.typeRecordNumber(newRecordNum);
|
||||||
|
dummyTypes.put(record, type);
|
||||||
|
return newRecordNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +111,13 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
* @return {@code 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);
|
int typeIndexMin = itemProgramInterface.getTypeIndexMin();
|
||||||
|
if (recordNumber < typeIndexMin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RecordNumber record = RecordNumber.itemRecordNumber(recordNumber);
|
||||||
|
dummyItems.put(record, type);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +127,48 @@ public class DummyPdb700 extends Pdb700 {
|
||||||
* @return record number assigned
|
* @return record number assigned
|
||||||
*/
|
*/
|
||||||
public int addItemRecord(AbstractMsType type) {
|
public int addItemRecord(AbstractMsType type) {
|
||||||
return itemProgramInterface.addRecord(type);
|
int newRecordNum = dummyItems.size() + itemProgramInterface.getTypeIndexMin();
|
||||||
|
RecordNumber record = RecordNumber.itemRecordNumber(newRecordNum);
|
||||||
|
dummyItems.put(record, type);
|
||||||
|
return newRecordNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractMsType getTypeRecord(RecordNumber recordNumber) {
|
||||||
|
return getTypeRecord(recordNumber, AbstractMsType.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends AbstractMsType> T getTypeRecord(RecordNumber recordNumber,
|
||||||
|
Class<T> typeClass) {
|
||||||
|
recordNumber = fixupTypeIndex(recordNumber, typeClass);
|
||||||
|
AbstractMsType msType = null;
|
||||||
|
if (recordNumber.getCategory() == RecordCategory.TYPE) {
|
||||||
|
int typeIndexMin = typeProgramInterface.getTypeIndexMin();
|
||||||
|
if (recordNumber.getNumber() < typeIndexMin) {
|
||||||
|
msType = typeProgramInterface.getPrimitiveRecord(recordNumber.getNumber());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msType = dummyTypes.get(recordNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int typeIndexMin = itemProgramInterface.getTypeIndexMin();
|
||||||
|
if (recordNumber.getNumber() < typeIndexMin) {
|
||||||
|
// Not sure there is such as thing as an item primitive
|
||||||
|
msType = itemProgramInterface.getPrimitiveRecord(recordNumber.getNumber());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msType = dummyItems.get(recordNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!typeClass.isInstance(msType)) {
|
||||||
|
if (!recordNumber.isNoType()) {
|
||||||
|
PdbLog.logGetTypeClassMismatch(msType, typeClass);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return typeClass.cast(msType);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1536,7 +1536,6 @@ public class TypesTest extends AbstractGenericTest {
|
||||||
String result = type.toString().trim();
|
String result = type.toString().trim();
|
||||||
assertEquals("DummyMsType[0:REGISTER: al, Type: DummyMsType, registerSymbolName][0:void]",
|
assertEquals("DummyMsType[0:REGISTER: al, Type: DummyMsType, registerSymbolName][0:void]",
|
||||||
result);
|
result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue