Merge remote-tracking branch

'origin/GP-3171_ghizard_PDB_stub_basic_Member_Pointers' (Closes #5055)
This commit is contained in:
Ryan Kurtz 2023-03-21 12:25:08 -04:00
commit eebe8ae825
7 changed files with 2371 additions and 2053 deletions

View file

@ -280,6 +280,46 @@ public abstract class AbstractPointerMsType extends AbstractMsType {
return memberPointerType;
}
/**
* Returns true of flat 0:32 address model
* @return true if flat
*/
public boolean isFlat() {
return isFlat;
}
/**
* Returns true if volatile pointer
* @return true if volatile
*/
public boolean isVolatile() {
return isVolatile;
}
/**
* Returns true if const pointer
* @return true if const
*/
public boolean isConst() {
return isConst;
}
/**
* Returns true if pointer not aligned on normal boundary
* @return true if not aligned
*/
public boolean isUnaligned() {
return isUnaligned;
}
/**
* Returns the record number of the class containing the member pointer
* @return The record number
*/
public RecordNumber getMemberPointerContainingClassRecordNumber() {
return memberPointerContainingClassRecordNumber;
}
@Override
public void emit(StringBuilder builder, Bind bind) {
StringBuilder myBuilder = new StringBuilder();

View file

@ -0,0 +1,86 @@
/* ###
* 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.pdb.pdbapplicator;
import org.apache.commons.lang3.StringUtils;
import ghidra.program.model.data.*;
/**
* Utilities in various places regarding ClassTypes
*/
public class ClassTypeUtils {
private static final String INTERNALS = "!internals";
private ClassTypeUtils() {
}
/**
* Returns an "internals" CategoryPath within the datatype managed by the applier
* @param applier for the owning composite datatype of the internals path
* @return the CategoryPath
*/
public static CategoryPath getInternalsCategoryPath(CompositeTypeApplier applier) {
DataType dt = applier.getDataType();
if (dt instanceof Composite composite) {
return getInternalsCategoryPath(composite);
}
return null;
}
// TODO: Eventually consider changing Composite argument below as model is refined.
/**
* Returns an "internals" CategoryPath for the owning composite datatype
* @param composite owning datatype of the internals path
* @return the CategoryPath
*/
public static CategoryPath getInternalsCategoryPath(Composite composite) {
DataTypePath dtp = composite.getDataTypePath();
return dtp.getCategoryPath().extend(dtp.getDataTypeName(), INTERNALS);
}
/**
* Returns a DataTypePath for the named type within the "internals" category of the type
* managed byte the applier
* @param applier the applier
* @param name the name of the type for the DataTypePath
* @return the DataTypePath
*/
public static DataTypePath getInternalsDataTypePath(CompositeTypeApplier applier, String name) {
CategoryPath cp = getInternalsCategoryPath(applier);
if (cp == null || StringUtils.isAllBlank(name)) {
return null;
}
return new DataTypePath(cp, name);
}
// TODO: Eventually consider changing Composite argument below as model is refined.
/**
* Returns a DataTypePath for the named type within the "internals" category of the composite
* type
* @param composite the composite
* @param name the name of the type for the DataTypePath
* @return the DataTypePath
*/
public static DataTypePath getInternalsDataTypePath(Composite composite, String name) {
CategoryPath cp = getInternalsCategoryPath(composite);
if (cp == null || StringUtils.isAllBlank(name)) {
return null;
}
return new DataTypePath(cp, name);
}
}

View file

@ -691,11 +691,15 @@ public class CompositeTypeApplier extends AbstractComplexTypeApplier {
}
}
else {
DefaultPdbUniversalMember member =
new DefaultPdbUniversalMember(applicator, memberName, fieldApplier, offset);
String memberComment = null;
if (fieldApplier instanceof PointerTypeApplier ptrApplier) {
memberComment = ptrApplier.getPointerCommentField();
}
DefaultPdbUniversalMember member = new DefaultPdbUniversalMember(applicator,
memberName, fieldApplier, offset, memberComment);
members.add(member);
classType.addMember(memberName, fieldDataType, isFlexibleArray,
convertAttributes(memberAttributes), offset);
convertAttributes(memberAttributes), offset, memberComment);
}
}
else if (memberTypeApplierIterated instanceof EnumerateTypeApplier) {

View file

@ -1267,7 +1267,7 @@ public class CppCompositeType {
void addPdbMember(List<ClassPdbMember> pdbMembers, Member member) {
ClassPdbMember classPdbMember = new ClassPdbMember(member.getName(), member.getDataType(),
member.isFlexibleArray(), member.getOffset(), null);
member.isFlexibleArray(), member.getOffset(), member.getComment());
pdbMembers.add(classPdbMember);
}

View file

@ -41,7 +41,23 @@ public class DefaultPdbUniversalMember extends PdbMember {
*/
DefaultPdbUniversalMember(DefaultPdbApplicator applicator, String name, MsTypeApplier applier,
int offset) {
super(name, (applier.getDataType()).getName(), offset, null);
this(applicator, name, applier, offset, null);
dataType = null;
}
/**
* Default PDB member construction
* @param applicator {@link DefaultPdbApplicator} for which we are working.
* @param name member field name. For bitfields this also conveys the bit-size
* and optionally the bit-offset.
* @param applier fieldApplier for the field datatype or base datatype associated with the
* bitfield.
* @param offset member's byte offset within the root composite.
* @param memberComment comment for member field
*/
DefaultPdbUniversalMember(DefaultPdbApplicator applicator, String name, MsTypeApplier applier,
int offset, String memberComment) {
super(name, applier.getDataType().getName(), offset, memberComment);
this.applier = applier;
dataType = null;
}

View file

@ -28,7 +28,7 @@ import ghidra.util.exception.CancelledException;
*/
public class PointerTypeApplier extends MsTypeApplier {
private boolean isFunctionPointer = false;
private String memberComment = null;
/**
* Constructor for pointer type applier, for transforming a enum into a
@ -42,8 +42,14 @@ public class PointerTypeApplier extends MsTypeApplier {
super(applicator, msType);
}
boolean isFunctionPointer() {
return isFunctionPointer;
/**
* Comment field if this type is used as a structure member. This method could go away later
* if we develop member pointers into the Ghidra framework; this method exists to pass some
* pertinent information along to the user
* @return comment string or null
*/
String getPointerCommentField() {
return memberComment;
}
@Override
@ -80,15 +86,10 @@ public class PointerTypeApplier extends MsTypeApplier {
return thisUnderlyingTypeApplier;
}
private DataType applyAbstractPointerMsType(AbstractPointerMsType type) {
private DataType getUnderlyingType(AbstractPointerMsType type) {
MsTypeApplier underlyingApplier =
applicator.getTypeApplier(type.getUnderlyingRecordNumber());
if (underlyingApplier instanceof ProcedureTypeApplier) {
isFunctionPointer = true;
}
//DataType underlyingType = underlyingApplier.getCycleBreakType(); // out 20191211
DataType underlyingType = underlyingApplier.getCycleBreakType();
if (underlyingType == null) {
// TODO: we have seen underlyingTypeApplier is for NoTypeApplier for VtShapeMsType
@ -98,14 +99,186 @@ public class PointerTypeApplier extends MsTypeApplier {
"PDB Warning: No type conversion for " + underlyingApplier.getMsType().toString() +
" as underlying type for pointer. Using void.");
}
return underlyingType;
}
private DataType applyAbstractPointerMsType(AbstractPointerMsType type) {
AbstractPointerMsType.PointerMode pointerMode = type.getPointerMode();
if (pointerMode == AbstractPointerMsType.PointerMode.MEMBER_DATA_POINTER ||
pointerMode == AbstractPointerMsType.PointerMode.MEMBER_FUNCTION_POINTER) {
return processMemberPointer(type);
}
return processPointer(type);
}
private DataType processMemberPointer(AbstractPointerMsType type) {
DataType underlyingType = getUnderlyingType(type);
int size = type.getSize().intValueExact();
RecordNumber memberPointerContainingClassRecordNumber =
type.getMemberPointerContainingClassRecordNumber();
MsTypeApplier containingClassApplier =
applicator.getTypeApplier(memberPointerContainingClassRecordNumber);
DataType dt = null;
String name;
AbstractPointerMsType.PointerMode pointerMode = type.getPointerMode();
if (pointerMode == AbstractPointerMsType.PointerMode.MEMBER_FUNCTION_POINTER) {
name = String.format("pmf_%08x", type.toString().hashCode());
memberComment = "\"::*\" (pmf) to type: " + underlyingType;
}
else {
name = String.format("pdm_%08x", type.toString().hashCode());
memberComment = "\"::*\" (pdm) to type: " + underlyingType;
}
if (containingClassApplier instanceof CompositeTypeApplier cta) {
DataTypePath dtp = ClassTypeUtils.getInternalsDataTypePath(cta, name);
if (dtp != null) {
dt = applicator.getDataTypeManager().getDataType(dtp);
if (dt == null) {
dt = new StructureDataType(dtp.getCategoryPath(), dtp.getDataTypeName(), size);
dt.setDescription(type.toString());
}
}
}
if (dt == null) {
dt = Undefined.getUndefinedDataType(size);
}
return dt;
}
private DataType processPointer(AbstractPointerMsType type) {
memberComment = null;
DataType underlyingType = getUnderlyingType(type);
int size = type.getSize().intValueExact();
if (size == applicator.getDataOrganization().getPointerSize()) {
size = -1; // Use default
}
Pointer pointer =
new PointerDataType(underlyingType, size, applicator.getDataTypeManager());
return pointer;
return new PointerDataType(underlyingType, size, applicator.getDataTypeManager());
}
// private DataType processMemberPointerFuture(AbstractPointerMsType type) {
// TODO: Incorporate some of processMemberPointer()
// AbstractPointerMsType.MemberPointerType memberPointerType = type.getMemberPointerType();
//
// int a = 1;
// Msg.info(this, String.format("size: %d mpt: %s", size, memberPointerType));
//
// switch (memberPointerType) {
// case INVALID:
// a = a + 1;
// break;
// case UNSPECIFIED:
// a = a + 1;
// break;
// case DATA_SINGLE_INHERITANCE:
// a = a + 1;
// break;
// case DATA_MULTIPLE_INHERITANCE:
// a = a + 1;
// break;
// case DATA_VIRTUAL_INHERITANCE:
// a = a + 1;
// break;
// case DATA_GENERAL:
// a = a + 1;
// break;
// case FUNCTION_SINGLE_INHERITANCE:
// a = a + 1;
// break;
// case FUNCTION_MULTIPLE_INHERITANCE:
// a = a + 1;
// // temporary code in place of more permanent code, but need something to help analyze
// // how this member of a class/structure is being used.
//// if (size == 16) {
//// return pmfDummy;
//// }
// break;
// case FUNCTION_VIRTUAL_INHERITANCE:
// a = a + 1;
// break;
// case FUNCTION_SINGLE_INHERITANCE_1632:
// a = a + 1;
// break;
// case FUNCTION_MULTIPLE_INHERITANCE_1632:
// a = a + 1;
// break;
// case FUNCTION_VIRTUAL_INHERITANCE_1632:
// a = a + 1;
// break;
// case FUNCTION_SINGLE_INHERITANCE_32:
// a = a + 1;
// break;
// case FUNCTION_MULTIPLE_INHERITANCE_32:
// a = a + 1;
// break;
// case FUNCTION_VIRTUAL_INHERITANCE_32:
// a = a + 1;
// break;
// default:
// a = a + 1;
// break;
// }
// return null;
// }
//
// private DataType processPointerFuture(AbstractPointerMsType type) {
// //
// AbstractPointerMsType.PointerType pointerType = type.getPointerType();
// //Msg.info(this, String.format("size: %d pt: %s", size, pointerType));
// int a = 1;
// switch (pointerType) {
// case INVALID:
// a = a + 1;
// break;
// case NEAR:
// a = a + 1;
// break;
// case FAR:
// a = a + 1;
// break;
// case HUGE:
// a = a + 1;
// break;
// case SEGMENT_BASED:
// a = a + 1;
// break;
// case VALUE_BASED:
// a = a + 1;
// break;
// case SEGMENT_VALUE_BASED:
// a = a + 1;
// break;
// case ADDRESS_BASED:
// a = a + 1;
// break;
// case SEGMENT_ADDRESS_BASED:
// a = a + 1;
// break;
// case TYPE_BASED:
// a = a + 1;
// break;
// case SELF_BASED:
// a = a + 1;
// break;
// case NEAR32:
// a = a + 1;
// break;
// case FAR32:
// a = a + 1;
// break;
// case PTR64:
// a = a + 1;
// break;
// case UNSPECIFIED:
// a = a + 1;
// break;
// default:
// a = a + 1;
// break;
// }
// return null;
// }
}