mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch
'origin/GP-3171_ghizard_PDB_stub_basic_Member_Pointers' (Closes #5055)
This commit is contained in:
commit
eebe8ae825
7 changed files with 2371 additions and 2053 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue