GP-2518 - PDB: vtshape structures; reduce analysis messages

This commit is contained in:
ghizard
2023-06-28 17:11:06 -04:00
parent 86091b7cfe
commit 344e1bb2d3
5 changed files with 89 additions and 50 deletions
@@ -35,26 +35,24 @@ public class FieldListTypeApplier extends MsTypeApplier {
private List<MsTypeApplier> methodList = new ArrayList<>();
private boolean isEmpty;
// return can be null
static FieldListTypeApplier getFieldListApplierSpecial(DefaultPdbApplicator applicator,
RecordNumber recordNumber) throws PdbException {
MsTypeApplier applier =
applicator.getApplierOrNoTypeSpec(recordNumber, FieldListTypeApplier.class);
FieldListTypeApplier fieldListApplier = null;
if (applier instanceof FieldListTypeApplier) {
return (FieldListTypeApplier) applicator.getApplierOrNoTypeSpec(recordNumber,
FieldListTypeApplier.class);
if (applier instanceof FieldListTypeApplier fieldListApplier) {
return fieldListApplier;
}
try {
if (recordNumber.getCategory() == RecordCategory.TYPE) {
fieldListApplier = new FieldListTypeApplier(applicator,
// Only the NoType spec should fall through to here
if (recordNumber.getCategory() == RecordCategory.TYPE) {
try {
return new FieldListTypeApplier(applicator,
applicator.getPdb().getTypeRecord(recordNumber), true);
}
catch (IllegalArgumentException e) {
applicator.appendLogMsg(e.getMessage());
}
}
catch (IllegalArgumentException e) {
applicator.appendLogMsg(e.getMessage());
}
return fieldListApplier;
throw new PdbException("Problem creating field list");
}
/**
@@ -105,7 +103,9 @@ public class FieldListTypeApplier extends MsTypeApplier {
@Override
void apply() throws PdbException, CancelledException {
dataType = applyFieldListMsType((AbstractFieldListMsType) msType);
if (!isEmpty()) {
dataType = applyFieldListMsType((AbstractFieldListMsType) msType);
}
}
List<MsTypeApplier> getBaseClassList() {
@@ -89,16 +89,7 @@ public class PointerTypeApplier extends MsTypeApplier {
private DataType getUnderlyingType(AbstractPointerMsType type) {
MsTypeApplier underlyingApplier =
applicator.getTypeApplier(type.getUnderlyingRecordNumber());
DataType underlyingType = underlyingApplier.getCycleBreakType();
if (underlyingType == null) {
// TODO: we have seen underlyingTypeApplier is for NoTypeApplier for VtShapeMsType
// Figure it out, and perhaps create an applier that creates a structure or something?
underlyingType = applicator.getPdbPrimitiveTypeApplicator().getVoidType();
applicator.appendLogMsg(
"PDB Warning: No type conversion for " + underlyingApplier.getMsType().toString() +
" as underlying type for pointer. Using void.");
}
return underlyingType;
}
@@ -112,9 +112,9 @@ public class TypeApplierFactory {
applier =
new MemberFunctionTypeApplier(applicator, (MemberFunction16MsType) type);
break;
// case VtShapeMsType.PDB_ID:
// applier = new VtShapeTypeApplier(applicator, (VtShapeMsType) type);
// break;
case VtShapeMsType.PDB_ID:
applier = new VtShapeTypeApplier(applicator, (VtShapeMsType) type);
break;
// case Cobol016MsType.PDB_ID:
// // Not evaluated/implemented yet.
// break;
@@ -381,7 +381,7 @@ public class TypeApplierFactory {
// // Not evaluated/implemented yet.
// break;
// 0x1500 block
// 0x1500 block
// case TypeServerMsType.PDB_ID:
// // Not evaluated/implemented yet.
// break;
@@ -472,7 +472,7 @@ public class TypeApplierFactory {
// // Not evaluated/implemented yet.
// break;
// 0x1600 block
// 0x1600 block
// case FunctionIdMsType.PDB_ID:
// // Not evaluated/implemented yet.
// break;
@@ -21,6 +21,7 @@ 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.*;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.VoidDataType;
import ghidra.util.exception.CancelledException;
/**
@@ -68,20 +69,24 @@ public class VirtualFunctionTablePointerTypeApplier extends MsTypeApplier {
@Override
void apply() throws PdbException, CancelledException {
if (msType instanceof AbstractVirtualFunctionTablePointerMsType) {
if (msType instanceof AbstractVirtualFunctionTablePointerWithOffsetMsType vftPtrWOffset) {
dataType = applyPointer(
((AbstractVirtualFunctionTablePointerMsType) msType).getPointerTypeRecordNumber());
vftPtrWOffset.getPointerTypeRecordNumber());
}
else if (msType instanceof AbstractVirtualFunctionTablePointerMsType vftPtr) {
dataType = applyPointer(vftPtr.getPointerTypeRecordNumber());
}
else {
dataType = applyPointer(
((AbstractVirtualFunctionTablePointerWithOffsetMsType) msType).getPointerTypeRecordNumber());
dataType = VoidDataType.dataType;
applicator.appendLogMsg(
"PDB Warning: Type not handled: " + msType.getClass().getSimpleName());
}
}
private DataType applyPointer(RecordNumber pointerTypeRecordNumber) {
MsTypeApplier rawApplier = applicator.getTypeApplier(pointerTypeRecordNumber);
if (rawApplier instanceof PointerTypeApplier) {
return rawApplier.getDataType();
if (rawApplier instanceof PointerTypeApplier pointerApplier) {
return pointerApplier.getDataType();
}
applicator.appendLogMsg("cannot process " + rawApplier.getClass().getSimpleName() + "for " +
getClass().getSimpleName());
@@ -57,40 +57,83 @@ public class VtShapeTypeApplier extends MsTypeApplier {
@Override
void apply() throws PdbException, CancelledException {
// Note that focused investigation as shown that both the VTShape as well as the pointer
// to the particular VTShapes are not specific to one class; they can be shared by
// totally unrelated classes; moreover, no duplicates of any VTShape or pointer to a
// particular VTShape were found either. Because of this, for now, the VTShape is going
// into an anonymous types category.
dataType = createVtShape((VtShapeMsType) msType);
}
// TODO: We are creating a structure for the vtshape. Is there anything different we would
// like to do instead?
private DataType createVtShape(VtShapeMsType msShape) throws CancelledException {
// We are creating a structure for the vtshape.
private DataType createVtShape(VtShapeMsType msShape)
throws CancelledException {
List<VtShapeDescriptorMsProperty> list = msShape.getDescriptorList();
// TODO: what are correct/appropriate CategoryPath and name
StructureDataType shape = new StructureDataType(applicator.getAnonymousTypesCategory(),
"vtshape" + index, 0, applicator.getDataTypeManager());
List<DefaultPdbUniversalMember> members = new ArrayList<>();
int offset = 0;
int defaultSize = applicator.getDataTypeManager().getDataOrganization().getPointerSize();
// Since each element has its own property, we have to assume there can be mixed
// properties in the table, thus each element must be set separately.
// However, note that the data types referenced by the symbols (e.g., GDATAx) at the
// vftable locations in memory seem to have these as an array of constant pointers to
// functions with no argument and void return; to me, this does not quite agree with what
// we have here where each element having its own pointer property. For now,
// using a structure here. Moreover, we might want to eventually fix-up the arrays put
// down with the GDATAx symbols with structures that contain pointers to func specs that
// match the real function signatures at each element.
for (VtShapeDescriptorMsProperty descriptor : list) {
DataType elementType;
switch (descriptor) {
case NEAR:
// near16:
// 16-bit offset
elementType = Undefined2DataType.dataType;
break;
case FAR:
// far16:
// 16-bit segment
// 16-bit offset
elementType = Undefined4DataType.dataType;
break;
case NEAR32:
// near32:
// 32-bit offset
elementType = Undefined4DataType.dataType;
break;
case FAR32:
// far32:
// 16-bit segment
// 32-bit offset
elementType = Undefined6DataType.dataType;
break;
// lump remaining together; we do not know about thin, outer, or meta
case UNUSED:
// Special message for unused, followed by fall through case
applicator.appendLogMsg("PDB Warning: UNUSED propery found in VTShape.");
case THIN:
case OUTER:
case META:
case NEAR32:
case FAR32:
Pointer pointer = new PointerDataType(applicator.getDataTypeManager());
DefaultPdbUniversalMember member =
new DefaultPdbUniversalMember(applicator, "", pointer, offset);
offset += pointer.getLength();
members.add(member);
break;
case UNUSED:
offset += applicator.getDataOrganization().getPointerSize();
break;
default:
// If any element type is not know, we will not return a full shape structure
// Instead, we return void type.
applicator.appendLogMsg(
"PDB Warning: No type conversion for " + msShape.toString() +
" as underlying type for pointer. Using void.");
return VoidDataType.dataType;
}
int size = elementType.getLength();
if (size == defaultSize) {
elementType = PointerDataType.dataType;
}
DefaultPdbUniversalMember member =
new DefaultPdbUniversalMember(applicator, "", elementType, offset);
offset += size;
members.add(member);
}
int size = applicator.getDataOrganization().getPointerSize() * msShape.getCount();
if (!DefaultCompositeMember.applyDataTypeMembers(shape, false, size, members,
// offset has the total size at this point
if (!DefaultCompositeMember.applyDataTypeMembers(shape, false, offset, members,
msg -> Msg.warn(this, msg), applicator.getCancelOnlyWrappingMonitor())) {
CompositeTypeApplier.clearComponents(shape);
}