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(); pdb.deserialize();
DefaultPdbApplicator applicator = DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(), new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), applicatorOptions, (MessageLog) null); program.getImageBase(), applicatorOptions, monitor, (MessageLog) null);
applicator.applyNoAnalysisState(); applicator.applyNoAnalysisState();
} }
catch (PdbException | IOException | CancelledException e) { catch (PdbException | IOException | CancelledException e) {

View file

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

View file

@ -205,8 +205,9 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
monitor.setMessage("PDB: Parsing " + pdbFile + "..."); monitor.setMessage("PDB: Parsing " + pdbFile + "...");
pdb.deserialize(); pdb.deserialize();
DefaultPdbApplicator applicator = new DefaultPdbApplicator(pdb, program, DefaultPdbApplicator applicator =
program.getDataTypeManager(), program.getImageBase(), pdbApplicatorOptions, log); new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), pdbApplicatorOptions, monitor, log);
applicator.applyDataTypesAndMainSymbolsAnalysis(); applicator.applyDataTypesAndMainSymbolsAnalysis();
AutoAnalysisManager aam = AutoAnalysisManager.getAnalysisManager(program); AutoAnalysisManager aam = AutoAnalysisManager.getAnalysisManager(program);
@ -360,7 +361,7 @@ public class PdbUniversalAnalyzer extends AbstractAnalyzer {
pdb.deserialize(); pdb.deserialize();
DefaultPdbApplicator applicator = DefaultPdbApplicator applicator =
new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(), new DefaultPdbApplicator(pdb, program, program.getDataTypeManager(),
program.getImageBase(), pdbApplicatorOptions, log); program.getImageBase(), pdbApplicatorOptions, monitor, log);
applicator.applyFunctionInternalsAnalysis(); applicator.applyFunctionInternalsAnalysis();
return true; 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.RecordNumber;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractComplexMsType; import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractComplexMsType;
import ghidra.app.util.pdb.PdbNamespaceUtils; import ghidra.app.util.pdb.PdbNamespaceUtils;
import ghidra.util.Msg;
import mdemangler.*;
import mdemangler.datatype.MDDataType;
/** /**
* Applier for {@link AbstractComplexMsType} types. * Applier for {@link AbstractComplexMsType} types.
@ -42,8 +45,21 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
* @see #getFixedSymbolPath(AbstractComplexMsType type) * @see #getFixedSymbolPath(AbstractComplexMsType type)
*/ */
SymbolPath getSymbolPath(AbstractComplexMsType type) { SymbolPath getSymbolPath(AbstractComplexMsType type) {
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(); String fullPathName = type.getName();
return new SymbolPath(SymbolPathParser.parse(fullPathName)); symbolPath = new SymbolPath(SymbolPathParser.parse(fullPathName));
}
return symbolPath;
} }
/** /**
@ -75,4 +91,28 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
return PdbNamespaceUtils.convertToGhidraPathName(path, num); 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, private void applyBasic(ComboType combo, AbstractCompositeMsType type,
FieldListTypeApplier.FieldLists lists) FieldListTypeApplier.FieldLists lists) throws CancelledException, PdbException {
throws CancelledException, PdbException {
Composite composite = combo.dt(); Composite composite = combo.dt();
CppCompositeType classType = combo.ct(); CppCompositeType classType = combo.ct();
boolean isClass = (type instanceof AbstractClassMsType); boolean isClass = (type instanceof AbstractClassMsType);
@ -156,8 +155,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
//============================================================================================== //==============================================================================================
private void applyCpp(ComboType combo, AbstractCompositeMsType type, private void applyCpp(ComboType combo, AbstractCompositeMsType type,
FieldListTypeApplier.FieldLists lists) FieldListTypeApplier.FieldLists lists) throws PdbException, CancelledException {
throws PdbException, CancelledException {
Composite composite = combo.dt(); Composite composite = combo.dt();
CppCompositeType classType = combo.ct(); CppCompositeType classType = combo.ct();
clearComponents(composite); clearComponents(composite);
@ -243,8 +241,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
} }
private void applyDirectBaseClass(AbstractBaseClassMsType base, CppCompositeType myClassType, private void applyDirectBaseClass(AbstractBaseClassMsType base, CppCompositeType myClassType,
Access defaultAccess) Access defaultAccess) throws PdbException {
throws PdbException {
CppCompositeType underlyingClassType = CppCompositeType underlyingClassType =
getUnderlyingClassType(base.getBaseClassRecordNumber()); getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingClassType == null) { if (underlyingClassType == null) {
@ -258,25 +255,23 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
private void applyDirectVirtualBaseClass(AbstractVirtualBaseClassMsType base, private void applyDirectVirtualBaseClass(AbstractVirtualBaseClassMsType base,
CppCompositeType myClassType, Access defaultAccess) throws PdbException { CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt = CppCompositeType underlyingCt = getUnderlyingClassType(base.getBaseClassRecordNumber());
getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) { if (underlyingCt == null) {
return; return;
} }
DataType vbtptr = getVirtualBaseTablePointerDataType( DataType vbtptr =
base.getVirtualBasePointerRecordNumber()); getVirtualBaseTablePointerDataType(base.getVirtualBasePointerRecordNumber());
ClassFieldMsAttributes atts = base.getAttributes(); ClassFieldMsAttributes atts = base.getAttributes();
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset()); int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt()); int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addDirectVirtualBaseClass(underlyingCt, myClassType.addDirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess), ClassFieldAttributes.convert(atts, defaultAccess), basePointerOffset, vbtptr,
basePointerOffset, vbtptr, offsetFromVbt); offsetFromVbt);
} }
private void applyIndirectVirtualBaseClass(AbstractIndirectVirtualBaseClassMsType base, private void applyIndirectVirtualBaseClass(AbstractIndirectVirtualBaseClassMsType base,
CppCompositeType myClassType, Access defaultAccess) throws PdbException { CppCompositeType myClassType, Access defaultAccess) throws PdbException {
CppCompositeType underlyingCt = CppCompositeType underlyingCt = getUnderlyingClassType(base.getBaseClassRecordNumber());
getUnderlyingClassType(base.getBaseClassRecordNumber());
if (underlyingCt == null) { if (underlyingCt == null) {
return; return;
} }
@ -286,8 +281,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset()); int basePointerOffset = applicator.bigIntegerToInt(base.getBasePointerOffset());
int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt()); int offsetFromVbt = applicator.bigIntegerToInt(base.getBaseOffsetFromVbt());
myClassType.addIndirectVirtualBaseClass(underlyingCt, myClassType.addIndirectVirtualBaseClass(underlyingCt,
ClassFieldAttributes.convert(atts, defaultAccess), ClassFieldAttributes.convert(atts, defaultAccess), basePointerOffset, vbtptr,
basePointerOffset, vbtptr, offsetFromVbt); offsetFromVbt);
} }
private CppCompositeType getUnderlyingClassType(RecordNumber recordNumber) { private CppCompositeType getUnderlyingClassType(RecordNumber recordNumber) {
@ -324,8 +319,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
private void addMembers(Composite composite, CppCompositeType myClassType, private void addMembers(Composite composite, CppCompositeType myClassType,
List<AbstractMemberMsType> msMembers, AbstractCompositeMsType type, List<AbstractMemberMsType> msMembers, AbstractCompositeMsType type,
List<DefaultPdbUniversalMember> myMembers) List<DefaultPdbUniversalMember> myMembers) throws CancelledException, PdbException {
throws CancelledException, PdbException {
ClassFieldAttributes.Access defaultAccess = ClassFieldAttributes.Access defaultAccess =
(type instanceof AbstractClassMsType) ? ClassFieldAttributes.Access.PRIVATE (type instanceof AbstractClassMsType) ? ClassFieldAttributes.Access.PRIVATE
: ClassFieldAttributes.Access.PUBLIC; : ClassFieldAttributes.Access.PUBLIC;
@ -344,8 +338,7 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
// Does not use applier... goes straight to vftptr type // Does not use applier... goes straight to vftptr type
private void addVftPtrs(Composite composite, CppCompositeType myClassType, private void addVftPtrs(Composite composite, CppCompositeType myClassType,
List<AbstractVirtualFunctionTablePointerMsType> msVftPtrs, AbstractCompositeMsType type, List<AbstractVirtualFunctionTablePointerMsType> msVftPtrs, AbstractCompositeMsType type,
List<DefaultPdbUniversalMember> myMembers) List<DefaultPdbUniversalMember> myMembers) throws CancelledException, PdbException {
throws CancelledException, PdbException {
for (AbstractVirtualFunctionTablePointerMsType vftPtr : msVftPtrs) { for (AbstractVirtualFunctionTablePointerMsType vftPtr : msVftPtrs) {
applicator.checkCancelled(); applicator.checkCancelled();
RecordNumber recordNumber = vftPtr.getPointerTypeRecordNumber(); RecordNumber recordNumber = vftPtr.getPointerTypeRecordNumber();
@ -487,8 +480,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
return done; return done;
} }
private DefaultPdbUniversalMember getNonStaticMember(Composite container, private DefaultPdbUniversalMember getNonStaticMember(Composite container, Access defaultAccess,
Access defaultAccess, AbstractMemberMsType memberMsType, int ordinal) AbstractMemberMsType memberMsType, int ordinal)
throws CancelledException, PdbException { throws CancelledException, PdbException {
MsTypeApplier applier = applicator.getTypeApplier(memberMsType); MsTypeApplier applier = applicator.getTypeApplier(memberMsType);
@ -524,8 +517,8 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
fieldApplier instanceof ArrayTypeApplier arrayApplier && fieldApplier instanceof ArrayTypeApplier arrayApplier &&
arrayApplier.isFlexibleArray(fieldType)); arrayApplier.isFlexibleArray(fieldType));
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(memberName, fieldDataType, DefaultPdbUniversalMember member =
isZeroLengthArray, offset, new DefaultPdbUniversalMember(memberName, fieldDataType, isZeroLengthArray, offset,
ClassFieldAttributes.convert(memberAttributes, defaultAccess), memberComment); ClassFieldAttributes.convert(memberAttributes, defaultAccess), memberComment);
return member; return member;
} }

View file

@ -180,6 +180,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
private PdbApplicatorOptions applicatorOptions; private PdbApplicatorOptions applicatorOptions;
private MessageLog log; private MessageLog log;
private TaskMonitor monitor;
private CancelOnlyWrappingTaskMonitor cancelOnlyWrappingMonitor; private CancelOnlyWrappingTaskMonitor cancelOnlyWrappingMonitor;
//============================================================================================== //==============================================================================================
@ -247,15 +248,18 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @param imageBaseParam address bases from which symbol addresses are based. If null, uses * @param imageBaseParam address bases from which symbol addresses are based. If null, uses
* the image base of the program (both cannot be null) * the image base of the program (both cannot be null)
* @param applicatorOptionsParam {@link PdbApplicatorOptions} used for applying the PDB * @param applicatorOptionsParam {@link PdbApplicatorOptions} used for applying the PDB
* @param monitor the task monitor to use
* @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
*/ */
public DefaultPdbApplicator(AbstractPdb pdb, Program programParam, public DefaultPdbApplicator(AbstractPdb pdb, Program programParam,
DataTypeManager dataTypeManagerParam, Address imageBaseParam, 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"); Objects.requireNonNull(pdb, "pdb cannot be null");
this.pdb = pdb; 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 // 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
@ -395,7 +399,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
AddressSet disassembleAddresses = gatherAddressesForDisassembly(); AddressSet disassembleAddresses = gatherAddressesForDisassembly();
TaskMonitor monitor = getMonitor();
Listing listing = program.getListing(); Listing listing = program.getListing();
DisassemblerContextImpl seedContext = DisassemblerContextImpl seedContext =
new DisassemblerContextImpl(program.getProgramContext()); new DisassemblerContextImpl(program.getProgramContext());
@ -447,7 +450,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void processTypes() throws CancelledException, PdbException { private void processTypes() throws CancelledException, PdbException {
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying to DTM " + dataTypeManager.getName() + "..."); monitor.setMessage("PDB: Applying to DTM " + dataTypeManager.getName() + "...");
PdbResearch.initBreakPointRecordNumbers(); // for developmental debug PdbResearch.initBreakPointRecordNumbers(); // for developmental debug
@ -469,9 +471,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
// PdbResearch.developerDebugOrder(this, monitor); // 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, // 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. // then this call can be performed with the data types only work.
if (program != null) { if (program != null) {
@ -480,6 +479,9 @@ public class DefaultPdbApplicator implements PdbApplicator {
// Process typedefs, which are in the symbols. // Process typedefs, which are in the symbols.
processGlobalTypdefSymbols(); processGlobalTypdefSymbols();
Msg.info(this, "resolveCount: " + resolveCount);
Msg.info(this, "conflictCount: " + conflictCount);
} }
//============================================================================================== //==============================================================================================
@ -562,7 +564,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam, validateAndSetParameters(programParam, dataTypeManagerParam, imageBaseParam,
applicatorOptionsParam, logParam); applicatorOptionsParam, logParam);
cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(getMonitor()); cancelOnlyWrappingMonitor = new CancelOnlyWrappingTaskMonitor(monitor);
pdbPeHeaderInfoManager = new PdbPeHeaderInfoManager(this); pdbPeHeaderInfoManager = new PdbPeHeaderInfoManager(this);
@ -675,7 +677,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
* @throws CancelledException if monitor has been cancelled * @throws CancelledException if monitor has been cancelled
*/ */
void checkCancelled() throws CancelledException { void checkCancelled() throws CancelledException {
getMonitor().checkCancelled(); monitor.checkCancelled();
} }
/** /**
@ -727,7 +729,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
*/ */
@Override @Override
public TaskMonitor getMonitor() { 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 + "; " + throw new PdbException("Type not completed for record: " + recordNumber + "; " +
type.getClass().getSimpleName()); 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); dataType = getDataType(recordNumber);
if (dataType == null) { if (dataType == null) {
throw new PdbException( throw new PdbException(
@ -1132,16 +1140,15 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin(); int num = tpi.getTypeIndexMaxExclusive() - tpi.getTypeIndexMin();
TaskMonitor monitor = getMonitor(); monitor.initialize(2 * num); // progress updated in MultiphaseResolver; 2x per record
monitor.initialize(num);
monitor.setMessage("PDB: Processing " + num + " data type components..."); monitor.setMessage("PDB: Processing " + num + " data type components...");
for (int indexNumber = tpi.getTypeIndexMin(); indexNumber < tpi for (int indexNumber = tpi.getTypeIndexMin(); indexNumber < tpi
.getTypeIndexMaxExclusive(); indexNumber++) { .getTypeIndexMaxExclusive(); indexNumber++) {
monitor.checkCancelled(); monitor.checkCancelled();
RecordNumber recordNumber = RecordNumber.typeRecordNumber(indexNumber); RecordNumber recordNumber = RecordNumber.typeRecordNumber(indexNumber);
RecordNumber mappedNumber = getMappedRecordNumber(recordNumber); RecordNumber mappedNumber = getMappedRecordNumber(recordNumber);
multiphaseResolver.process(mappedNumber); multiphaseResolver.process(mappedNumber, monitor);
monitor.incrementProgress(1); // Monitor progress is updated in the multiphasResolver
} }
doCheck(); doCheck();
@ -1213,7 +1220,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin(); int num = ipi.getTypeIndexMaxExclusive() - ipi.getTypeIndexMin();
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 = ipi.getTypeIndexMin(); indexNumber < ipi for (int indexNumber = ipi.getTypeIndexMin(); indexNumber < ipi
@ -1244,8 +1250,7 @@ public class DefaultPdbApplicator implements PdbApplicator {
if (!(dataType instanceof DataTypeImpl)) { if (!(dataType instanceof DataTypeImpl)) {
return dataType; return dataType;
} }
DataType resolved = getDataTypeManager().resolve(dataType, DataType resolved = getDataTypeManager().resolve(dataType, null);
DataTypeConflictHandler.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD_HANDLER);
resolveCount++; resolveCount++;
if (DataTypeUtilities.isConflictDataType(resolved)) { if (DataTypeUtilities.isConflictDataType(resolved)) {
conflictCount++; conflictCount++;
@ -1486,7 +1491,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
int totalCount = symbolGroup.size(); int totalCount = symbolGroup.size();
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);
MsSymbolIterator iter = symbolGroup.getSymbolIterator(); MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1499,7 +1503,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
PdbDebugInfo debugInfo = pdb.getDebugInfo(); PdbDebugInfo debugInfo = pdb.getDebugInfo();
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Deferred-applying module symbol components..."); monitor.setMessage("PDB: Deferred-applying module symbol components...");
monitor.initialize(num + 1); // add one because we doing 0 through num, inclusive monitor.initialize(num + 1); // add one because we doing 0 through num, inclusive
AddressSet addresses = new AddressSet(); AddressSet addresses = new AddressSet();
@ -1522,7 +1525,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
AddressSet getDisassembleAddressForModule(int moduleNumber, MsSymbolIterator iter) AddressSet getDisassembleAddressForModule(int moduleNumber, MsSymbolIterator iter)
throws CancelledException { throws CancelledException {
iter.initGet(); iter.initGet();
TaskMonitor monitor = getMonitor();
AddressSet addresses = new AddressSet(); AddressSet addresses = new AddressSet();
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
@ -1550,7 +1552,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
if (debugInfo == null) { if (debugInfo == null) {
return; return;
} }
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Deferred-applying module symbol components..."); monitor.setMessage("PDB: Deferred-applying module symbol components...");
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
monitor.initialize(num); monitor.initialize(num);
@ -1571,7 +1572,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void doDeferredModuleSymbolGroup(int moduleNumber, MsSymbolIterator iter) private void doDeferredModuleSymbolGroup(int moduleNumber, MsSymbolIterator iter)
throws CancelledException { throws CancelledException {
iter.initGet(); iter.initGet();
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
AbstractMsSymbol symbol = iter.peek(); AbstractMsSymbol symbol = iter.peek();
@ -1593,7 +1593,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying module symbol components..."); monitor.setMessage("PDB: Applying module symbol components...");
monitor.initialize(num); monitor.initialize(num);
// Process symbols list for each module // Process symbols list for each module
@ -1613,7 +1612,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
private void processSymbolGroup(int moduleNumber, MsSymbolIterator iter) private void processSymbolGroup(int moduleNumber, MsSymbolIterator iter)
throws CancelledException { throws CancelledException {
iter.initGet(); iter.initGet();
TaskMonitor monitor = getMonitor();
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
procSymNew(iter); procSymNew(iter);
@ -1642,7 +1640,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation(); PublicSymbolInformation publicSymbolInformation = debugInfo.getPublicSymbolInformation();
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying public symbols..."); monitor.setMessage("PDB: Applying public symbols...");
MsSymbolIterator iter = symbolGroup.getSymbolIterator(); MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1699,7 +1696,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
// return; // return;
// } // }
// //
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying global symbols..."); monitor.setMessage("PDB: Applying global symbols...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
// MsSymbolIterator iter = symbolGroup.getSymbolIterator(); // MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1721,6 +1717,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
monitor.incrementProgress(1); 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 = // AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
// globalSymbolInformation.iterator(); // globalSymbolInformation.iterator();
@ -1754,7 +1752,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
MsSymbolIterator iter = debugInfo.getSymbolIterator(); MsSymbolIterator iter = debugInfo.getSymbolIterator();
List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets(); List<Long> offsets = globalSymbolInformation.getModifiedHashRecordSymbolOffsets();
TaskMonitor monitor = getMonitor();
monitor.initialize(offsets.size(), "PDB: Performing deferred global symbols processing..."); monitor.initialize(offsets.size(), "PDB: Performing deferred global symbols processing...");
for (long offset : offsets) { for (long offset : offsets) {
monitor.checkCancelled(); monitor.checkCancelled();
@ -1789,7 +1786,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
TaskMonitor monitor = getMonitor();
monitor.setMessage("PDB: Applying typedefs..."); monitor.setMessage("PDB: Applying typedefs...");
GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation(); GlobalSymbolInformation globalSymbolInformation = debugInfo.getGlobalSymbolInformation();
MsSymbolIterator iter = symbolGroup.getSymbolIterator(); MsSymbolIterator iter = symbolGroup.getSymbolIterator();
@ -1808,6 +1804,8 @@ public class DefaultPdbApplicator implements PdbApplicator {
} }
monitor.incrementProgress(1); 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 = // AbstractSymbolInformation.ModifiedOffsetIterator globalsIter =
// globalSymbolInformation.iterator(); // globalSymbolInformation.iterator();
@ -1851,7 +1849,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return; return;
} }
TaskMonitor monitor = getMonitor();
Set<Long> offsetsRemaining = symbolGroup.getOffsets(); Set<Long> offsetsRemaining = symbolGroup.getOffsets();
for (long off : debugInfo.getPublicSymbolInformation() for (long off : debugInfo.getPublicSymbolInformation()
.getModifiedHashRecordSymbolOffsets()) { .getModifiedHashRecordSymbolOffsets()) {
@ -1913,7 +1910,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
return false; return false;
} }
TaskMonitor monitor = getMonitor();
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());
@ -1955,7 +1951,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber); SymbolGroup symbolGroup = getSymbolGroupForModule(linkerModuleNumber);
if (symbolGroup != null) { if (symbolGroup != null) {
TaskMonitor monitor = getMonitor();
monitor.initialize(symbolGroup.size()); monitor.initialize(symbolGroup.size());
MsSymbolIterator iter = symbolGroup.getSymbolIterator(); MsSymbolIterator iter = symbolGroup.getSymbolIterator();
int numCompileSymbols = 0; int numCompileSymbols = 0;
@ -2012,7 +2007,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
int totalCount = 0; int totalCount = 0;
int num = debugInfo.getNumModules(); int num = debugInfo.getNumModules();
TaskMonitor monitor = getMonitor();
for (int index = 1; index <= num; index++) { for (int index = 1; index <= num; index++) {
monitor.checkCancelled(); monitor.checkCancelled();
if (index == linkerModuleNumber) { if (index == linkerModuleNumber) {
@ -2132,7 +2126,6 @@ public class DefaultPdbApplicator implements PdbApplicator {
//============================================================================================== //==============================================================================================
private void defineClasses() throws CancelledException { private void defineClasses() throws CancelledException {
// create namespace and classes in an ordered fashion use tree map // create namespace and classes in an ordered fashion use tree map
TaskMonitor monitor = getMonitor();
monitor.initialize(isClassByNamespace.size()); monitor.initialize(isClassByNamespace.size());
monitor.setMessage("PDB: Defining classes..."); monitor.setMessage("PDB: Defining classes...");
for (Map.Entry<SymbolPath, Boolean> entry : isClassByNamespace.entrySet()) { 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.*;
import ghidra.app.util.bin.format.pdb2.pdbreader.type.AbstractMsType; 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.AssertException;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; 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 { public class MultiphaseDataTypeResolver {
private DefaultPdbApplicator applicator; private DefaultPdbApplicator applicator;
private AbstractPdb pdb; private AbstractPdb pdb;
private TaskMonitor monitor;
private RecordStack todoStack; private RecordStack todoStack;
private RecordStack resolveStack; private RecordStack resolveStack;
@ -40,7 +40,6 @@ public class MultiphaseDataTypeResolver {
public MultiphaseDataTypeResolver(DefaultPdbApplicator applicator) { public MultiphaseDataTypeResolver(DefaultPdbApplicator applicator) {
this.applicator = applicator; this.applicator = applicator;
this.pdb = applicator.getPdb(); this.pdb = applicator.getPdb();
this.monitor = applicator.getMonitor();
todoStack = new RecordStack(); todoStack = new RecordStack();
resolveStack = new RecordStack(); resolveStack = new RecordStack();
} }
@ -50,10 +49,12 @@ public class MultiphaseDataTypeResolver {
* type. Deals with cyclic dependencies and ultimately stores resolved (in most cases) * type. Deals with cyclic dependencies and ultimately stores resolved (in most cases)
* types in the DefaultPdbApplicator types map * types in the DefaultPdbApplicator types map
* @param recordNumber the record number * @param recordNumber the record number
* @param monitor the task monitor to use
* @throws PdbException upon processing error * @throws PdbException upon processing error
* @throws CancelledException upon user cancellation * @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 found in the applicator map then the type is completed.
if (applicator.getDataType(recordNumber) != null) { if (applicator.getDataType(recordNumber) != null) {
@ -81,6 +82,9 @@ public class MultiphaseDataTypeResolver {
} }
todoStack.pop(); todoStack.pop();
resolveStack.push(recordToProcess); 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) // 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) { while ((recordToProcess = resolveStack.pop()) != null) {
monitor.checkCancelled(); monitor.checkCancelled();
DataType dataType = applicator.getDataType(recordToProcess); DataType dataType = applicator.getDataType(recordToProcess);
// Resolve and re-store most data types // Resolve and re-store most types. Normally we wouldn't want to resolve
if (!(dataType instanceof PointerDataType || dataType instanceof BitFieldDataType)) { // 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); dataType = applicator.resolve(dataType);
applicator.putDataType(recordToProcess, 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; RecordNode tail;
boolean debug; boolean debug;
StringBuilder debugBuilder; StringBuilder debugBuilder;
long numNodes;
/** /**
* Constructor for new record stack * Constructor for new record stack
@ -165,6 +176,7 @@ public class MultiphaseDataTypeResolver {
head.prev = tail; head.prev = tail;
tail.next = head; tail.next = head;
tail.prev = null; tail.prev = null;
numNodes = 0L; // does not count HEAD/TAIL special nodes
} }
/** /**
@ -205,6 +217,7 @@ public class MultiphaseDataTypeResolver {
debugBuilder.append("\n"); debugBuilder.append("\n");
} }
map.put(recordNumber, node); map.put(recordNumber, node);
numNodes++;
} }
else { // already exists in non-top-of-stack position else { // already exists in non-top-of-stack position
removeNodeLinkage(node); removeNodeLinkage(node);
@ -235,6 +248,7 @@ public class MultiphaseDataTypeResolver {
} }
removeNodeLinkage(node); removeNodeLinkage(node);
map.remove(node.recordNumber); map.remove(node.recordNumber);
numNodes--;
if (debug) { if (debug) {
debugBuilder.append(" pop:"); debugBuilder.append(" pop:");
debugBuilder.append(node.recordNumber); debugBuilder.append(node.recordNumber);
@ -289,6 +303,7 @@ public class MultiphaseDataTypeResolver {
int count = 0; int count = 0;
RecordNode node = head.prev; RecordNode node = head.prev;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(numNodes + ":");
builder.append('['); builder.append('[');
while (node != tail && count < TO_STRING_LIMIT) { while (node != tail && count < TO_STRING_LIMIT) {
if (count != 0) { if (count != 0) {