mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-23 10:26:02 +08:00
GP-6499 - Various PDB tweaks
This commit is contained in:
+6
-1
@@ -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() {
|
||||
|
||||
+14
-2
@@ -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();
|
||||
|
||||
+3
-3
@@ -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;
|
||||
|
||||
+7
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -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();
|
||||
|
||||
+18
-4
@@ -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
|
||||
|
||||
+4
-4
@@ -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
|
||||
}
|
||||
|
||||
+43
-2
@@ -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 {
|
||||
|
||||
+13
-11
@@ -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
|
||||
|
||||
+5
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user