|
3 | 3 | // Used by `PatchCoreLib.targets`. |
4 | 4 |
|
5 | 5 | using System.Reflection.Metadata; |
6 | | -using System.Reflection.Metadata.Ecma335; |
7 | 6 | using System.Reflection.PortableExecutable; |
8 | 7 |
|
9 | 8 | if (args.Length != 2) |
|
34 | 33 |
|
35 | 34 | var reader = peReader.GetMetadataReader(); |
36 | 35 |
|
37 | | - var volatileType = FindTypeDefinition(reader, "System.Threading", "Volatile"); |
38 | | - var interlockedType = FindTypeDefinition(reader, "System.Threading", "Interlocked"); |
39 | | - var threadType = FindTypeDefinition(reader, "System.Threading", "Thread"); |
| 36 | + var runtimeFeatureType = FindTypeDefinition(reader, "System.Runtime.CompilerServices", "RuntimeFeature"); |
40 | 37 |
|
41 | | - var readBarrier = FindMethodDefinition(reader, volatileType, "ReadBarrier", 0); |
42 | | - var writeBarrier = FindMethodDefinition(reader, volatileType, "WriteBarrier", 0); |
43 | | - var memoryBarrier = FindMethodDefinition(reader, interlockedType, "MemoryBarrier", 0); |
44 | | - |
45 | | - var throwIfSingleThreaded = FindMethodDefinition(reader, threadType, "ThrowIfSingleThreaded", 0); |
46 | | - |
47 | | - // Workaround for https://github.com/jjonescz/DotNetLab/issues/129. |
48 | | - PatchMethodBody(bytes, peReader, readBarrier, memoryBarrier, "Volatile.ReadBarrier"); |
49 | | - PatchMethodBody(bytes, peReader, writeBarrier, memoryBarrier, "Volatile.WriteBarrier"); |
| 38 | + var throwIfMultithreadingIsNotSupported = FindMethodDefinition(reader, runtimeFeatureType, "ThrowIfMultithreadingIsNotSupported", 0); |
50 | 39 |
|
51 | 40 | // Workaround for https://github.com/dotnet/roslyn/issues/82361. |
52 | | - PatchMethodBodyToRet(bytes, peReader, throwIfSingleThreaded, "System.Threading.Thread.ThrowIfSingleThreaded"); |
| 41 | + PatchMethodBodyToRet(bytes, peReader, throwIfMultithreadingIsNotSupported, "System.Runtime.CompilerServices.RuntimeFeature.ThrowIfMultithreadingIsNotSupported"); |
53 | 42 | } |
54 | 43 |
|
55 | 44 | Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? "."); |
@@ -109,63 +98,6 @@ static MethodDefinitionHandle FindMethodDefinition( |
109 | 98 | throw new InvalidOperationException($"Method not found: {name} with {parameterCount} parameters"); |
110 | 99 | } |
111 | 100 |
|
112 | | -static void PatchMethodBody( |
113 | | - byte[] peBytes, |
114 | | - PEReader peReader, |
115 | | - MethodDefinitionHandle targetMethod, |
116 | | - MethodDefinitionHandle memoryBarrier, |
117 | | - string displayName) |
118 | | -{ |
119 | | - var reader = peReader.GetMetadataReader(); |
120 | | - var methodDef = reader.GetMethodDefinition(targetMethod); |
121 | | - |
122 | | - if (methodDef.RelativeVirtualAddress == 0) |
123 | | - { |
124 | | - throw new InvalidOperationException($"Method has no body: {displayName}"); |
125 | | - } |
126 | | - |
127 | | - var bodyOffset = GetOffset(peReader, methodDef.RelativeVirtualAddress); |
128 | | - |
129 | | - // Determine method header format to locate IL bytes without changing header size. |
130 | | - var headerByte = peBytes[bodyOffset]; |
131 | | - int headerSize; |
132 | | - int codeSize; |
133 | | - |
134 | | - if ((headerByte & 0x3) == 0x2) |
135 | | - { |
136 | | - headerSize = 1; |
137 | | - codeSize = headerByte >> 2; |
138 | | - } |
139 | | - else if ((headerByte & 0x3) == 0x3) |
140 | | - { |
141 | | - var flags = BitConverter.ToUInt16(peBytes, bodyOffset); |
142 | | - headerSize = ((flags >> 12) & 0xF) * 4; |
143 | | - codeSize = BitConverter.ToInt32(peBytes, bodyOffset + 4); |
144 | | - } |
145 | | - else |
146 | | - { |
147 | | - throw new InvalidOperationException($"Unknown method header format: {displayName}"); |
148 | | - } |
149 | | - |
150 | | - if (codeSize < 6) |
151 | | - { |
152 | | - throw new InvalidOperationException($"Method body too small to patch: {displayName}"); |
153 | | - } |
154 | | - |
155 | | - var ilStart = bodyOffset + headerSize; |
156 | | - var callToken = MetadataTokens.GetToken(memoryBarrier); |
157 | | - |
158 | | - peBytes[ilStart + 0] = 0x28; // call |
159 | | - var tokenBytes = BitConverter.GetBytes(callToken); |
160 | | - Buffer.BlockCopy(tokenBytes, 0, peBytes, ilStart + 1, 4); |
161 | | - peBytes[ilStart + 5] = 0x2A; // ret |
162 | | - |
163 | | - for (var i = 6; i < codeSize; i++) |
164 | | - { |
165 | | - peBytes[ilStart + i] = 0x00; // nop padding |
166 | | - } |
167 | | -} |
168 | | - |
169 | 101 | static void PatchMethodBodyToRet( |
170 | 102 | byte[] peBytes, |
171 | 103 | PEReader peReader, |
|
0 commit comments