diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/ModuleInformation.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/ModuleInformation.java index 3afceac6a8..6375ecd47a 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/ModuleInformation.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/ModuleInformation.java @@ -141,7 +141,12 @@ public abstract class ModuleInformation { } /** - * Returns {@link SectionContribution} of the module + * Returns {@link SectionContribution} of the module. This seems to be just one of possibly + * many SectionContributions for the module (at least of ModuleInformation600; need to check + * for older PDBs/ModuleInformation500). User should consult the debugInfo + * SectionContributionList for full list of SectionContributions, which also (at least for + * newer PDBs) has many contributions that all refer to the same module (contributions are + * relatively small) * @return {@link SectionContribution} of the module */ public SectionContribution getSectionContribution() { diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SectionContribution.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SectionContribution.java index b7d487e9c4..66755e0783 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SectionContribution.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/SectionContribution.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.pdb2.pdbreader; import java.io.*; +import ghidra.app.util.bin.format.pe.SectionFlags; + /** * This class represents Section Contribution component of a PDB file. This class is only * suitable for reading; not for writing or modifying a PDB. @@ -62,6 +64,16 @@ public abstract class SectionContribution { return imod; } + /** + * Returns the characteristics. Believe these to be documented at: + * https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header + * User can likely get interpretation from {@link SectionFlags#resolveFlags(int value)} + * @return the characteristics + */ + public long getCharacteristics() { + return characteristics; + } + @Override public String toString() { StringWriter writer = new StringWriter(); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/AbstractComplexMsType.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/AbstractComplexMsType.java index 26cf1100a2..7f137f08ef 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/AbstractComplexMsType.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/AbstractComplexMsType.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -104,7 +104,7 @@ public abstract class AbstractComplexMsType extends AbstractMsType { /** * Returns the mangled name within this complex type - * @return Mangled name + * @return Mangled name; can be null */ public String getMangledName() { return mangledName; diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/FunctionMsAttributes.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/FunctionMsAttributes.java index 6343728650..cee6f22d40 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/FunctionMsAttributes.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/bin/format/pdb2/pdbreader/type/FunctionMsAttributes.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -58,7 +58,11 @@ public class FunctionMsAttributes extends AbstractParsableItem { isInstanceConstructorOfClassWithVirtualBases = ((attributes & 0x0001) == 0x0001); } - boolean isConstructor() { + /** + * Returns {@code true} if flagged as a constructor + * @return {@code true} if is constructor + */ + public boolean isConstructor() { return isInstanceConstructor || isInstanceConstructorOfClassWithVirtualBases; } 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 ddc9971bac..86e41960b8 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 @@ -72,6 +72,11 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier { */ //return mine or my def's (and set mine) SymbolPath getFixedSymbolPath(AbstractComplexMsType type) { + CppCompositeType compType = applicator.getClassType(type); + if (compType != null) { + // Return path if it has already been processed + return compType.getSymbolPath(); + } SymbolPath path = getSymbolPath(type); RecordNumber mappedNumber = applicator.getMappedRecordNumber(type.getRecordNumber()); Integer num = mappedNumber.getNumber(); diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java index bc5d7336a7..58598a2f65 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/AbstractFunctionTypeApplier.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import ghidra.app.util.DataTypeNamingUtil; +import ghidra.app.util.SymbolPath; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber; import ghidra.app.util.bin.format.pdb2.pdbreader.type.*; @@ -79,8 +80,9 @@ public abstract class AbstractFunctionTypeApplier extends MsDataTypeApplier { /** * Processes containing class if one exists * @param type the PDB type being inspected + * @return symbol path of containing type; {@code null} if does not exist */ - protected abstract void processContainingType(AbstractMsType type); + protected abstract SymbolPath processContainingType(AbstractMsType type); /** * Returns if known to be a constructor. @@ -220,10 +222,12 @@ public abstract class AbstractFunctionTypeApplier extends MsDataTypeApplier { return false; } - FunctionDefinitionDataType functionDefinition = new FunctionDefinitionDataType( - applicator.getAnonymousFunctionsCategory(), "_func", applicator.getDataTypeManager()); + SymbolPath spContainer = processContainingType(type); + + CategoryPath cpFunction = getFunctionCategoryPath(spContainer); + FunctionDefinitionDataType functionDefinition = new FunctionDefinitionDataType( + cpFunction, "_func", applicator.getDataTypeManager()); - processContainingType(type); setReturnType(functionDefinition, type); setArguments(functionDefinition, type); Pointer thisPointer = getThisPointer(type); @@ -238,6 +242,16 @@ public abstract class AbstractFunctionTypeApplier extends MsDataTypeApplier { return true; } + private CategoryPath getFunctionCategoryPath(SymbolPath spContainer) { + CategoryPath cpStandard = applicator.getAnonymousFunctionsCategory(); + if (spContainer == null) { + return cpStandard; + } + CategoryPath cpContainer = applicator.getCategory(spContainer); + // Add the "standard" name to the container path + return cpContainer.extend(cpStandard.getName()); + } + /** * Uses {@link DefaultPdbApplicator#getDataTypeOrSchedule(RecordNumber)}) on all underlying * types to ensure that the types get scheduled... and detects whether any types were not yet 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 955ccd6f5b..8877d2f0cc 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 @@ -2226,12 +2226,12 @@ public class DefaultPdbApplicator implements PdbApplicator { } //============================================================================================== - void predefineClass(SymbolPath classPath) { - if (classPath == null) { + void predefineClass(SymbolPath symbolPath) { + if (symbolPath == null) { return; } - isClassByNamespace.put(classPath, true); - for (SymbolPath path = classPath.getParent(); path != null; path = path.getParent()) { + isClassByNamespace.put(symbolPath, true); + for (SymbolPath path = symbolPath.getParent(); path != null; path = path.getParent()) { if (!isClassByNamespace.containsKey(path)) { isClassByNamespace.put(path, false); // path is simple namespace } diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java index 3cf2e60d36..1c5fee44d6 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/FunctionSymbolApplier.java @@ -25,8 +25,7 @@ import ghidra.app.util.bin.format.pdb2.pdbreader.symbol.*; import ghidra.app.util.bin.format.pdb2.pdbreader.type.*; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSet; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.FunctionDefinition; +import ghidra.program.model.data.*; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.SourceType; @@ -119,6 +118,9 @@ public class FunctionSymbolApplier extends AbstractBlockContextApplier return symbolPath; } + // For Future investigation + //String modName = getConstructorName(symbolPath); + // Get containing type, and while we are at it, ensure that it is defined as a class // namespace. // This has likely already been done, but we want to be sure that it has. @@ -170,6 +172,29 @@ public class FunctionSymbolApplier extends AbstractBlockContextApplier return new SymbolPath(parts); } + // For Future investigation + @SuppressWarnings("unused") + private String getConstructorName(SymbolPath symbolPath) { + if (isConstructor() && function != null) { + DataType ret = function.getReturnType(); + if (ret != null) { + if (ret instanceof Pointer p) { + DataType u = p.getDataType(); + if (u instanceof Composite c) { + String s = c.getName(); + String x = symbolPath.getName(); + if (!s.equals(x)) { + // Future investigation? In what cases does this hit? + // For example, triggers on x:=DName<1> and s:=DName + // (standard embedded msft demangler stuff found in most binaries) + } + } + } + } + } + return null; + } + /** * returns true only if we set a function signature * @return true if function signature was set @@ -232,6 +257,22 @@ public class FunctionSymbolApplier extends AbstractBlockContextApplier return true; } + /** + * Returns true if we can tell that we have a constructor type; false if not or we cannot tell + * @return true if we know that we have a constructor type + */ + private boolean isConstructor() { + RecordNumber typeRecordNumber = symbol.getTypeRecordNumber(); + AbstractMsType fType = applicator.getTypeRecord(typeRecordNumber); + if (fType instanceof AbstractMemberFunctionMsType memFn) { + return memFn.getFunctionAttributes().isConstructor(); + } + else if (fType instanceof AbstractProcedureMsType fn) { + return fn.getFunctionAttributes().isConstructor(); + } + return false; + } + //============================================================================================== @Override public void deferredApply(MsSymbolIterator iter) throws PdbException, CancelledException { diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MemberFunctionTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MemberFunctionTypeApplier.java index 0f608beee7..806d4fcb4b 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MemberFunctionTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/MemberFunctionTypeApplier.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -67,7 +67,8 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier { return null; } if (mType instanceof AbstractPointerMsType msPtr) { - predefineClass(msPtr.getUnderlyingRecordNumber()); + SymbolPath sp = getClassSymbolPath(msPtr.getUnderlyingRecordNumber()); + applicator.predefineClass(sp); } applicator.getPdbApplicatorMetrics().witnessMemberFunctionThisPointer(mType); DataType dt = applicator.getDataType(ptrRecord); @@ -78,32 +79,33 @@ public class MemberFunctionTypeApplier extends AbstractFunctionTypeApplier { } @Override - protected void processContainingType(AbstractMsType type) { + protected SymbolPath processContainingType(AbstractMsType type) { // TODO: evaluate whether we need to schedule this container type... guessing not RecordNumber containerRecord = ((AbstractMemberFunctionMsType) type).getContainingClassRecordNumber(); if (containerRecord == null) { - return; + return null; } - predefineClass(containerRecord); + SymbolPath sp = getClassSymbolPath(containerRecord); + applicator.predefineClass(sp); AbstractMsType mType = applicator.getTypeRecord(containerRecord); applicator.getPdbApplicatorMetrics().witnessMemberFunctionContainingType(mType); + return sp; } - private void predefineClass(RecordNumber recordNumber) { + private SymbolPath getClassSymbolPath(RecordNumber recordNumber) { AbstractMsType type = applicator.getTypeRecord(recordNumber); if (!(type instanceof AbstractCompositeMsType msComposite)) { - return; + return null; } MsTypeApplier applier = applicator.getTypeApplier(recordNumber); if (!(applier instanceof CompositeTypeApplier compApplier)) { - return; + return null; } // 20240709: found example of "this" pointer of method that referenced a composite that // did not have any base classes or methods. So we want to make sure we take the // opportunity here to promote the namespace to a class. - SymbolPath sp = compApplier.getFixedSymbolPath(msComposite); - applicator.predefineClass(sp); + return compApplier.getFixedSymbolPath(msComposite); } @Override diff --git a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureTypeApplier.java b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureTypeApplier.java index 6ca2c351e3..7719a941e6 100644 --- a/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureTypeApplier.java +++ b/Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/ProcedureTypeApplier.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,6 +15,7 @@ */ package ghidra.app.util.pdb.pdbapplicator; +import ghidra.app.util.SymbolPath; import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException; import ghidra.app.util.bin.format.pdb2.pdbreader.RecordNumber; import ghidra.app.util.bin.format.pdb2.pdbreader.type.*; @@ -59,8 +60,8 @@ public class ProcedureTypeApplier extends AbstractFunctionTypeApplier { } @Override - protected void processContainingType(AbstractMsType type) { - return; // do nothing + protected SymbolPath processContainingType(AbstractMsType type) { + return null; // do nothing } @Override