不同类型在CIL中具有相同的签名

时间:2015-01-06 20:47:17

标签: .net cil ildasm

我在CIL中定义了一个字段,如下所示:

.field public int32 modopt(void*) fld

我把它编译成一个程序集。现在我将其更改为:

.field public int32 modopt(int16) fld

现在怎么可能ILDASM报告(显示为十六进制)这两个这些字段?

Field #1 (04000001)
-------------------------------------------------------
    Field Name: fld (04000001)
    Flags     : [Public]  (00000006)
    CallCnvntn: [FIELD]
    Field type:  CMOD_OPT 1b000001 I4
    Signature : 06 20 06 08 

此代码查找两个字段完全相同(实际上我创建了第二个字段以匹配报告的签名)。签名显然与第二个字段匹配,但第一个字段的签名应如下所示: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 

因此ILDASM十六进制转储中只有一个错误报告错误的成员签名(虽然我想知道错误签名中的06来自哪里)。

1 个答案:

答案 0 :(得分:1)

让我们尝试根据the specification手动构建字段签名。首先,字段签名在§II.23.2.4中定义。对于我们使用一个自定义修饰符的情况,它将是:

FIELD CustomMod Type

由于FIELD定义为0x06,我们有:

06 CustomMod Type

我们的自定义修饰符为modopt,因此我们得到(基于§II.23.2.7):

06 CMOD_OPT TypeDefOrRefOrSpecEncoded Type

CMOD_OPT是0x20(§II.23.1.16):

06 20 TypeDefOrRefOrSpecEncoded Type

我们想引用TypeSpec 0x1b000001,编码为0b110(TypeSpec为10,0x000001为1,§II.23.2.8)。然后将其“压缩”为单字节0x06(§II.23.2):

06 20 06 Type

最后,类型为int32,即ELEMENT_TYPE_I4 = 0x08(§II.23.2.12和§II.23.1.16):

06 20 06 08

因此,我们得到与ILDasm中显示的签名完全相同的签名。