mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-5076 change PDB class naming for bases and internal category and
significant change to tests
This commit is contained in:
parent
6086ba9bfb
commit
ed7cc31cfd
5 changed files with 4514 additions and 5821 deletions
|
@ -0,0 +1,35 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util;
|
||||||
|
|
||||||
|
import ghidra.program.model.data.PointerDataType;
|
||||||
|
|
||||||
|
public class ClassUtils {
|
||||||
|
|
||||||
|
// Prototype values for now. Need to come to agreement on what these should be
|
||||||
|
public static final String VBPTR = "{vbptr}";
|
||||||
|
public static final String VFPTR = "{vfptr}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type used for {@link #VBPTR} and {@link #VFPTR} fields in a class
|
||||||
|
*/
|
||||||
|
public static final PointerDataType VXPTR_TYPE = new PointerDataType();
|
||||||
|
|
||||||
|
private ClassUtils() {
|
||||||
|
// no instances
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -362,16 +362,15 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
|
||||||
applicator.checkCancelled();
|
applicator.checkCancelled();
|
||||||
RecordNumber recordNumber = vftPtr.getPointerTypeRecordNumber();
|
RecordNumber recordNumber = vftPtr.getPointerTypeRecordNumber();
|
||||||
DataType dataType = applicator.getDataType(recordNumber);
|
DataType dataType = applicator.getDataType(recordNumber);
|
||||||
if (dataType == null) {
|
if (!(dataType instanceof Pointer ptrType)) {
|
||||||
throw new PdbException("Type not processed for record: " + recordNumber);
|
throw new PdbException("vftptr not pointer type for record: " + recordNumber);
|
||||||
}
|
}
|
||||||
int offset = vftPtr.getOffset();
|
int offset = vftPtr.getOffset();
|
||||||
String vftPtrMemberName = vftPtr.getName();
|
String vftPtrMemberName = vftPtr.getName();
|
||||||
DefaultPdbUniversalMember member =
|
DefaultPdbUniversalMember member =
|
||||||
new DefaultPdbUniversalMember(vftPtrMemberName, dataType, offset);
|
new DefaultPdbUniversalMember(vftPtrMemberName, dataType, offset);
|
||||||
myMembers.add(member);
|
myMembers.add(member);
|
||||||
myClassType.addVirtualFunctionTablePointer(member.getName(),
|
myClassType.addVirtualFunctionTablePointer(ptrType, offset);
|
||||||
member.getDataType().getDataType(), member.getOffset());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import ghidra.app.util.ClassUtils;
|
||||||
import ghidra.app.util.SymbolPath;
|
import ghidra.app.util.SymbolPath;
|
||||||
import ghidra.app.util.bin.format.pdb.*;
|
import ghidra.app.util.bin.format.pdb.*;
|
||||||
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
import ghidra.app.util.bin.format.pdb2.pdbreader.PdbException;
|
||||||
|
@ -37,6 +38,13 @@ import ghidra.util.task.TaskMonitor;
|
||||||
*/
|
*/
|
||||||
public class CppCompositeType {
|
public class CppCompositeType {
|
||||||
|
|
||||||
|
private static final String SELF_BASE_COMMENT = "Self Base";
|
||||||
|
private static final String BASE_COMMENT = "Base";
|
||||||
|
private static final String VIRTUAL_BASE_COMMENT = "Virtual Base";
|
||||||
|
private static final String VIRTUAL_BASE_SPECULATIVE_COMMENT =
|
||||||
|
"Virtual Base - Speculative Placement";
|
||||||
|
//private static final String INDIRECT_VIRTUAL_BASE_CLASS_COMMENT = "Indirect Virtual Base Class";
|
||||||
|
|
||||||
// Order matters for both base classes and members for class layout. Members get offsets,
|
// Order matters for both base classes and members for class layout. Members get offsets,
|
||||||
// which helps for those, but layout algorithms usually utilize order.
|
// which helps for those, but layout algorithms usually utilize order.
|
||||||
private List<SyntacticBaseClass> syntacticBaseClasses;
|
private List<SyntacticBaseClass> syntacticBaseClasses;
|
||||||
|
@ -44,6 +52,7 @@ public class CppCompositeType {
|
||||||
private List<AbstractMember> myMembers;
|
private List<AbstractMember> myMembers;
|
||||||
private List<Member> layoutMembers;
|
private List<Member> layoutMembers;
|
||||||
private List<Member> layoutVftPtrMembers;
|
private List<Member> layoutVftPtrMembers;
|
||||||
|
private Map<Integer, Pointer> vftPtrTypeByOffset;
|
||||||
private boolean isFinal;
|
private boolean isFinal;
|
||||||
private ClassKey classKey;
|
private ClassKey classKey;
|
||||||
private String className; // String for now.
|
private String className; // String for now.
|
||||||
|
@ -53,20 +62,19 @@ public class CppCompositeType {
|
||||||
private SymbolPath symbolPath;
|
private SymbolPath symbolPath;
|
||||||
private Composite composite;
|
private Composite composite;
|
||||||
private CategoryPath categoryPath;
|
private CategoryPath categoryPath;
|
||||||
|
private CategoryPath internalsCategoryPath;
|
||||||
private ObjectOrientedClassLayout classLayout = null;
|
|
||||||
|
|
||||||
private List<ClassPdbMember> memberData;
|
private List<ClassPdbMember> memberData;
|
||||||
|
|
||||||
private boolean hasDirect;
|
private boolean hasSelfBase;
|
||||||
|
|
||||||
static String createDirectClassName(Composite composite) {
|
static String createSelfBaseClassName(Composite composite) {
|
||||||
return composite.getName() + "_direct";
|
return composite.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
static CategoryPath createDirectCategoryPath(CppCompositeType cppType) {
|
static CategoryPath createSelfBaseCategoryPath(CppCompositeType cppType) {
|
||||||
return cppType.getBaseCategoryName(
|
return cppType.getSelfBaseCategoryName(
|
||||||
CppCompositeType.createDirectClassName(cppType.getComposite()));
|
CppCompositeType.createSelfBaseClassName(cppType.getComposite()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -92,6 +100,7 @@ public class CppCompositeType {
|
||||||
|
|
||||||
memberData = new ArrayList<>();
|
memberData = new ArrayList<>();
|
||||||
layoutVftPtrMembers = new ArrayList<>();
|
layoutVftPtrMembers = new ArrayList<>();
|
||||||
|
vftPtrTypeByOffset = new HashMap<>();
|
||||||
|
|
||||||
isFinal = false;
|
isFinal = false;
|
||||||
classKey = ClassKey.UNKNOWN;
|
classKey = ClassKey.UNKNOWN;
|
||||||
|
@ -100,6 +109,7 @@ public class CppCompositeType {
|
||||||
this.composite = composite;
|
this.composite = composite;
|
||||||
placeholderVirtualBaseTables = new HashMap<>();
|
placeholderVirtualBaseTables = new HashMap<>();
|
||||||
categoryPath = new CategoryPath(composite.getCategoryPath(), composite.getName());
|
categoryPath = new CategoryPath(composite.getCategoryPath(), composite.getName());
|
||||||
|
internalsCategoryPath = new CategoryPath(categoryPath, "!internal");
|
||||||
this.mangledName = mangledName;
|
this.mangledName = mangledName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +224,10 @@ public class CppCompositeType {
|
||||||
return categoryPath;
|
return categoryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CategoryPath getInternalsCategoryPath() {
|
||||||
|
return internalsCategoryPath;
|
||||||
|
}
|
||||||
|
|
||||||
public void setFinal(boolean isFinal) {
|
public void setFinal(boolean isFinal) {
|
||||||
this.isFinal = isFinal;
|
this.isFinal = isFinal;
|
||||||
}
|
}
|
||||||
|
@ -275,9 +289,17 @@ public class CppCompositeType {
|
||||||
return layoutMembers.size();
|
return layoutMembers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addVirtualFunctionTablePointer(String name, DataType dataType, int offset) {
|
public void addVirtualFunctionTablePointer(Pointer ptrType, int offset) {
|
||||||
Member newMember = new Member(name, dataType, false, ClassFieldAttributes.UNKNOWN, offset);
|
// Not using ptrType argument for member... not generic enough
|
||||||
|
Member newMember =
|
||||||
|
new Member(ClassUtils.VFPTR, ClassUtils.VXPTR_TYPE, false, ClassFieldAttributes.UNKNOWN,
|
||||||
|
offset);
|
||||||
layoutVftPtrMembers.add(newMember);
|
layoutVftPtrMembers.add(newMember);
|
||||||
|
vftPtrTypeByOffset.put(offset, ptrType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pointer getVftPtrType(int offset) {
|
||||||
|
return vftPtrTypeByOffset.get(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertVirtualFunctionTablePointers(List<ClassPdbMember> pdbMembers) {
|
private void insertVirtualFunctionTablePointers(List<ClassPdbMember> pdbMembers) {
|
||||||
|
@ -596,33 +618,6 @@ public class CppCompositeType {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectOrientedClassLayout getLayout(ObjectOrientedClassLayout layoutOptions) {
|
|
||||||
if (classLayout == null) {
|
|
||||||
classLayout = determineClassLayout(layoutOptions);
|
|
||||||
}
|
|
||||||
return classLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObjectOrientedClassLayout determineClassLayout(
|
|
||||||
ObjectOrientedClassLayout layoutOptions) {
|
|
||||||
ObjectOrientedClassLayout initialLayoutDetermination;
|
|
||||||
if (layoutOptions == ObjectOrientedClassLayout.MEMBERS_ONLY) {
|
|
||||||
return ObjectOrientedClassLayout.MEMBERS_ONLY;
|
|
||||||
}
|
|
||||||
else if (getNumLayoutBaseClasses() == 0) {
|
|
||||||
initialLayoutDetermination = ObjectOrientedClassLayout.BASIC_SIMPLE_COMPLEX;
|
|
||||||
}
|
|
||||||
else if (getNumLayoutVirtualBaseClasses() == 0) {
|
|
||||||
initialLayoutDetermination = ObjectOrientedClassLayout.SIMPLE_COMPLEX;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
initialLayoutDetermination = ObjectOrientedClassLayout.COMPLEX;
|
|
||||||
}
|
|
||||||
ObjectOrientedClassLayout classLayoutOption = layoutOptions;
|
|
||||||
return classLayoutOption.compareTo(initialLayoutDetermination) >= 0 ? classLayoutOption
|
|
||||||
: initialLayoutDetermination;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isZeroSize() {
|
boolean isZeroSize() {
|
||||||
return memberData.size() == 0;
|
return memberData.size() == 0;
|
||||||
}
|
}
|
||||||
|
@ -659,76 +654,70 @@ public class CppCompositeType {
|
||||||
public void createVbtBasedLayout(ObjectOrientedClassLayout layoutOptions, VxtManager vxtManager,
|
public void createVbtBasedLayout(ObjectOrientedClassLayout layoutOptions, VxtManager vxtManager,
|
||||||
TaskMonitor monitor) throws PdbException, CancelledException {
|
TaskMonitor monitor) throws PdbException, CancelledException {
|
||||||
CategoryPath cn;
|
CategoryPath cn;
|
||||||
hasDirect = false;
|
hasSelfBase = false;
|
||||||
switch (getLayout(layoutOptions)) {
|
switch (layoutOptions) {
|
||||||
case MEMBERS_ONLY:
|
case MEMBERS_ONLY:
|
||||||
addLayoutPdbMembers(memberData, layoutMembers);
|
addLayoutPdbMembers(memberData, layoutMembers);
|
||||||
break;
|
break;
|
||||||
case BASIC_SIMPLE_COMPLEX:
|
case CLASS_HIERARCHY:
|
||||||
addLayoutPdbMembers(memberData, layoutMembers);
|
cn = createSelfBaseCategoryPath(this);
|
||||||
insertVirtualFunctionTablePointers(memberData);
|
Composite selfBaseType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
||||||
break;
|
|
||||||
// TODO: evaluate... not really getting difference I thought we could get... so far
|
|
||||||
// BASIC and SIMPLE seem to yield the same results. I might be doing something wrong.
|
|
||||||
case SIMPLE_COMPLEX:
|
|
||||||
case COMPLEX:
|
|
||||||
cn = createDirectCategoryPath(this);
|
|
||||||
Composite directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
|
||||||
composite.getDataTypeManager());
|
composite.getDataTypeManager());
|
||||||
|
selfBaseType.setDescription("Base of " + cn.getName());
|
||||||
|
|
||||||
List<ClassPdbMember> directClassPdbMembers = getDirectBaseClassMembers(monitor);
|
List<ClassPdbMember> selfBasePdbMembers = getSelfBaseClassMembers(monitor);
|
||||||
List<VirtualLayoutBaseClass> myVirtualLayoutBases = preprocessVirtualBases(monitor);
|
List<VirtualLayoutBaseClass> myVirtualLayoutBases = preprocessVirtualBases(monitor);
|
||||||
|
|
||||||
// TODO: consider moving down below next line.
|
// TODO: consider moving down below next line.
|
||||||
boolean allVbtFound =
|
boolean allVbtFound =
|
||||||
reconcileVirtualBaseTables(composite.getDataTypeManager(), vxtManager);
|
reconcileVirtualBaseTables(composite.getDataTypeManager(), vxtManager);
|
||||||
|
|
||||||
addLayoutPdbMembers(directClassPdbMembers, layoutMembers);
|
addLayoutPdbMembers(selfBasePdbMembers, layoutMembers);
|
||||||
insertVirtualFunctionTablePointers(directClassPdbMembers);
|
insertVirtualFunctionTablePointers(selfBasePdbMembers);
|
||||||
|
|
||||||
if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, false, 0,
|
if (!DefaultCompositeMember.applyDataTypeMembers(selfBaseType, false, false, 0,
|
||||||
directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) {
|
selfBasePdbMembers, msg -> Msg.warn(this, msg), monitor)) {
|
||||||
clearComponents(directDataType);
|
clearComponents(selfBaseType);
|
||||||
}
|
}
|
||||||
int directClassLength = getCompositeLength(directDataType);
|
int selfBaseLength = getCompositeLength(selfBaseType);
|
||||||
|
|
||||||
if (directClassLength == 0) {
|
if (selfBaseLength == 0) {
|
||||||
// Not using the direct type (only used it to get the directClassLength), so
|
// Not using the direct type (only used it to get the selfBaseLength), so
|
||||||
// remove it and add the members to the main type instead.
|
// remove it and add the members to the main type instead.
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this does not deal with the case where more members from memberData get
|
// this does not deal with the case where more members from memberData get
|
||||||
// added below and must still fit in "size."
|
// added below and must still fit in "size."
|
||||||
if (directClassLength > size) {
|
if (selfBaseLength > size) {
|
||||||
// Redo it with the size of the overall structure/class
|
// Redo it with the size of the overall structure/class
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
selfBaseType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
||||||
composite.getDataTypeManager());
|
composite.getDataTypeManager());
|
||||||
if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false,
|
if (!DefaultCompositeMember.applyDataTypeMembers(selfBaseType, false,
|
||||||
false, size, directClassPdbMembers, msg -> Msg.warn(this, msg),
|
false, size, selfBasePdbMembers, msg -> Msg.warn(this, msg),
|
||||||
monitor)) {
|
monitor)) {
|
||||||
clearComponents(directDataType);
|
clearComponents(selfBaseType);
|
||||||
}
|
}
|
||||||
directClassLength = getCompositeLength(directDataType);
|
selfBaseLength = getCompositeLength(selfBaseType);
|
||||||
}
|
}
|
||||||
if (getLayout(layoutOptions) == ObjectOrientedClassLayout.SIMPLE_COMPLEX) {
|
if (getNumLayoutVirtualBaseClasses() == 0) {
|
||||||
// Not using the dummy/direct type (only used it to get the
|
// Not using the dummy/direct type (only used it to get the
|
||||||
// directClassLength), so remove it and add the members to the main
|
// selfBaseLength), so remove it and add the members to the main
|
||||||
// type instead.
|
// type instead.
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
memberData.addAll(directClassPdbMembers);
|
memberData.addAll(selfBasePdbMembers);
|
||||||
//addLayoutPdbMembers(memberData, layoutMembers, monitor);
|
//addLayoutPdbMembers(memberData, layoutMembers, monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClassPdbMember directClassPdbMember =
|
ClassPdbMember directClassPdbMember =
|
||||||
new ClassPdbMember("", directDataType, false, 0, null);
|
new ClassPdbMember("", selfBaseType, false, 0, SELF_BASE_COMMENT);
|
||||||
memberData.add(directClassPdbMember);
|
memberData.add(directClassPdbMember);
|
||||||
hasDirect = true;
|
hasSelfBase = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addVirtualBases(directClassLength, memberData, myVirtualLayoutBases, allVbtFound,
|
addVirtualBases(selfBaseLength, memberData, myVirtualLayoutBases, allVbtFound,
|
||||||
monitor);
|
monitor);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -744,9 +733,9 @@ public class CppCompositeType {
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
private List<ClassPdbMember> getDirectBaseClassMembers(TaskMonitor monitor)
|
private List<ClassPdbMember> getSelfBaseClassMembers(TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
List<ClassPdbMember> myDirectClassPdbMembers = new ArrayList<>();
|
List<ClassPdbMember> mySelfClassPdbMembers = new ArrayList<>();
|
||||||
TreeMap<Integer, Member> orderedBaseMembers = new TreeMap<>();
|
TreeMap<Integer, Member> orderedBaseMembers = new TreeMap<>();
|
||||||
for (LayoutBaseClass base : getLayoutBaseClasses()) {
|
for (LayoutBaseClass base : getLayoutBaseClasses()) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
|
@ -755,18 +744,16 @@ public class CppCompositeType {
|
||||||
if (!baseComposite.isZeroSize()) {
|
if (!baseComposite.isZeroSize()) {
|
||||||
Composite baseDataType = base.getDirectDataType();
|
Composite baseDataType = base.getDirectDataType();
|
||||||
int offset = ((DirectLayoutBaseClass) base).getOffset();
|
int offset = ((DirectLayoutBaseClass) base).getOffset();
|
||||||
CategoryPath cn =
|
|
||||||
getBaseCategoryName("BaseClass_" + base.getBaseClassType().getName());
|
|
||||||
Member baseMember =
|
Member baseMember =
|
||||||
new Member("", baseDataType, false, null, offset, cn.toString());
|
new Member("", baseDataType, false, null, offset, BASE_COMMENT);
|
||||||
orderedBaseMembers.put(offset, baseMember);
|
orderedBaseMembers.put(offset, baseMember);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Member baseMember : orderedBaseMembers.values()) {
|
for (Member baseMember : orderedBaseMembers.values()) {
|
||||||
addPdbMember(myDirectClassPdbMembers, baseMember);
|
addPdbMember(mySelfClassPdbMembers, baseMember);
|
||||||
}
|
}
|
||||||
return myDirectClassPdbMembers;
|
return mySelfClassPdbMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
@ -796,80 +783,73 @@ public class CppCompositeType {
|
||||||
// so with multiple virtual inheritance, a parent from multiple family lines will likely
|
// so with multiple virtual inheritance, a parent from multiple family lines will likely
|
||||||
// get moved.
|
// get moved.
|
||||||
CategoryPath cn;
|
CategoryPath cn;
|
||||||
hasDirect = false;
|
hasSelfBase = false;
|
||||||
switch (getLayout(layoutOptions)) {
|
switch (layoutOptions) {
|
||||||
case MEMBERS_ONLY:
|
case MEMBERS_ONLY:
|
||||||
addLayoutPdbMembers(memberData, layoutMembers);
|
addLayoutPdbMembers(memberData, layoutMembers);
|
||||||
break;
|
break;
|
||||||
case BASIC_SIMPLE_COMPLEX:
|
case CLASS_HIERARCHY:
|
||||||
cn = composite.getCategoryPath();
|
cn = createSelfBaseCategoryPath(this);
|
||||||
addLayoutPdbMembers(memberData, layoutMembers);
|
Composite selfBaseType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
||||||
insertVirtualFunctionTablePointers(memberData);
|
|
||||||
break;
|
|
||||||
// TODO: evaluate... not really getting difference I thought we could get... so far
|
|
||||||
// BASIC and SIMPLE seem to yield the same results. I might be doing something wrong.
|
|
||||||
case SIMPLE_COMPLEX:
|
|
||||||
case COMPLEX:
|
|
||||||
cn = createDirectCategoryPath(this);
|
|
||||||
Composite directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
|
||||||
composite.getDataTypeManager());
|
composite.getDataTypeManager());
|
||||||
|
selfBaseType.setDescription("Base of " + cn.getName());
|
||||||
|
|
||||||
List<LayoutBaseClass> myAccumulatedDirectBases = new ArrayList<>();
|
List<LayoutBaseClass> myAccumulatedDirectBases = new ArrayList<>();
|
||||||
List<VirtualLayoutBaseClass> myAccumulatedVirtualBases = new ArrayList<>();
|
List<VirtualLayoutBaseClass> myAccumulatedVirtualBases = new ArrayList<>();
|
||||||
List<ClassPdbMember> directClassPdbMembers = new ArrayList<>();
|
List<ClassPdbMember> selfBasePdbMembers = new ArrayList<>();
|
||||||
processBaseClassesRecursive(this, true, directClassPdbMembers,
|
processBaseClassesRecursive(this, true, selfBasePdbMembers,
|
||||||
myAccumulatedDirectBases, myAccumulatedVirtualBases, 0, monitor);
|
myAccumulatedDirectBases, myAccumulatedVirtualBases, 0, monitor);
|
||||||
|
|
||||||
// TODO: consider moving down below next line.
|
// TODO: consider moving down below next line.
|
||||||
boolean allVbtFound =
|
boolean allVbtFound =
|
||||||
reconcileVirtualBaseTables(composite.getDataTypeManager(), vxtManager);
|
reconcileVirtualBaseTables(composite.getDataTypeManager(), vxtManager);
|
||||||
|
|
||||||
addLayoutPdbMembers(directClassPdbMembers, layoutMembers);
|
addLayoutPdbMembers(selfBasePdbMembers, layoutMembers);
|
||||||
insertVirtualFunctionTablePointers(directClassPdbMembers);
|
insertVirtualFunctionTablePointers(selfBasePdbMembers);
|
||||||
|
|
||||||
if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false, false, 0,
|
if (!DefaultCompositeMember.applyDataTypeMembers(selfBaseType, false, false, 0,
|
||||||
directClassPdbMembers, msg -> Msg.warn(this, msg), monitor)) {
|
selfBasePdbMembers, msg -> Msg.warn(this, msg), monitor)) {
|
||||||
clearComponents(directDataType);
|
clearComponents(selfBaseType);
|
||||||
}
|
}
|
||||||
int directClassLength = getCompositeLength(directDataType);
|
int selfBaseLength = getCompositeLength(selfBaseType);
|
||||||
|
|
||||||
if (directClassLength == 0) {
|
if (selfBaseLength == 0) {
|
||||||
// Not using the direct type (only used it to get the directClassLength), so
|
// Not using the direct type (only used it to get the selfBaseLength), so
|
||||||
// remove it and add the members to the main type instead.
|
// remove it and add the members to the main type instead.
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this does not deal with the case where more members from memberData get
|
// this does not deal with the case where more members from memberData get
|
||||||
// added below and must still fit in "size."
|
// added below and must still fit in "size."
|
||||||
if (directClassLength > size) {
|
if (selfBaseLength > size) {
|
||||||
// Redo it with the size of the overall structure/class
|
// Redo it with the size of the overall structure/class
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
directDataType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
selfBaseType = new StructureDataType(cn.getParent(), cn.getName(), 0,
|
||||||
composite.getDataTypeManager());
|
composite.getDataTypeManager());
|
||||||
if (!DefaultCompositeMember.applyDataTypeMembers(directDataType, false,
|
if (!DefaultCompositeMember.applyDataTypeMembers(selfBaseType, false,
|
||||||
false, size, directClassPdbMembers, msg -> Msg.warn(this, msg),
|
false, size, selfBasePdbMembers, msg -> Msg.warn(this, msg),
|
||||||
monitor)) {
|
monitor)) {
|
||||||
clearComponents(directDataType);
|
clearComponents(selfBaseType);
|
||||||
}
|
}
|
||||||
directClassLength = getCompositeLength(directDataType);
|
selfBaseLength = getCompositeLength(selfBaseType);
|
||||||
}
|
}
|
||||||
if (getLayout(layoutOptions) == ObjectOrientedClassLayout.SIMPLE_COMPLEX) {
|
if (getNumLayoutVirtualBaseClasses() == 0) {
|
||||||
// Not using the dummy/direct type (only used it to get the
|
// Not using the dummy/direct type (only used it to get the
|
||||||
// directClassLength), so remove it and add the members to the main
|
// selfBaseLength), so remove it and add the members to the main
|
||||||
// type instead.
|
// type instead.
|
||||||
directDataType.getDataTypeManager().remove(directDataType, monitor);
|
selfBaseType.getDataTypeManager().remove(selfBaseType, monitor);
|
||||||
memberData.addAll(directClassPdbMembers);
|
memberData.addAll(selfBasePdbMembers);
|
||||||
//addLayoutPdbMembers(memberData, layoutMembers, monitor);
|
//addLayoutPdbMembers(memberData, layoutMembers, monitor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClassPdbMember directClassPdbMember =
|
ClassPdbMember directClassPdbMember =
|
||||||
new ClassPdbMember("", directDataType, false, 0, null);
|
new ClassPdbMember("", selfBaseType, false, 0, SELF_BASE_COMMENT);
|
||||||
memberData.add(directClassPdbMember);
|
memberData.add(directClassPdbMember);
|
||||||
hasDirect = true;
|
hasSelfBase = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addVirtualBasesSpeculatively(directClassLength, memberData,
|
addVirtualBasesSpeculatively(selfBaseLength, memberData,
|
||||||
myAccumulatedVirtualBases, monitor);
|
myAccumulatedVirtualBases, monitor);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -902,10 +882,8 @@ public class CppCompositeType {
|
||||||
if (!baseComposite.isZeroSize()) {
|
if (!baseComposite.isZeroSize()) {
|
||||||
Composite baseDataType = base.getDirectDataType();
|
Composite baseDataType = base.getDirectDataType();
|
||||||
int offset = ((DirectLayoutBaseClass) base).getOffset();
|
int offset = ((DirectLayoutBaseClass) base).getOffset();
|
||||||
CategoryPath cn =
|
|
||||||
getBaseCategoryName("BaseClass_" + base.getBaseClassType().getName());
|
|
||||||
Member baseMember =
|
Member baseMember =
|
||||||
new Member("", baseDataType, false, null, offset, cn.toString());
|
new Member("", baseDataType, false, null, offset, BASE_COMMENT);
|
||||||
addPdbMember(myPdbMembers, baseMember);
|
addPdbMember(myPdbMembers, baseMember);
|
||||||
}
|
}
|
||||||
myAccumulatedDirectBases.add(base);
|
myAccumulatedDirectBases.add(base);
|
||||||
|
@ -1012,10 +990,10 @@ public class CppCompositeType {
|
||||||
CppParentageAndMember cAndP = findDirectBaseParentageAndMember(this, 0, vbtptrOffset);
|
CppParentageAndMember cAndP = findDirectBaseParentageAndMember(this, 0, vbtptrOffset);
|
||||||
|
|
||||||
if (cAndP == null) {
|
if (cAndP == null) {
|
||||||
insertMember("{vbptr}", vbptr, false, vbtptrOffset, "{vbptr} for " + myClass);
|
insertMember(ClassUtils.VBPTR, ClassUtils.VXPTR_TYPE, false, vbtptrOffset, null);
|
||||||
}
|
}
|
||||||
else if (!"{vbptr}".equals(cAndP.member().getName())) {
|
else if (!ClassUtils.VBPTR.equals(cAndP.member().getName())) {
|
||||||
String message = "PDB: Collision of non-{vbptr}.";
|
String message = "PDB: Collision of non-" + ClassUtils.VBPTR;
|
||||||
PdbLog.message(message);
|
PdbLog.message(message);
|
||||||
Msg.info(this, message);
|
Msg.info(this, message);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1027,11 +1005,10 @@ public class CppCompositeType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int entrySize = 4; // Default to something (could be wrong)
|
int entrySize = 4; // Default to something (could be wrong)
|
||||||
if (vbptr instanceof PointerDataType) {
|
if (vbptr instanceof Pointer ptr) {
|
||||||
entrySize = ((PointerDataType) vbptr).getDataType().getLength();
|
entrySize = ptr.getDataType().getLength();
|
||||||
}
|
}
|
||||||
boolean x = findVbt(table, mvxtManager, entrySize, symbolPath, parentage);
|
return findVbt(table, mvxtManager, entrySize, symbolPath, parentage);
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean findVbt(PlaceholderVirtualBaseTable table, MsftVxtManager mvbtm, int entrySize,
|
private boolean findVbt(PlaceholderVirtualBaseTable table, MsftVxtManager mvbtm, int entrySize,
|
||||||
|
@ -1052,7 +1029,7 @@ public class CppCompositeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
private CppParentageAndMember findDirectBaseParentageAndMember(CppCompositeType cppType,
|
private CppParentageAndMember findDirectBaseParentageAndMember(CppCompositeType cppType,
|
||||||
int offsetCppType, int vbtptrOffset) throws PdbException {
|
int offsetCppType, int offset) throws PdbException {
|
||||||
for (LayoutBaseClass base : cppType.layoutBaseClasses) {
|
for (LayoutBaseClass base : cppType.layoutBaseClasses) {
|
||||||
if (!(base instanceof DirectLayoutBaseClass)) {
|
if (!(base instanceof DirectLayoutBaseClass)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1060,13 +1037,13 @@ public class CppCompositeType {
|
||||||
DirectLayoutBaseClass directBase = (DirectLayoutBaseClass) base;
|
DirectLayoutBaseClass directBase = (DirectLayoutBaseClass) base;
|
||||||
int directBaseOffset = directBase.getOffset() + offsetCppType;
|
int directBaseOffset = directBase.getOffset() + offsetCppType;
|
||||||
int directBaseLength = directBase.getDirectDataType().getLength();
|
int directBaseLength = directBase.getDirectDataType().getLength();
|
||||||
if (vbtptrOffset >= directBaseOffset &&
|
if (offset >= directBaseOffset &&
|
||||||
vbtptrOffset < directBaseOffset + directBaseLength) {
|
offset < directBaseOffset + directBaseLength) {
|
||||||
CppCompositeType childCppType = directBase.getBaseClassType();
|
CppCompositeType childCppType = directBase.getBaseClassType();
|
||||||
CppParentageAndMember cAndP =
|
CppParentageAndMember cAndP =
|
||||||
findDirectBaseParentageAndMember(childCppType, directBaseOffset, vbtptrOffset);
|
findDirectBaseParentageAndMember(childCppType, directBaseOffset, offset);
|
||||||
if (cAndP == null) {
|
if (cAndP == null) {
|
||||||
Member member = childCppType.findLayoutMemberOrVftPtrMember(vbtptrOffset);
|
Member member = childCppType.findLayoutMember(offset);
|
||||||
if (member == null) {
|
if (member == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1080,17 +1057,20 @@ public class CppCompositeType {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Member findLayoutMemberOrVftPtrMember(int offset) {
|
private Member findLayoutMember(int offset) {
|
||||||
|
// the following will report the basic, such as int *
|
||||||
for (Member member : layoutMembers) {
|
for (Member member : layoutMembers) {
|
||||||
if (member.getOffset() == offset) {
|
if (member.getOffset() == offset) {
|
||||||
return member;
|
return member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Member member : layoutVftPtrMembers) {
|
// the following will report the more info, such as shape1234 *, but this code will not
|
||||||
if (member.getOffset() == offset) {
|
// hit here, as we should not have an entry for the offset if it did not find it above
|
||||||
return member;
|
// for (Member member : layoutVftPtrMembers) {
|
||||||
}
|
// if (member.getOffset() == offset) {
|
||||||
}
|
// return member;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,6 +1116,8 @@ public class CppCompositeType {
|
||||||
private void addVirtualBases(int startOffset, List<ClassPdbMember> pdbMembers,
|
private void addVirtualBases(int startOffset, List<ClassPdbMember> pdbMembers,
|
||||||
List<VirtualLayoutBaseClass> virtualBases, boolean allVbtFound, TaskMonitor monitor)
|
List<VirtualLayoutBaseClass> virtualBases, boolean allVbtFound, TaskMonitor monitor)
|
||||||
throws PdbException, CancelledException {
|
throws PdbException, CancelledException {
|
||||||
|
// We accumulate the comment because if there are any empty base classes, they take
|
||||||
|
// no space and will be at the same offset as a non-empty base class
|
||||||
String accumulatedComment = "";
|
String accumulatedComment = "";
|
||||||
int memberOffset = startOffset;
|
int memberOffset = startOffset;
|
||||||
List<VirtualLayoutBaseClass> orderedBases = new ArrayList<>();
|
List<VirtualLayoutBaseClass> orderedBases = new ArrayList<>();
|
||||||
|
@ -1160,18 +1142,20 @@ public class CppCompositeType {
|
||||||
// }
|
// }
|
||||||
memberOffset += basePointerOffset;
|
memberOffset += basePointerOffset;
|
||||||
if (virtualBaseLength != 0) {
|
if (virtualBaseLength != 0) {
|
||||||
String comment =
|
String comment = VIRTUAL_BASE_COMMENT;
|
||||||
"(Virtual Base " + virtualBase.getDataTypePath().getDataTypeName() + ")";
|
if (!accumulatedComment.isEmpty()) {
|
||||||
accumulatedComment += comment;
|
comment += " and previous " + accumulatedComment;
|
||||||
|
}
|
||||||
|
//accumulatedComment += "Virtual Base";
|
||||||
ClassPdbMember virtualClassPdbMember =
|
ClassPdbMember virtualClassPdbMember =
|
||||||
new ClassPdbMember("", baseDataType, false, memberOffset, accumulatedComment);
|
new ClassPdbMember("", baseDataType, false, memberOffset, comment);
|
||||||
pdbMembers.add(virtualClassPdbMember);
|
pdbMembers.add(virtualClassPdbMember);
|
||||||
memberOffset += virtualBaseLength;
|
memberOffset += virtualBaseLength;
|
||||||
accumulatedComment = "";
|
accumulatedComment = "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String comment = "(Virtual Base (empty) " +
|
String comment =
|
||||||
virtualBase.getDataTypePath().getDataTypeName() + ")";
|
"(Empty Virtual Base " + virtualBase.getDataTypePath().getDataTypeName() + ")";
|
||||||
accumulatedComment += comment;
|
accumulatedComment += comment;
|
||||||
}
|
}
|
||||||
// If last base is empty, then its comment and any accumulated to this point
|
// If last base is empty, then its comment and any accumulated to this point
|
||||||
|
@ -1211,6 +1195,8 @@ public class CppCompositeType {
|
||||||
private void addVirtualBasesSpeculatively(int startOffset, List<ClassPdbMember> pdbMembers,
|
private void addVirtualBasesSpeculatively(int startOffset, List<ClassPdbMember> pdbMembers,
|
||||||
List<VirtualLayoutBaseClass> virtualBases, TaskMonitor monitor)
|
List<VirtualLayoutBaseClass> virtualBases, TaskMonitor monitor)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
// We accumulate the comment because if there are any empty base classes, they take
|
||||||
|
// no space and will be at the same offset as a non-empty base class
|
||||||
String accumulatedComment = "";
|
String accumulatedComment = "";
|
||||||
int memberOffset = startOffset;
|
int memberOffset = startOffset;
|
||||||
for (VirtualLayoutBaseClass virtualBase : virtualBases) {
|
for (VirtualLayoutBaseClass virtualBase : virtualBases) {
|
||||||
|
@ -1219,8 +1205,7 @@ public class CppCompositeType {
|
||||||
int virtualBaseLength = getCompositeLength(baseDataType);
|
int virtualBaseLength = getCompositeLength(baseDataType);
|
||||||
|
|
||||||
if (virtualBaseLength != 0) {
|
if (virtualBaseLength != 0) {
|
||||||
String comment = "((Speculative Placement) Virtual Base " +
|
String comment = VIRTUAL_BASE_SPECULATIVE_COMMENT;
|
||||||
virtualBase.getDataTypePath().getDataTypeName() + ")";
|
|
||||||
accumulatedComment += comment;
|
accumulatedComment += comment;
|
||||||
ClassPdbMember virtualClassPdbMember =
|
ClassPdbMember virtualClassPdbMember =
|
||||||
new ClassPdbMember("", baseDataType, false, memberOffset, accumulatedComment);
|
new ClassPdbMember("", baseDataType, false, memberOffset, accumulatedComment);
|
||||||
|
@ -1285,8 +1270,8 @@ public class CppCompositeType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CategoryPath getBaseCategoryName(String baseName) {
|
CategoryPath getSelfBaseCategoryName(String baseName) {
|
||||||
CategoryPath cn = getCategoryPath();
|
CategoryPath cn = getInternalsCategoryPath();
|
||||||
return new CategoryPath(cn, baseName);
|
return new CategoryPath(cn, baseName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,10 +1313,6 @@ public class CppCompositeType {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectOrientedClassLayout getLayoutMode(ObjectOrientedClassLayout layoutOptions) {
|
|
||||||
return baseClassType.getLayout(layoutOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataTypePath getDataTypePath() {
|
DataTypePath getDataTypePath() {
|
||||||
return new DataTypePath(baseClassType.getCategoryPath().getParent(),
|
return new DataTypePath(baseClassType.getCategoryPath().getParent(),
|
||||||
baseClassType.getCategoryPath().getName());
|
baseClassType.getCategoryPath().getName());
|
||||||
|
@ -1346,21 +1327,19 @@ public class CppCompositeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
Composite getDirectDataType() {
|
Composite getDirectDataType() {
|
||||||
Composite c = getBaseClassType().getComposite();
|
CppCompositeType cct = getBaseClassType();
|
||||||
if (c.getNumComponents() == 0) {
|
CategoryPath selfBasePath = createSelfBaseCategoryPath(cct);
|
||||||
return c;
|
DataTypeManager dtm = cct.getComposite().getDataTypeManager();
|
||||||
|
DataType base = dtm.getDataType(selfBasePath.getParent(), selfBasePath.getName());
|
||||||
|
if (base == null) {
|
||||||
|
// There is no self base meaning that the layout class is simple and no self
|
||||||
|
// base was needed. So return the layout class
|
||||||
|
base = cct.getComposite();
|
||||||
}
|
}
|
||||||
if (!baseClassType.hasDirect) {
|
if (base instanceof Structure s) {
|
||||||
return c;
|
return s;
|
||||||
}
|
}
|
||||||
DataTypeComponent dtc = c.getComponent(0); // by construction this should be "Direct"
|
throw new AssertException("Cannot find Base type");
|
||||||
DataType dt = dtc.getDataType();
|
|
||||||
Structure bdt;
|
|
||||||
if (!(dt instanceof Structure)) {
|
|
||||||
throw new AssertException("Not Structure for Direct");
|
|
||||||
}
|
|
||||||
bdt = (Structure) dt;
|
|
||||||
return bdt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,17 +19,20 @@ package ghidra.app.util.pdb.pdbapplicator;
|
||||||
* PDB Analyzer user algorithmic choice for performing object oriented class layout.
|
* PDB Analyzer user algorithmic choice for performing object oriented class layout.
|
||||||
* <p>
|
* <p>
|
||||||
* Actual algorithms determination is as follows:
|
* Actual algorithms determination is as follows:
|
||||||
* {@link #MEMBERS_ONLY} is a fixed setting. The others weigh the setting against the data
|
* <p> {@link #MEMBERS_ONLY} is a the legacy output that only shows members of the current class.
|
||||||
* available in the class records. They all start out as {@link #COMPLEX} but fall back to a
|
* <p> {@link #CLASS_HIERARCHY} provides a nested layout more suitable for understanding
|
||||||
* more simplistic layout when the data permits:
|
* the composition of classes from base classes and members from the Structure Editor perspective.
|
||||||
* <p> {@link #SIMPLE_COMPLEX} can fall back to "simple" and
|
|
||||||
* <p> {@link #BASIC_SIMPLE_COMPLEX} can fall back to "simple" or "basic"
|
|
||||||
*/
|
*/
|
||||||
public enum ObjectOrientedClassLayout {
|
public enum ObjectOrientedClassLayout {
|
||||||
MEMBERS_ONLY("Legacy"),
|
/**
|
||||||
BASIC_SIMPLE_COMPLEX("Complex with Basic Fallback"),
|
* Processes members of the current class only; legacy solution
|
||||||
SIMPLE_COMPLEX("Complex with Simple Fallback"),
|
*/
|
||||||
COMPLEX("Complex Always");
|
MEMBERS_ONLY("No C++ Hierarchy (Legacy)"),
|
||||||
|
/**
|
||||||
|
* Include base class hierarchies and other C++-isms into a class layout that is suited for
|
||||||
|
* understanding the hierarchies and components from the Structure Editor perspective
|
||||||
|
*/
|
||||||
|
CLASS_HIERARCHY("Class Hierarchy (Experimental)");
|
||||||
|
|
||||||
private final String label;
|
private final String label;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue