我在CIL中定义了一个字段,如下所示:
.field public int32 modopt(void*) fld
Run Code Online (Sandbox Code Playgroud)
我把它编译成一个程序集.现在我将其更改为:
.field public int32 modopt(int16) fld
Run Code Online (Sandbox Code Playgroud)
现在,ILDASM如何报告(当显示为十六进制时)这两个字段都是可能的?
Field #1 (04000001)
-------------------------------------------------------
Field Name: fld (04000001)
Flags : [Public] (00000006)
CallCnvntn: [FIELD]
Field type: CMOD_OPT 1b000001 I4
Signature : 06 20 06 08
Run Code Online (Sandbox Code Playgroud)
此代码查找两个字段完全相同(实际上我创建了第二个字段以匹配报告的签名).签名明显相匹配的第二场,但第一场的签名应该是这样的:06 20 0f 01 08!我在这里错过了什么?
编辑:
C#不能发出这种类型的字段,抛出关于自定义类型修饰符不支持的指针和数组类型的异常,因此这显然解决了签名不匹配问题.但是ILDASM允许创建无法反编译的无效签名的问题仍然存在.
编辑#2:
似乎ILASM实际上正在创建正确的IL,我上次错过的十六进制转储存在差异:
//the first assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : Ptr Void
Signature: 0f 01
//the second assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : I2
Signature: 06
Run Code Online (Sandbox Code Playgroud)
因此,ILDASM十六进制转储中只有一个错误报告了错误的成员签名(尽管我想知道06错误签名的来源).
让我们尝试根据规范手动构建字段签名。首先,字段签名在 \xc2\xa7II.23.2.4 中定义。对于我们使用一个自定义修饰符的情况,它将是:
\n\nFIELD CustomMod Type\nRun Code Online (Sandbox Code Playgroud)\n\n由于FIELD被定义为 0x06,我们有:
06 CustomMod Type\nRun Code Online (Sandbox Code Playgroud)\n\n我们的自定义修饰符是modopt,所以我们得到(基于 \xc2\xa7II.23.2.7):
06 CMOD_OPT TypeDefOrRefOrSpecEncoded Type\nRun Code Online (Sandbox Code Playgroud)\n\nCMOD_OPT是 0x20 (\xc2\xa7II.23.1.16):
06 20 TypeDefOrRefOrSpecEncoded Type\nRun Code Online (Sandbox Code Playgroud)\n\n我们想要引用TypeSpec0x1b000001,它被编码为 0b110(10 代表TypeSpec,1 代表 0x000001,\xc2\xa7II.23.2.8)。然后将其“压缩”为单字节 0x06 (\xc2\xa7II.23.2):
06 20 06 Type\nRun Code Online (Sandbox Code Playgroud)\n\n最后,类型为int32,即ELEMENT_TYPE_I4= 0x08(\xc2\xa7II.23.2.12 和 \xc2\xa7II.23.1.16):
06 20 06 08\nRun Code Online (Sandbox Code Playgroud)\n\n所以我们得到了与 ILDasm 中显示的完全相同的签名。
\n| 归档时间: |
|
| 查看次数: |
181 次 |
| 最近记录: |