public SymDumpParam(SYM_DUMP_PARAM nativeSdp) { Name = Marshal.PtrToStringAnsi(nativeSdp.sName); Address = nativeSdp.addr; ModBase = nativeSdp.ModBase; TypeId = nativeSdp.TypeId; TypeSize = nativeSdp.TypeSize; PointerFlag = (PointerFlag)(nativeSdp.Flags & 0x0003); IsArray = 0 != (nativeSdp.Flags & 0x0004); IsStruct = 0 != (nativeSdp.Flags & 0x0008); IsConstant = 0 != (nativeSdp.Flags & 0x0010); } // end constructor
} // end constructor public IList <FieldInfo> GetSymbolFields(uint typeId, ulong modBase) { SYM_DUMP_PARAM sdp = new SYM_DUMP_PARAM(); sdp.size = (uint)Marshal.SizeOf(sdp); sdp.Options = DbgDump.NO_PRINT | DbgDump.CALL_FOR_EACH; sdp.ModBase = modBase; // presumably this makes it so we don't have to search all modules? (it's doc'ed as an 'out' param) List <FieldInfo> fields = new List <FieldInfo>(); GCHandle gchFields = GCHandle.Alloc(fields); SYM_DUMP_FIELD_CALLBACK callback = new SYM_DUMP_FIELD_CALLBACK(_My_SYM_DUMP_FIELD_CALLBACK); sdp.Context = GCHandle.ToIntPtr(gchFields); sdp.CallbackRoutine = Marshal.GetFunctionPointerForDelegate(callback); sdp.TypeId = typeId; try { int err = Ioctl(IoctlCode.DumpSymbolInfo, sdp); if (0 != err) { // TODO: proper error throw new Exception(String.Format("Ioctl for DumpSymbolInfo returned: {0}", err)); } DebugModuleAndId dmai = new DebugModuleAndId(modBase, typeId); foreach (var field in fields) { field.OwningType = dmai; } return(fields.AsReadOnly()); } finally { gchFields.Free(); GC.KeepAlive(callback); } } // end GetSymbolFields