mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/GP-3714_ghizard_investigate_random_access_datatype_records--SQUASHED'
This commit is contained in:
commit
0a2b9f6fd1
3 changed files with 70 additions and 13 deletions
|
@ -169,8 +169,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
* @throws PdbException upon error in processing components
|
* @throws PdbException upon error in processing components
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
public void deserialize()
|
public void deserialize() throws IOException, PdbException, CancelledException {
|
||||||
throws IOException, PdbException, CancelledException {
|
|
||||||
// msf should only be null for testing versions of PDB.
|
// msf should only be null for testing versions of PDB.
|
||||||
if (msf == null) {
|
if (msf == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -330,6 +329,8 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
recordNumber = fixupTypeIndex(recordNumber, typeClass);
|
recordNumber = fixupTypeIndex(recordNumber, typeClass);
|
||||||
AbstractMsType msType =
|
AbstractMsType msType =
|
||||||
getTPI(recordNumber.getCategory()).getRecord(recordNumber.getNumber());
|
getTPI(recordNumber.getCategory()).getRecord(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);
|
||||||
|
@ -494,8 +495,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
* @throws PdbException upon error in processing components
|
* @throws PdbException upon error in processing components
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
void deserializeSubstreams()
|
void deserializeSubstreams() throws IOException, PdbException, CancelledException {
|
||||||
throws IOException, PdbException, CancelledException {
|
|
||||||
|
|
||||||
if (substreamsDeserialized) {
|
if (substreamsDeserialized) {
|
||||||
return;
|
return;
|
||||||
|
@ -594,8 +594,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
* @throws PdbException upon error parsing a field
|
* @throws PdbException upon error parsing a field
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
abstract void deserializeDirectory()
|
abstract void deserializeDirectory() throws IOException, PdbException, CancelledException;
|
||||||
throws IOException, PdbException, CancelledException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps the PDB Directory to {@link Writer}. This package-protected method is for
|
* Dumps the PDB Directory to {@link Writer}. This package-protected method is for
|
||||||
|
@ -616,8 +615,7 @@ public abstract class AbstractPdb implements AutoCloseable {
|
||||||
* inability to read required bytes
|
* inability to read required bytes
|
||||||
* @throws CancelledException upon user cancellation
|
* @throws CancelledException upon user cancellation
|
||||||
*/
|
*/
|
||||||
protected PdbByteReader getDirectoryReader()
|
protected PdbByteReader getDirectoryReader() throws IOException, CancelledException {
|
||||||
throws IOException, CancelledException {
|
|
||||||
return getReaderForStreamNumber(PDB_DIRECTORY_STREAM_NUMBER, 0,
|
return getReaderForStreamNumber(PDB_DIRECTORY_STREAM_NUMBER, 0,
|
||||||
MsfStream.MAX_STREAM_LENGTH);
|
MsfStream.MAX_STREAM_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,11 @@ public interface TPI {
|
||||||
int getTypeIndexMaxExclusive();
|
int getTypeIndexMaxExclusive();
|
||||||
|
|
||||||
AbstractMsType getRecord(int recordNumber);
|
AbstractMsType getRecord(int recordNumber);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Random access of {@link AbstractMsType} record indicated by {@code recordNumber}
|
||||||
|
* @param recordNumber record number of the record to retrieve
|
||||||
|
* @return {@link AbstractMsType} pertaining to the record number
|
||||||
|
*/
|
||||||
|
AbstractMsType getRandomAccessRecord(int recordNumber);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,10 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
|
|
||||||
protected int versionNumber = 0;
|
protected int versionNumber = 0;
|
||||||
|
|
||||||
|
private record OffLen(int offset, int length) {}; // record type for quick random access
|
||||||
|
|
||||||
|
private List<OffLen> offLenRecords;
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// API
|
// API
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -68,8 +72,7 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
* @param recordCategory the RecordCategory of these records
|
* @param recordCategory the RecordCategory of these records
|
||||||
* @param streamNumber the stream number that contains the {@link TypeProgramInterface} data
|
* @param streamNumber the stream number that contains the {@link TypeProgramInterface} data
|
||||||
*/
|
*/
|
||||||
public TypeProgramInterface(AbstractPdb pdb, RecordCategory recordCategory,
|
public TypeProgramInterface(AbstractPdb pdb, RecordCategory recordCategory, int streamNumber) {
|
||||||
int streamNumber) {
|
|
||||||
Objects.requireNonNull(pdb, "pdb cannot be null");
|
Objects.requireNonNull(pdb, "pdb cannot be null");
|
||||||
this.pdb = pdb;
|
this.pdb = pdb;
|
||||||
this.recordCategory = recordCategory;
|
this.recordCategory = recordCategory;
|
||||||
|
@ -142,6 +145,40 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
return typeList.get(recordNumber - typeIndexMin);
|
return typeList.get(recordNumber - typeIndexMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractMsType getRandomAccessRecord(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordNumber rn = RecordNumber.make(recordCategory, recordNumber);
|
||||||
|
OffLen offLen = offLenRecords.get(recordNumber - typeIndexMin);
|
||||||
|
|
||||||
|
try {
|
||||||
|
PdbByteReader recordReader =
|
||||||
|
pdb.getReaderForStreamNumber(streamNumber, offLen.offset(), offLen.length());
|
||||||
|
return TypeParser.parseRecord(pdb, recordReader, rn);
|
||||||
|
}
|
||||||
|
catch (PdbException | IOException | CancelledException e) {
|
||||||
|
BadMsType badType = new BadMsType(pdb, 0);
|
||||||
|
badType.setRecordNumber(RecordNumber.make(recordCategory, recordNumber));
|
||||||
|
return badType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Package-Protected Internals
|
// Package-Protected Internals
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
@ -165,7 +202,9 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
// Commented out, but this is currently where we might put this method. See the note
|
// Commented out, but this is currently where we might put this method. See the note
|
||||||
// placed within the method (deserializeHashStreams()) for more information about why
|
// placed within the method (deserializeHashStreams()) for more information about why
|
||||||
// we have this commented out.
|
// we have this commented out.
|
||||||
//hash.deserializeHashStreams(monitor);
|
//hash.deserializeHashStreams(pdb.getMonitor());
|
||||||
|
|
||||||
|
createOffLenRecords(reader);
|
||||||
|
|
||||||
deserializeTypeRecords(reader);
|
deserializeTypeRecords(reader);
|
||||||
|
|
||||||
|
@ -254,6 +293,20 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
// Internal Data Methods
|
// Internal Data Methods
|
||||||
//==============================================================================================
|
//==============================================================================================
|
||||||
|
private void createOffLenRecords(PdbByteReader reader) throws PdbException, CancelledException {
|
||||||
|
int savedIndex = reader.getIndex();
|
||||||
|
offLenRecords = new ArrayList<>();
|
||||||
|
while (reader.hasMore()) {
|
||||||
|
pdb.checkCancelled();
|
||||||
|
int recordLength = reader.parseUnsignedShortVal();
|
||||||
|
// reading offset after parsing length so we have correct offset to read from later
|
||||||
|
int offset = reader.getIndex();
|
||||||
|
reader.skip(recordLength);
|
||||||
|
offLenRecords.add(new OffLen(offset, recordLength));
|
||||||
|
}
|
||||||
|
reader.setIndex(savedIndex); // restore reader to original state
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes the Type Records of this class
|
* Deserializes the Type Records of this class
|
||||||
* @param reader {@link PdbByteReader} from which to deserialize the data
|
* @param reader {@link PdbByteReader} from which to deserialize the data
|
||||||
|
@ -418,8 +471,7 @@ public abstract class TypeProgramInterface implements TPI {
|
||||||
if (hashStreamNumberAuxiliary == 0xffff) {
|
if (hashStreamNumberAuxiliary == 0xffff) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PdbByteReader readerAuxiliary =
|
PdbByteReader readerAuxiliary = pdb.getReaderForStreamNumber(hashStreamNumberAuxiliary);
|
||||||
pdb.getReaderForStreamNumber(hashStreamNumberAuxiliary);
|
|
||||||
//readerAuxiliary.dump();
|
//readerAuxiliary.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue