GP-4595 - PDB fix class containing member with same type name and primitive typedef and use default type handler

This commit is contained in:
ghizard 2024-07-01 18:29:57 -04:00
parent 2b73a6157f
commit 3326d42baf
7 changed files with 116 additions and 73 deletions

View File

@ -198,7 +198,7 @@ public class Pagedump extends DumpFile {
pdb.deserialize();
DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), applicatorOptions, (MessageLog) null);
program.getImageBase(), applicatorOptions, monitor, (MessageLog) null);
applicator.applyNoAnalysisState();
}
catch (PdbException | IOException | CancelledException e) {

View File

@ -110,8 +110,9 @@ public class PdbDeveloperApplyDummyScript extends GhidraScript {
try (AbstractPdb pdb = PdbParser.parse(pdbFile, pdbReaderOptions, monitor)) {
monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize();
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb, program,
program.getDataTypeManager(), program.getImageBase(), pdbApplicatorOptions, log);
DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), pdbApplicatorOptions, monitor, log);
applicator.applyNoAnalysisState();
}
catch (PdbException | IOException e) {

View File

@ -205,8 +205,9 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize();
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb, program,
program.getDataTypeManager(), program.getImageBase(), pdbApplicatorOptions, log);
DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), pdbApplicatorOptions, monitor, log);
applicator.applyDataTypesAndMainSymbolsAnalysis();
AutoAnalysisManager aam = AutoAnalysisManager.getAnalysisManager(program);
@ -360,7 +361,7 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
pdb.deserialize();
DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), pdbApplicatorOptions, log);
program.getImageBase(), pdbApplicatorOptions, monitor, log);
applicator.applyFunctionInternalsAnalysis();
return true;
}

View File

@ -20,6 +20,9 @@ import ghidra.app.util.SymbolPathParser;
import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractComplexMsType;
import ghidra.app.util.pdb.PdbNamespaceUtils;
import ghidra.util.Msg;
import mdemangler.*;
import mdemangler.datatype.MDDataType;
/**
* Applier for {@link AbstractComplexMsType} types.
@ -42,8 +45,21 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
* @see #getFixedSymbolPath(AbstractComplexMsType type)
*/
SymbolPath getSymbolPath(AbstractComplexMsType type) {
String fullPathName = type.getName();
return new SymbolPath(SymbolPathParser.parse(fullPathName));
SymbolPath symbolPath = null;
// We added logic to check the mangled name first because we found some LLVM "lambda"
// symbols where the regular name was a generic "<lambda_0>" with a namespace, but this
// often had a member that also lambda that was marked with the exact same namespace/name
// as the containing structure. We found that the mangled names had more accurate and
// distinguished lambda numbers.
String mangledName = type.getMangledName();
if (mangledName != null) {
symbolPath = getSymbolPathFromMangledTypeName(mangledName);
}
if (symbolPath == null) {
String fullPathName = type.getName();
symbolPath = new SymbolPath(SymbolPathParser.parse(fullPathName));
}
return symbolPath;
}
/**
@ -75,4 +91,28 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
return PdbNamespaceUtils.convertToGhidraPathName(path, num);
}
private SymbolPath getSymbolPathFromMangledTypeName(String mangledString) {
MDMang demangler = new MDMangGhidra();
try {
MDDataType mdDataType = demangler.demangleType(mangledString, true);
// 20240626: Ultimately, it might be better to retrieve the Demangled-type to pass
// to the DemangledObject.createNamespace() method to convert to a true Ghidra
// Namespace that are flagged as functions (not capable at this time) or types or
// raw namespace nodes. Note, however, that the Demangler is still weak in this
// area as there are codes that we still not know how to interpret.
return MDMangUtils.getSymbolPath(mdDataType);
// Could consider the following simplification method instead
// return MDMangUtils.getSimpleSymbolPath(mdDataType);
}
catch (MDException e) {
// Couldn't demangle.
// Message might cause too much noise (we have a fallback, above, to use the regular
// name, but this could cause an error... see the notes above about why a mangled
// name is checked first).
Msg.info(this,
"PDB issue dmangling type name: " + e.getMessage() + " for : " + mangledString);
}
return null;
}
}

View File

@ -136,8 +136,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
//==============================================================================================
private void applyBasic(ComboType combo, AbstractCompositeMsType type,
FieldListTypeApplier.FieldLists lists)
throws CancelledException, PdbException {
FieldListTypeApplier.FieldLists lists) throws CancelledException, PdbException {
Composite composite = combo.dt();
CppCompositeType classType = combo.ct();
boolean isClass = (type instanceof AbstractClassMsType);
@ -156,8 +155,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
//==============================================================================================
private void applyCpp(ComboType combo, AbstractCompositeMsType type,
FieldListTypeApplier.FieldLists lists)
throws PdbException, CancelledException {
FieldListTypeApplier.FieldLists lists) throws PdbException, CancelledException {
Composite composite = combo.dt();
CppCompositeType classType = combo.ct();
clearComponents(composite);
@ -243,8 +241,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
private void applyDirectBaseClass(AbstractBaseClassMsType base, CppCompositeType myClassType,
Access defaultAccess)
throws PdbException {
Access defaultAccess) throws PdbException {
CppCompositeType underlyingClassType =
getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingClassType == null) {
@ -258,25 +255,23 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
private void applyDirectVirtualBaseClass(AbstractVirtualBaseClassMsType base,
CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt =
getUnderlyingClassType(base.getBaseClassRecordNumber());
CppCompositeType underlyingCt = getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) {
return;
}
DataType vbtptr = getVirtualBaseTablePointerDataType(
base.getVirtualBasePointerRecordNumber());
DataType vbtptr =
getVirtualBaseTablePointerDataType(base.getVirtualBasePointerRecordNumber());
ClassFieldMsAttributes atts = base.getAttributes();
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addDirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess),
basePointerOffset, vbtptr, offsetFromVbt);
ClassFieldAttributes.convert(atts, defaultAccess), basePointerOffset, vbtptr,
offsetFromVbt);
}
private void applyIndirectVirtualBaseClass(AbstractIndirectVirtualBaseClassMsType base,
CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt =
getUnderlyingClassType(base.getBaseClassRecordNumber());
CppCompositeType underlyingCt = getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) {
return;
}
@ -286,8 +281,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addIndirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess),
basePointerOffset, vbtptr, offsetFromVbt);
ClassFieldAttributes.convert(atts, defaultAccess), basePointerOffset, vbtptr,
offsetFromVbt);
}
private CppCompositeType getUnderlyingClassType(RecordNumber recordNumber) {
@ -324,8 +319,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
private void addMembers(Composite composite, CppCompositeType myClassType,
List<AbstractMemberMsType> msMembers, AbstractCompositeMsType type,
List<DefaultPdbUniversalMember> myMembers)
throws CancelledException, PdbException {
List<DefaultPdbUniversalMember> myMembers) throws CancelledException, PdbException {
ClassFieldAttributes.Access defaultAccess =
(type instanceof AbstractClassMsType) ? ClassFieldAttributes.Access.PRIVATE
: ClassFieldAttributes.Access.PUBLIC;
@ -344,8 +338,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
// Does not use applier... goes straight to vftptr type
private void addVftPtrs(Composite composite, CppCompositeType myClassType,
List<AbstractVirtualFunctionTablePointerMsType> msVftPtrs, AbstractCompositeMsType type,
List<DefaultPdbUniversalMember> myMembers)
throws CancelledException, PdbException {
List<DefaultPdbUniversalMember> myMembers) throws CancelledException, PdbException {
for (AbstractVirtualFunctionTablePointerMsType vftPtr : msVftPtrs) {
applicator.checkCancelled();
RecordNumber recordNumber = vftPtr.getPointerTypeRecordNumber();
@ -487,8 +480,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return done;
}
private DefaultPdbUniversalMember getNonStaticMember(Composite container,
Access defaultAccess, AbstractMemberMsType memberMsType, int ordinal)
private DefaultPdbUniversalMember getNonStaticMember(Composite container, Access defaultAccess,
AbstractMemberMsType memberMsType, int ordinal)
throws CancelledException, PdbException {
MsTypeApplier applier = applicator.getTypeApplier(memberMsType);
@ -524,9 +517,9 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
fieldApplier instanceof ArrayTypeApplier arrayApplier &&
arrayApplier.isFlexibleArray(fieldType));
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(memberName, fieldDataType,
isZeroLengthArray, offset,
ClassFieldAttributes.convert(memberAttributes, defaultAccess), memberComment);
DefaultPdbUniversalMember member =
new DefaultPdbUniversalMember(memberName, fieldDataType, isZeroLengthArray, offset,
ClassFieldAttributes.convert(memberAttributes, defaultAccess), memberComment);
return member;
}

View File

@ -180,6 +180,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
private PdbApplicatorOptions applicatorOptions;
private MessageLog log;
private TaskMonitor monitor;
private CancelOnlyWrappingTaskMonitor cancelOnlyWrappingMonitor;
//==============================================================================================
@ -247,15 +248,18 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @param imageBaseParam address bases from which symbol addresses are based. If null, uses
* the image base of the program (both cannot be null)
* @param applicatorOptionsParam {@link PdbApplicatorOptions} used for applying the PDB
* @param monitor the task monitor to use
* @param logParam the MessageLog to which to output messages
* @throws PdbException if there was a problem processing the data
*/
public DefaultPdbApplicator(AbstractPdb pdb, Program programParam,
DataTypeManager dataTypeManagerParam, Address imageBaseParam,
PdbApplicatorOptions applicatorOptionsParam, MessageLog logParam) throws PdbException {
PdbApplicatorOptions applicatorOptionsParam, TaskMonitor monitor, MessageLog logParam)
throws PdbException {
Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdb = pdb;
this.monitor = (monitor != null) ? monitor : TaskMonitor.DUMMY;
// 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
@ -395,7 +399,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
AddressSet disassembleAddresses = gatherAddressesForDisassembly();
TaskMonitor monitor = getMonitor();
Listing listing = program.getListing();
DisassemblerContextImpl seedContext =
new DisassemblerContextImpl(program.getProgramContext());
@ -447,7 +450,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
//==============================================================================================
private void processTypes() throws CancelledException, PdbException {
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying to DTM " + dataTypeManager.getName() + "...");
PdbResearch.initBreakPointRecordNumbers(); // for developmental debug
@ -469,9 +471,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
// PdbResearch.developerDebugOrder(this, monitor);
Msg.info(this, "resolveCount: " + resolveCount);
Msg.info(this, "conflictCount: " + conflictCount);
// Currently, defining classes needs to have a program. When this is no longer true,
// then this call can be performed with the data types only work.
if (program != null) {
@ -480,6 +479,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
// Process typedefs, which are in the symbols.
processGlobalTypdefSymbols();
Msg.info(this, "resolveCount: " + resolveCount);
Msg.info(this, "conflictCount: " + conflictCount);
}
//==============================================================================================
@ -562,7 +564,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, logParam);
cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(getMonitor());
cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(monitor);
pdbPeHeaderInfoManager = new PdbPeHeaderInfoManager(this);
@ -675,7 +677,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @throws CancelledException if monitor has been cancelled
*/
void checkCancelled() throws CancelledException {
getMonitor().checkCancelled();
monitor.checkCancelled();
}
/**
@ -727,7 +729,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
*/
@Override
public TaskMonitor getMonitor() {
return pdb.getMonitor();
return monitor;
}
/**
@ -922,7 +924,13 @@ public class DefaultPdbApplicator implements PdbApplicator {
throw new PdbException("Type not completed for record: " + recordNumber + "; " +
type.getClass().getSimpleName());
}
multiphaseResolver.process(recordNumber);
MsDataTypeApplier dataTypeApplier = (MsDataTypeApplier) getTypeApplier(recordNumber);
if (!dataTypeApplier.apply(type)) {
throw new PdbException(
"Problem creating Primitive data type for record: " + recordNumber);
}
dataType = getDataType(recordNumber);
if (dataType == null) {
throw new PdbException(
@ -1132,16 +1140,15 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin();
TaskMonitor monitor = getMonitor();
monitor.initialize(num);
monitor.initialize(2 * num); // progress updated in MultiphaseResolver; 2x per record
monitor.setMessage("PDB: Processing " + num + " data type components...");
for (int indexNumber = tpi.getTypeIndexMin(); indexNumber < tpi
.getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCancelled();
RecordNumber recordNumber = RecordNumber.typeRecordNumber(indexNumber);
RecordNumber mappedNumber = getMappedRecordNumber(recordNumber);
multiphaseResolver.process(mappedNumber);
monitor.incrementProgress(1);
multiphaseResolver.process(mappedNumber, monitor);
// Monitor progress is updated in the multiphasResolver
}
doCheck();
@ -1213,7 +1220,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin();
TaskMonitor monitor = getMonitor();
monitor.initialize(num);
monitor.setMessage("PDB: Processing " + num + " item type components...");
for (int indexNumber = ipi.getTypeIndexMin(); indexNumber < ipi
@ -1244,8 +1250,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
if (!(dataType instanceof DataTypeImpl)) {
return dataType;
}
DataType resolved = getDataTypeManager().resolve(dataType,
DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER);
DataType resolved = getDataTypeManager().resolve(dataType, null);
resolveCount++;
if (DataTypeUtilities.isConflictDataType(resolved)) {
conflictCount++;
@ -1486,7 +1491,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
int totalCount = symbolGroup.size();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying " + totalCount + " main symbol components...");
monitor.initialize(totalCount);
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1499,7 +1503,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
PdbDebugInfo debugInfo = pdb.getDebugInfo();
int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Deferred-applying module symbol components...");
monitor.initialize(num + 1); // add one because we doing 0 through num, inclusive
AddressSet addresses = new AddressSet();
@ -1522,7 +1525,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
AddressSet getDisassembleAddressForModule(int moduleNumber, MsSymbolIterator iter)
throws CancelledException {
iter.initGet();
TaskMonitor monitor = getMonitor();
AddressSet addresses = new AddressSet();
while (iter.hasNext()) {
monitor.checkCancelled();
@ -1550,7 +1552,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
if (debugInfo == null) {
return;
}
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Deferred-applying module symbol components...");
int num = debugInfo.getNumModules();
monitor.initialize(num);
@ -1571,7 +1572,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void doDeferredModuleSymbolGroup(int moduleNumber, MsSymbolIterator iter)
throws CancelledException {
iter.initGet();
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) {
monitor.checkCancelled();
AbstractMsSymbol symbol = iter.peek();
@ -1593,7 +1593,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying module symbol components...");
monitor.initialize(num);
// Process symbols list for each module
@ -1613,7 +1612,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void processSymbolGroup(int moduleNumber, MsSymbolIterator iter)
throws CancelledException {
iter.initGet();
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) {
monitor.checkCancelled();
procSymNew(iter);
@ -1642,7 +1640,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying public symbols...");
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1699,7 +1696,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
// return;
// }
//
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying global symbols...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
// MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1721,6 +1717,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
monitor.incrementProgress(1);
}
// TODO: need to create and update a count for only those really applied
//Msg.info(this, "GlobalSymbolComponentsCount: " + offsets.size());
// AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
// globalSymbolInformation.iterator();
@ -1754,7 +1752,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
MsSymbolIterator iter = debugInfo.getSymbolIterator();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
TaskMonitor monitor = getMonitor();
monitor.initialize(offsets.size(), "PDB: Performing deferred global symbols processing...");
for (long offset : offsets) {
monitor.checkCancelled();
@ -1789,7 +1786,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying typedefs...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1808,6 +1804,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
}
monitor.incrementProgress(1);
}
// TODO: need to create and update a count for only those really applied
//Msg.info(this, "GlobalTypedefCount: " + offsets.size());
// AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
// globalSymbolInformation.iterator();
@ -1851,7 +1849,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return;
}
TaskMonitor monitor = getMonitor();
Set<Long> offsetsRemaining = symbolGroup.getOffsets();
for (long off : debugInfo.getPublicSymbolInformation()
.getModifiedHashRecordSymbolOffsets()) {
@ -1913,7 +1910,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return false;
}
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying " + symbolGroup.size() + " linker symbol components...");
monitor.initialize(symbolGroup.size());
@ -1955,7 +1951,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber);
if (symbolGroup != null) {
TaskMonitor monitor = getMonitor();
monitor.initialize(symbolGroup.size());
MsSymbolIterator iter = symbolGroup.getSymbolIterator();
int numCompileSymbols = 0;
@ -2012,7 +2007,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
int totalCount = 0;
int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
for (int index = 1; index <= num; index++) {
monitor.checkCancelled();
if (index == linkerModuleNumber) {
@ -2132,7 +2126,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
//==============================================================================================
private void defineClasses() throws CancelledException {
// create namespace and classes in an ordered fashion use tree map
TaskMonitor monitor = getMonitor();
monitor.initialize(isClassByNamespace.size());
monitor.setMessage("PDB: Defining classes...");
for (Map.Entry<SymbolPath, Boolean> entry : isClassByNamespace.entrySet()) {

View File

@ -20,19 +20,19 @@ import java.util.Map;
import ghidra.app.util.bin.format.pdb2.pdbreader.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType;
import ghidra.program.model.data.*;
import ghidra.program.model.data.BitFieldDataType;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Performs appropriated multiple passes on data types to get theme filled in and resolved
* Performs appropriate multiple passes on data types to get theme filled in and resolved
*/
public class MultiphaseDataTypeResolver {
private DefaultPdbApplicator applicator;
private AbstractPdb pdb;
private TaskMonitor monitor;
private RecordStack todoStack;
private RecordStack resolveStack;
@ -40,7 +40,6 @@ public class MultiphaseDataTypeResolver {
public MultiphaseDataTypeResolver(DefaultPdbApplicator applicator) {
this.applicator = applicator;
this.pdb = applicator.getPdb();
this.monitor = applicator.getMonitor();
todoStack = new RecordStack();
resolveStack = new RecordStack();
}
@ -50,10 +49,12 @@ public class MultiphaseDataTypeResolver {
* type. Deals with cyclic dependencies and ultimately stores resolved (in most cases)
* types in the DefaultPdbApplicator types map
* @param recordNumber the record number
* @param monitor the task monitor to use
* @throws PdbException upon processing error
* @throws CancelledException upon user cancellation
*/
void process(RecordNumber recordNumber) throws PdbException, CancelledException {
void process(RecordNumber recordNumber, TaskMonitor monitor)
throws PdbException, CancelledException {
// If found in the applicator map then the type is completed.
if (applicator.getDataType(recordNumber) != null) {
@ -81,6 +82,9 @@ public class MultiphaseDataTypeResolver {
}
todoStack.pop();
resolveStack.push(recordToProcess);
// only update when popped; 1st of 2 monitor updates; monitor count was
// initialized in DefaultPdbApplicator.processAndResolveDataTypesSequentially()
monitor.incrementProgress(1);
}
}
// If set true above, location where one might do conditional: todoStack.setDebug(false)
@ -89,11 +93,17 @@ public class MultiphaseDataTypeResolver {
while ((recordToProcess = resolveStack.pop()) != null) {
monitor.checkCancelled();
DataType dataType = applicator.getDataType(recordToProcess);
// Resolve and re-store most data types
if (!(dataType instanceof PointerDataType || dataType instanceof BitFieldDataType)) {
// Resolve and re-store most types. Normally we wouldn't want to resolve
// pointer types, but here it is preferred while we have the types in hand the the
// PDB would have a type record if it wasn't used somewhere here or as the referred-to
// type of a typedef.
if (!(dataType instanceof BitFieldDataType)) {
dataType = applicator.resolve(dataType);
applicator.putDataType(recordToProcess, dataType);
}
// 2nd of 2 monitor updates; monitor count was initialized in
// DefaultPdbApplicator.processAndResolveDataTypesSequentially()
monitor.incrementProgress(1);
}
}
@ -152,6 +162,7 @@ public class MultiphaseDataTypeResolver {
RecordNode tail;
boolean debug;
StringBuilder debugBuilder;
long numNodes;
/**
* Constructor for new record stack
@ -165,6 +176,7 @@ public class MultiphaseDataTypeResolver {
head.prev = tail;
tail.next = head;
tail.prev = null;
numNodes = 0L; // does not count HEAD/TAIL special nodes
}
/**
@ -205,6 +217,7 @@ public class MultiphaseDataTypeResolver {
debugBuilder.append("\n");
}
map.put(recordNumber, node);
numNodes++;
}
else { // already exists in non-top-of-stack position
removeNodeLinkage(node);
@ -235,6 +248,7 @@ public class MultiphaseDataTypeResolver {
}
removeNodeLinkage(node);
map.remove(node.recordNumber);
numNodes--;
if (debug) {
debugBuilder.append(" pop:");
debugBuilder.append(node.recordNumber);
@ -289,6 +303,7 @@ public class MultiphaseDataTypeResolver {
int count = 0;
RecordNode node = head.prev;
StringBuilder builder = new StringBuilder();
builder.append(numNodes + ":");
builder.append('[');
while (node != tail && count < TO_STRING_LIMIT) {
if (count != 0) {