From 3326d42bafe4ab34f3694482dbc2ce0cfc171a58 Mon Sep 17 00:00:00 2001 From: ghizard <50744617+ghizard@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:29:57 -0400 Subject: [PATCH] GP-4595 - PDB fix class containing member with same type name and primitive typedef and use default type handler --- .../file/formats/dump/pagedump/Pagedump.java | 2 +- .../PdbDeveloperApplyDummyScript.java | 5 +- .../core/analysis/PdbUniversalAnalyzer.java | 7 ++- .../AbstractComplexTypeApplier.java | 44 +++++++++++++- .../pdbapplicator/CompositeTypeApplier.java | 43 ++++++-------- .../pdbapplicator/DefaultPdbApplicator.java | 59 ++++++++----------- .../MultiphaseDataTypeResolver.java | 29 ++++++--- 7 files changed, 116 insertions(+), 73 deletions(-) diff --git a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/dump/pagedump/Pagedump.java b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/dump/pagedump/Pagedump.java index b639320072..a07fe8fadb 100644 --- a/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/dump/pagedump/Pagedump.java +++ b/Ghidra/Features/FileFormats/src/main/java/ghidra/file/formats/dump/pagedump/Pagedump.java @@ -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) { diff --git a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java index dcfc1f3fa8..602e72376b 100644 --- a/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java +++ b/Ghidra/Features/PDB/developer_scripts/PdbDeveloperApplyDummyScript.java @@ -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) { diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java index d089dc76bf..3b7e08c8ae 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/plugin/core/analysis/PdbUniversalAnalyzer.java @@ -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; } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractComplexTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractComplexTypeApplier.java index cf5dd8eee7..dfe2c4d6d8 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractComplexTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractComplexTypeApplier.java @@ -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 "" 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; + } + } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java index 7ca899e2f3..d10058c2b0 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CompositeTypeApplier.java @@ -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 msMembers, AbstractCompositeMsType type, - List myMembers) - throws CancelledException, PdbException { + List 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 msVftPtrs, AbstractCompositeMsType type, - List myMembers) - throws CancelledException, PdbException { + List 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; } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java index 8b46c877fc..2502d2625c 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/DefaultPdbApplicator.java @@ -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 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 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 entry : isClassByNamespace.entrySet()) { diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MultiphaseDataTypeResolver.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MultiphaseDataTypeResolver.java index 567454fff7..d0b5b7eb92 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MultiphaseDataTypeResolver.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MultiphaseDataTypeResolver.java @@ -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) {