// /// <summary> /// Gets the type information /// </summary> /// <param name="moduleName">Name of the module that contains the type</param> /// <param name="typeName">Name of the type that contains the field</param> /// <param name="fieldName">Name of the field</param> /// <param name="structureAddress">Address of the structure</param> /// <param name="memberTypeName">The type name read from symbols</param> /// <returns>HRESULT</returns> public int ReadTypeName(string symbolName, ulong structureAddress, out string memberTypeName) { const int MAX_TYPE_SIZE = 512; // even most templated types shouldn't be 512 chars memberTypeName = ""; // Make a new Typed Data structure. _EXT_TYPED_DATA SymbolTypedData; // Get the ModuleBase ulong ModuleBase; // Get the TypeID for the parent structure uint TypeId; int hr = GetSymbolTypeIdWide(symbolName, out TypeId, out ModuleBase); if (FAILED(hr)) { OutputVerboseLine("[ReadTypeName] GetSymbolTypeIdWide Failed to get {1} hr={0:x}", hr, symbolName); return hr; } // Set up the first operation to get symbol data SymbolTypedData.Operation = _EXT_TDOP.EXT_TDOP_SET_FROM_TYPE_ID_AND_U64; SymbolTypedData.InData.ModBase = ModuleBase; SymbolTypedData.InData.Offset = structureAddress; SymbolTypedData.InData.TypeId = TypeId; //d.OutputVerboseLine("FieldTypeId:{0:x} ModuleBase:{1:x} Offset:{2:x}", FieldTypeId, ModuleBase, offset); if (FAILED(hr = DebugAdvanced.Request(DEBUG_REQUEST.EXT_TYPED_DATA_ANSI, &SymbolTypedData, sizeof(_EXT_TYPED_DATA), &SymbolTypedData, sizeof(_EXT_TYPED_DATA), null))) { OutputVerboseLine("[ReadTypeName] DebugAdvanced.Request 1 Failed to get {1} hr={0:x}", hr,symbolName); return hr; } IntPtr Buffer = IntPtr.Zero; try { _EXT_TYPED_DATA TemporaryTypedDataForBufferConstruction; // Allocate Buffers int TotalSize = sizeof(_EXT_TYPED_DATA) + MAX_TYPE_SIZE; Buffer = Marshal.AllocHGlobal((int)TotalSize); // Set up the parameters for the 2nd request call to get the type TemporaryTypedDataForBufferConstruction.Operation = _EXT_TDOP.EXT_TDOP_GET_TYPE_NAME; // Pass in the OutData from the first call to Request(), so it knows what symbol to use TemporaryTypedDataForBufferConstruction.InData = SymbolTypedData.OutData; // The index of the string will be immediatly following the _EXT_TYPED_DATA structure TemporaryTypedDataForBufferConstruction.StrBufferIndex = (uint)sizeof(_EXT_TYPED_DATA); TemporaryTypedDataForBufferConstruction.StrBufferChars = MAX_TYPE_SIZE; // I suck at moving buffers around in C#.. but this seems to work :) // Copy TemporaryTypedDataForBufferConstruction into the Buffer. // Source is our _EXT_TYPED_DATA stuction, Dest is our empty allocated buffer DebugUtilities.CopyMemory(Buffer, (IntPtr)(&TemporaryTypedDataForBufferConstruction), sizeof(_EXT_TYPED_DATA)); // Hack alert. // I had to make a new class called EXT_TYPED_DATA so i could call Marshal.PtrToStructure.. The struct wouldnt work.. so we have a struct and a class with the same(ish) fields. EXT_TYPED_DATA TypedDataInClassForm = new EXT_TYPED_DATA(); // Call Request(), Passing in the buffer we created as the In and Out Parameters if (FAILED(hr = DebugAdvanced.Request(DEBUG_REQUEST.EXT_TYPED_DATA_ANSI, (void*)Buffer, TotalSize, (void*)Buffer, TotalSize, null))) { OutputVerboseLine("[ReadTypeNameFromStructureMember]DebugAdvanced.Request 2 Failed to get {1} hr={0:x}", hr, symbolName); return hr; } // Convert the returned buffer to a _EXT_TYPED_Data CLASS (since it wont let me convert to a struct) Marshal.PtrToStructure(Buffer, TypedDataInClassForm); memberTypeName = Marshal.PtrToStringAnsi((IntPtr)(Buffer.ToInt64() + TypedDataInClassForm.StrBufferIndex)); } finally { Marshal.FreeHGlobal(Buffer); } return hr; }
// /// <summary> /// Gets the type information from a structure member /// </summary> /// <param name="moduleName">Name of the module that contains the type</param> /// <param name="typeName">Name of the type that contains the field</param> /// <param name="fieldName">Name of the field</param> /// <param name="structureAddress">Address of the structure</param> /// <param name="memberTypeName">The type name read from symbols</param> /// <returns>HRESULT</returns> public int ReadTypeNameFromStructureMember(string moduleName, string typeName, string fieldName, ulong structureAddress, out string memberTypeName) { moduleName = FixModuleName(moduleName); const int MAX_TYPE_SIZE = 512; // even most templated types shouldn't be 512 chars memberTypeName = ""; // Make a new Typed Data structure. _EXT_TYPED_DATA SymbolTypedData; // Get the ModuleBase ulong ModuleBase; GetModuleBase(moduleName, out ModuleBase); // Get the TypeID for the parent structure uint TypeId; GetTypeId(moduleName, typeName, out TypeId); // get the field offset and typeid for the member uint FieldTypeId; uint offset; int hr; try { hr = DebugSymbols.GetFieldTypeAndOffsetWide(ModuleBase, TypeId, fieldName, &FieldTypeId, &offset); if (FAILED(hr)) { OutputVerboseLine("GetFieldTypeAndOffset Failed: {0:x}", hr); return hr; } } catch { OutputErrorLine("[ReadTypeNameFromStructureMember] ERROR: IDebugSymbols.GetFieldTypeAndOffset threw an exception. Your Debugger is probably out of date and does not support the IDebugSymbols5 interface"); return S_FALSE; } // Set up the first operation to get symbol data SymbolTypedData.Operation = _EXT_TDOP.EXT_TDOP_SET_FROM_TYPE_ID_AND_U64; SymbolTypedData.InData.ModBase = ModuleBase; SymbolTypedData.InData.Offset = structureAddress; SymbolTypedData.InData.TypeId = FieldTypeId; //d.OutputVerboseLine("FieldTypeId:{0:x} ModuleBase:{1:x} Offset:{2:x}", FieldTypeId, ModuleBase, offset); if (FAILED(hr = DebugAdvanced.Request(DEBUG_REQUEST.EXT_TYPED_DATA_ANSI, &SymbolTypedData, sizeof(_EXT_TYPED_DATA), &SymbolTypedData, sizeof(_EXT_TYPED_DATA), null))) { OutputVerboseLine("[ReadTypeNameFromStructureMember] DebugAdvanced.Request 1 Failed to get {1}!{2}.{3} hr={0:x}", hr, moduleName, typeName, fieldName); return hr; } IntPtr Buffer = IntPtr.Zero; try { _EXT_TYPED_DATA TemporaryTypedDataForBufferConstruction; // Allocate Buffers int TotalSize = sizeof(_EXT_TYPED_DATA) + MAX_TYPE_SIZE; Buffer = Marshal.AllocHGlobal((int)TotalSize); // Set up the parameters for the 2nd request call to get the type TemporaryTypedDataForBufferConstruction.Operation = _EXT_TDOP.EXT_TDOP_GET_TYPE_NAME; // Pass in the OutData from the first call to Request(), so it knows what symbol to use TemporaryTypedDataForBufferConstruction.InData = SymbolTypedData.OutData; // The index of the string will be immediatly following the _EXT_TYPED_DATA structure TemporaryTypedDataForBufferConstruction.StrBufferIndex = (uint)sizeof(_EXT_TYPED_DATA); TemporaryTypedDataForBufferConstruction.StrBufferChars = MAX_TYPE_SIZE; // I suck at moving buffers around in C#.. but this seems to work :) // Copy TemporaryTypedDataForBufferConstruction into the Buffer. // Source is our _EXT_TYPED_DATA stucture, Dest is our empty allocated buffer DebugUtilities.CopyMemory(Buffer, (IntPtr)(&TemporaryTypedDataForBufferConstruction), sizeof(_EXT_TYPED_DATA)); // Call Request(), Passing in the buffer we created as the In and Out Parameters if (FAILED(hr = DebugAdvanced.Request(DEBUG_REQUEST.EXT_TYPED_DATA_ANSI, (void*)Buffer, TotalSize, (void*)Buffer, TotalSize, null))) { OutputVerboseLine("[ReadTypeNameFromStructureMember]DebugAdvanced.Request 2 Failed to get {1}!{2}.{3} hr={0:x}", hr, moduleName, typeName, fieldName); return hr; } EXT_TYPED_DATA TypedDataInClassForm = new EXT_TYPED_DATA(); // Convert the returned buffer to a _EXT_TYPED_Data _CLASS_ (since it wont let me convert to a struct) Marshal.PtrToStructure(Buffer, TypedDataInClassForm); memberTypeName = Marshal.PtrToStringAnsi((IntPtr)(Buffer.ToInt64() + TypedDataInClassForm.StrBufferIndex)); } finally { Marshal.FreeHGlobal(Buffer); } return hr; }