c# – Visual Studio编译器如何将安全属性编译为CIL?

我在类中的方法上有以下属性SecurityPermission(SecurityAction.Assert).我编译它(调试版本)并通过查看原始堆并查看包含PermissionSet blob的blob堆来查看ildasm.exe中的输出.我期望(根据ECMA-335):

2e 01 80 84 53 79 73 74  65 6d 2e 53 65 63 75 72 >.   System.Secur<
69 74 79 2e 50 65 72 6d  69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79  50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62  75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56  65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20  43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c  20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d  62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39  00 00

但我看到的是:

2e 01 80 84 53 79 73 74  65 6d 2e 53 65 63 75 72 >.   System.Secur<
69 74 79 2e 50 65 72 6d  69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79  50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62  75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56  65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20  43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c  20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d  62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39  01 00

特别要注意01 00的末尾,我预期00 00.规范说在计数的字符串之后应该是命名参数的数量.由于我没有传递任何命名参数,我预计该数字为16位0.

这是使用Visual Studio 2013针对.NET 2.0编译的.

更复杂的是,如果我添加一个命名参数,我得到这个:

2e 01 80 84 53 79 73 74  65 6d 2e 53 65 63 75 72 >.   System.Secur<
69 74 79 2e 50 65 72 6d  69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79  50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62  75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56  65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20  43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c  20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d  62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39  12 01 54 02 0d 55 6e 6d >1934e089  T  Unm<
61 6e 61 67 65 64 43 6f  64 65 01                >anagedCode      <

再次,查看属性的计数字符串的结尾,您可以看到12 01后跟命名参数列表(一个项目的列表).我希望这是01 00,一个16位的小端1用于命名参数的数量.

基于此,我假设计数字符串后面的第二个字节是命名参数计数但我仍然不明白第一个字节是什么(第一个例子中的0x01,下一个中的0x12).

如果我添加第二个命名属性,则第一个字节更改为26,如果我添加第三个命名属性,则更改为33.我没有看到数字的明显模式,而不是它们正在增加的事实.

我问这个问题是因为我试图手工构建一个PermissionSet blob(我正在编写一个CLR分析器),我需要知道该字节中要放什么.

解决方法:

我认为你的沮丧是正确的,我记得这是我之前对命名参数的经验 – NumNamed是作为压缩的int实现的,而不是规范中规定的int16,而不像给出的§VI.B.3的例子.我不知道在后续的.NET 3.0实现中是否已经改变了.

对于您正在寻找的PermissionSet,


* A set of properties, encoded as the named arguments to a custom
attribute would be (as in §II.23.3, beginning with NumNamed).


§II.23.3

Next is a description of the optional “named” fields and properties.
This starts with NumNamed – an unsigned int16 giving the number of
“named” properties or fields that follow. … In the case
where NumNamed is non-zero, it is followed by NumNamed repeats of
NamedArgs.

12 01是小端整数“给出后面的属性数”.一个命名属性,总长度为18(十进制,包括在内).

这个总长度是你正在寻找的模式,但要注意,因为我认为这个长度是可选的,有时编译器设法在前面的int16中打包属性的数量,丢弃长度.您将不得不尝试不同数量的属性,以确保正确解析所有案例.

NamesArgs:

… SerString – a PackedLen count of bytes, followed by the UTF8
characters

PROPERTY is the single byte 0x54. The FieldOrPropName is the name of
the field or property, stored as a SerString (defined above)

上一篇:为什么C# – > CIL在每条指令上都有标签?


下一篇:vue-cil 打包爬坑(解决)