blob: 63c2a7fe4cbab8226c16eec5e4cc1f565f837c52 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Buffers.Binary;
using System.Diagnostics;
namespace Internal.IL
{
public class ILTokenReplacer
{
public static void Replace(byte[] ilStream, Func<int, int> tokenReplaceFunc)
{
ILReader ilReader = new ILReader(ilStream);
while (ilReader.HasNext)
{
int offsetBefore = ilReader.Offset;
ILOpcode opcode = ilReader.ReadILOpcode();
ilReader.Skip(opcode);
int offsetAfter = ilReader.Offset;
if (ILOpcodeHasToken(opcode))
{
Debug.Assert((offsetAfter - offsetBefore) == 5 || (offsetAfter - offsetBefore) == 6);
var tokenSpan = ilStream.AsSpan(checked(offsetAfter - 4), 4);
// Replace token in IL stream with a new token provided by the tokenReplaceFunc
//
// This is used by the StandaloneMethodMetadata logic to create method local tokens
// and by the IL provider used for cross module inlining to create tokens which are
// stable and contained within the R2R module instead of being in a module separated
// by a version boundary.
int token = BinaryPrimitives.ReadInt32LittleEndian(tokenSpan);
var alternateToken = tokenReplaceFunc(token);
BinaryPrimitives.WriteInt32LittleEndian(tokenSpan, alternateToken);
}
}
}
private static bool ILOpcodeHasToken(ILOpcode opcode)
{
switch (opcode)
{
case ILOpcode.jmp:
case ILOpcode.call:
case ILOpcode.calli:
case ILOpcode.callvirt:
case ILOpcode.cpobj:
case ILOpcode.ldobj:
case ILOpcode.ldstr:
case ILOpcode.newobj:
case ILOpcode.castclass:
case ILOpcode.isinst:
case ILOpcode.unbox:
case ILOpcode.ldfld:
case ILOpcode.ldflda:
case ILOpcode.stfld:
case ILOpcode.ldsfld:
case ILOpcode.ldsflda:
case ILOpcode.stsfld:
case ILOpcode.stobj:
case ILOpcode.box:
case ILOpcode.newarr:
case ILOpcode.ldelema:
case ILOpcode.ldelem:
case ILOpcode.stelem:
case ILOpcode.unbox_any:
case ILOpcode.refanyval:
case ILOpcode.mkrefany:
case ILOpcode.ldtoken:
case ILOpcode.ldftn:
case ILOpcode.ldvirtftn:
case ILOpcode.initobj:
case ILOpcode.constrained:
case ILOpcode.sizeof_:
return true;
}
return false;
}
}
}
|