|
4 | 4 | using System;
|
5 | 5 | using System.Runtime.InteropServices;
|
6 | 6 | using System.Runtime.InteropServices.Marshalling;
|
| 7 | +using Microsoft.Diagnostics.DataContractReader.Legacy; |
7 | 8 |
|
8 | 9 | namespace Microsoft.Diagnostics.DataContractReader;
|
9 | 10 |
|
@@ -83,4 +84,80 @@ private static unsafe int CreateSosInterface(IntPtr handle, IntPtr legacyImplPtr
|
83 | 84 | *obj = ptr;
|
84 | 85 | return 0;
|
85 | 86 | }
|
| 87 | + |
| 88 | + [UnmanagedCallersOnly(EntryPoint = "CLRDataCreateInstance")] |
| 89 | + private static unsafe int CLRDataCreateInstance(Guid* pIID, IntPtr /*ICLRDataTarget*/ pLegacyTarget, void** iface) |
| 90 | + { |
| 91 | + if (pLegacyTarget == IntPtr.Zero || iface == null) |
| 92 | + return HResults.E_INVALIDARG; |
| 93 | + |
| 94 | + *iface = null; |
| 95 | + |
| 96 | + ComWrappers cw = new StrategyBasedComWrappers(); |
| 97 | + object obj = cw.GetOrCreateObjectForComInstance(pLegacyTarget, CreateObjectFlags.None); |
| 98 | + ICLRDataTarget dataTarget = obj as ICLRDataTarget ?? throw new ArgumentException($"pLegacyTarget does not implement ${nameof(ICLRDataTarget)}", nameof(pLegacyTarget)); |
| 99 | + ICLRContractLocator contractLocator = obj as ICLRContractLocator ?? throw new ArgumentException($"pLegacyTarget does not implement ${nameof(ICLRContractLocator)}", nameof(pLegacyTarget)); |
| 100 | + |
| 101 | + ulong contractAddress; |
| 102 | + if (contractLocator.GetContractDescriptor(&contractAddress) != 0) |
| 103 | + { |
| 104 | + throw new InvalidOperationException("Unable to retrieve contract address from ICLRContractLocator"); |
| 105 | + } |
| 106 | + |
| 107 | + if (!ContractDescriptorTarget.TryCreate( |
| 108 | + contractAddress, |
| 109 | + (address, buffer) => |
| 110 | + { |
| 111 | + fixed (byte* bufferPtr = buffer) |
| 112 | + { |
| 113 | + uint bytesRead; |
| 114 | + return dataTarget.ReadVirtual(address, bufferPtr, (uint)buffer.Length, &bytesRead); |
| 115 | + } |
| 116 | + }, |
| 117 | + (threadId, contextFlags, contextSize, bufferToFill) => |
| 118 | + { |
| 119 | + fixed (byte* bufferPtr = bufferToFill) |
| 120 | + { |
| 121 | + return dataTarget.GetThreadContext(threadId, contextFlags, contextSize, bufferPtr); |
| 122 | + } |
| 123 | + }, |
| 124 | + (out platform) => |
| 125 | + { |
| 126 | + platform = 0; |
| 127 | + uint machineType; |
| 128 | + int hr = dataTarget.GetMachineType(&machineType); |
| 129 | + switch (machineType) |
| 130 | + { |
| 131 | + // ICLRDataTarget can not be used to find OS. For now labeling all platforms as Windows |
| 132 | + // |
| 133 | + case 0x014c: // IMAGE_FILE_MACHINE_I386 |
| 134 | + platform = (int)Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_X86; |
| 135 | + break; |
| 136 | + case 0x8664: // IMAGE_FILE_MACHINE_AMD64 |
| 137 | + platform = (int)Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_AMD64; |
| 138 | + break; |
| 139 | + case 0x01c4: // IMAGE_FILE_MACHINE_ARMNT |
| 140 | + platform = (int)Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_ARM; |
| 141 | + break; |
| 142 | + case 0xAA64: // IMAGE_FILE_MACHINE_ARM64 |
| 143 | + platform = (int)Target.CorDebugPlatform.CORDB_PLATFORM_WINDOWS_ARM64; |
| 144 | + break; |
| 145 | + } |
| 146 | + return hr; |
| 147 | + }, |
| 148 | + out ContractDescriptorTarget? target)) |
| 149 | + { |
| 150 | + return -1; |
| 151 | + } |
| 152 | + |
| 153 | + Legacy.SOSDacImpl impl = new(target, null); |
| 154 | + nint ccw = cw.GetOrCreateComInterfaceForObject(impl, CreateComInterfaceFlags.None); |
| 155 | + Marshal.QueryInterface(ccw, *pIID, out nint ptrToIface); |
| 156 | + *iface = (void*)ptrToIface; |
| 157 | + |
| 158 | + // Decrement reference count on ccw because QI increments it |
| 159 | + Marshal.Release(ccw); |
| 160 | + |
| 161 | + return 0; |
| 162 | + } |
86 | 163 | }
|
0 commit comments