GP-5074 - CPP PDB vxtable datatype composition

This commit is contained in:
ghizard 2025-03-24 06:51:40 -04:00
parent ce6bef1e12
commit edb277177d
27 changed files with 1545 additions and 533 deletions

View file

@ -0,0 +1,108 @@
/* ###
* 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.program.model.gclass;
import java.util.Objects;
import ghidra.app.util.SymbolPath;
import ghidra.program.model.data.CategoryPath;
/**
* Unique ID of a Program Class Type. Not sure if there will be different implementation for
* definition vs. compiled vs. program vs. debug.
*/
public class ClassID implements Comparable<ClassID> {
// All of the internals of this might change, but we need something to work with for now.
// It might end up being a hash/guid/long value.
// We were trying to use DataTypePath, but that doesn't work in light of conflicts, as we
// started with a DataTypePath for the type, which later got resolved to a .conflict (so
// DataTypePath changed out from underneath us).
private final SymbolPath symbolPath;
private final CategoryPath categoryPath;
static final int classNameHash = Objects.hash(ClassID.class.getName());
/**
* Constructor
* @param categoryPath the category path for the claass
* @param symbolPath the symbol path for the class
*/
public ClassID(CategoryPath categoryPath, SymbolPath symbolPath) {
this.categoryPath = categoryPath;
this.symbolPath = symbolPath;
}
/**
* Returns the category path
* @return the category path
*/
public CategoryPath getCategoryPath() {
return categoryPath;
}
/**
* Returns the symbol path
* @return the symbol path
*/
public SymbolPath getSymbolPath() {
return symbolPath;
}
// Might want to do something with data type ID if resolved
// long doIt(DataTypeManager dtm, DataType dt) {
// int x = DataTypeUtilities.getConflictValue(dt);
// long dataTypeID;
// dataTypeID = dtm.getID(dt);
// UniversalID uid = dt.getUniversalID();
// return dataTypeID;
// }
@Override
public String toString() {
return String.format("%s --- %s", categoryPath, symbolPath);
}
@Override
public int compareTo(ClassID o) {
int ret;
ret = symbolPath.compareTo(o.symbolPath);
if (ret != 0) {
return ret;
}
return categoryPath.compareTo(o.categoryPath);
}
@Override
public int hashCode() {
return Objects.hash(categoryPath, symbolPath);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ClassID other = (ClassID) obj;
return Objects.equals(categoryPath, other.categoryPath) &&
Objects.equals(symbolPath, other.symbolPath);
}
}

View file

@ -15,6 +15,7 @@
*/
package ghidra.program.model.gclass;
import ghidra.app.util.SymbolPath;
import ghidra.program.model.data.*;
/**
@ -40,6 +41,11 @@ public class ClassUtils {
*/
public static final PointerDataType VXPTR_TYPE = new PointerDataType();
/**
* The standard prefix used for the special symbol. Private for now.
*/
private static final String VTABLE_PREFIX = "VTABLE_";
/**
* private constructor -- no instances
*/
@ -54,8 +60,27 @@ public class ClassUtils {
*/
public static CategoryPath getClassInternalsPath(Composite composite) {
DataTypePath dtp = composite.getDataTypePath();
return new CategoryPath(new CategoryPath(dtp.getCategoryPath(), dtp.getDataTypeName()),
"!internal");
return getClassInternalsPath(dtp.getCategoryPath(), dtp.getDataTypeName());
}
/**
* Returns the category for class internals for the ClassID
* @param id the class ID
* @return the category path
*/
public static CategoryPath getClassInternalsPath(ClassID id) {
CategoryPath cp = recurseGetCategoryPath(id.getCategoryPath(), id.getSymbolPath());
return cp.extend("!internal");
}
/**
* Returns the category for class internals
* @param path the category path of the class composite
* @param className the name of the class
* @return the category path
*/
public static CategoryPath getClassInternalsPath(CategoryPath path, String className) {
return new CategoryPath(new CategoryPath(path, className), "!internal");
}
/**
@ -92,4 +117,46 @@ public class ClassUtils {
return composite;
}
/**
* Provides the standard special name for a virtual table (e.g., vbtable, vftable) that is
* keyed off of by the Decompiler during flattening and replacing of types within a class
* structure. More details to come
* @param ptrOffsetInClass the offset of the special field within the class
* @return the special name
*/
public static String getSpecialVxTableName(long ptrOffsetInClass) {
return String.format("%s%08x", VTABLE_PREFIX, ptrOffsetInClass);
}
public static DataType getVftDefaultEntry(DataTypeManager dtm) {
return new PointerDataType(dtm);
}
public static DataType getVbtDefaultEntry(DataTypeManager dtm) {
return new IntegerDataType(dtm);
}
public static int getVftEntrySize(DataTypeManager dtm) {
return dtm.getDataOrganization().getPointerSize();
}
public static int getVbtEntrySize(DataTypeManager dtm) {
return dtm.getDataOrganization().getIntegerSize();
}
/**
* Method to get a category path from a base category path and symbol path
* @param category the {@ink CategoryPath} on which to build
* @param symbolPath the current {@link SymbolPath} from which the current name is pulled.
* @return the new {@link CategoryPath} for the recursion level
*/
private static CategoryPath recurseGetCategoryPath(CategoryPath category,
SymbolPath symbolPath) {
SymbolPath parent = symbolPath.getParent();
if (parent != null) {
category = recurseGetCategoryPath(category, parent);
}
return new CategoryPath(category, symbolPath.getName());
}
}