Files
UnrealEngine/Engine/Extras/ThirdPartyNotUE/crunchersharp/PDBReader.cs
2025-05-18 13:04:45 +08:00

169 lines
3.4 KiB
C#

using System;
using System.Runtime.InteropServices;
namespace PDBReader
{
unsafe struct PDBHandle { };
enum TypeRecordKind : ushort
{
Modifier = 0x1001,
Pointer = 0x1002,
Array = 0x001503,
Structure = 0x001505,
Class = 0x001504,
Union = 0x001506,
Enum = 0x001507,
Member = 0x00150D,
}
[Flags]
enum ClassFlags : ushort
{
Packed = 0x1,
Ctor = 0x2,
Ovlops = 0x4,
IsNested = 0x8,
CNested = 0x10,
OpAssign = 0x20,
OpCast = 0x40,
FwdRef = 0x80,
Scoped = 0x100,
HasUniqueName = 0x200,
Sealed = 0x400,
//HFA = 0x1,
Intrinsic = 0x1000,
//mocom= 0x1,
}
[Flags]
enum ModifierFlags : ushort
{
None = 0x0,
Const = 0x1,
Volatile = 0x2,
Unaligned = 0x4,
}
[StructLayout(LayoutKind.Sequential)]
struct TPIRecord_Class
{
public ushort Count;
public ClassFlags Flags;
public uint FieldIndex;
public uint DerivedIndex;
public uint VshapeIndex;
}
[StructLayout(LayoutKind.Sequential)]
struct TPIRecord_Union
{
public ushort Count;
public ClassFlags Flags;
public uint FieldIndex;
}
[StructLayout(LayoutKind.Explicit)]
struct TPIRecord
{
[FieldOffset(0)]
public ushort Size;
[FieldOffset(2)]
public TypeRecordKind Kind;
[FieldOffset(4)]
public TPIRecord_Class Class;
[FieldOffset(4)]
public TPIRecord_Union Union;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct RecordBasicInfo
{
public IntPtr Name;
public ulong Size;
// Kind == LF_CLASS || Kind == LF_STRUCTURE
// -> field list
// Kind == LF_POINTER
// -> pointed-to type
// Kind == LF_ARRAY
// -> element type
// Kind == LF_MODIFIER
// -> type being modified
public uint RelatedTypeIndex;
public ModifierFlags Modifiers;
public TypeRecordKind Kind;
}
[StructLayout(LayoutKind.Sequential)]
struct StructFieldCounts
{
public uint NumDataMembers;
}
[Flags]
enum DataMemberFlags
{
None = 0x0,
IsVtable = 0x1,
IsBitfield = 0x2,
IsBaseClass = 0x4,
}
[StructLayout(LayoutKind.Sequential)]
struct DataMemberInfo
{
public IntPtr Name;
public ulong Offset;
public uint TypeIndex;
public DataMemberFlags Flags;
public uint BitPosition;
public uint BitSize;
public bool IsVtable { get { return (Flags & DataMemberFlags.IsVtable) != DataMemberFlags.None; } }
public bool IsBitfield { get { return (Flags & DataMemberFlags.IsBitfield) != DataMemberFlags.None; } }
public bool IsBaseClass { get { return (Flags & DataMemberFlags.IsBaseClass) != DataMemberFlags.None; } }
}
internal unsafe class PDBReader
{
const string LibraryName = nameof(PDBReader) + ".dll";
[DllImport(LibraryName)]
internal static extern PDBHandle* LoadPDB([MarshalAs(UnmanagedType.LPWStr)] string path);
[DllImport(LibraryName)]
internal static extern void ClosePDB(PDBHandle* handle);
[DllImport(LibraryName)]
internal static extern void GetTypeRecordsInfo(
PDBHandle* handle,
out TPIRecord** Records,
out ulong RecordCount,
out uint TypeIndexBegin,
out uint TypeIndexEnd
);
[DllImport(LibraryName)]
internal static extern void GetBasicTypeInfo(
PDBHandle* handle,
uint typeIndex,
out RecordBasicInfo info
);
[DllImport(LibraryName)]
internal static extern void CountNumFields(
PDBHandle* handle,
TPIRecord* fieldListRecord,
out StructFieldCounts counts
);
[DllImport(LibraryName)]
internal static extern void ReadDataMembers(
PDBHandle* handle,
TPIRecord* fieldListRecord,
[In, Out, MarshalAs(UnmanagedType.LPArray)] DataMemberInfo[] members
);
}
}