我正在处理混淆程序集,在混淆之后,PEVerify发出以下错误:
[MD]: Error: Method has a duplicate, token=0x060035d8. [token:0x060035D5]
[MD]: Error: Method has a duplicate, token=0x060035d5. [token:0x060035D8]下面是第一个带有头的方法声明:
// Token: 0x060035D5 RID: 13781 RVA: 0x000D7828 File Offset: 0x000D5A28
.method private final hidebysig newslot virtual
instance void b () cil managed
{
.override method instance void [mscorlib]System.IDisposable::Dispose()
// Header Size: 12 bytes
// Code Size: 52 (0x34) bytes
// LocalVarSig Token: 0x11000050 RID: 80
.maxstack 2
.locals init (
[0] int32
)这是第二个:
// Token: 0x060035D8 RID: 13784 RVA: 0x000248BC File Offset: 0x00022ABC
.method private hidebysig
instance void b () cil managed
{
// Header Size: 1 byte
// Code Size: 31 (0x1F) bytes
.maxstack 8在我看来,这是一个显式的IDisposable接口实现。这两个方法也都被调用了,所以并不是所有对一个方法的调用都被调用另一个方法所取代。他们只是同名
如果在C#中编写了类似的代码,编译器将发出System.IDisposable.Dispose()和Dispose()方法,从而消除相同的名称,并使PEVerify保持沉默。
为了确保相同的名称在其中一个是接口方法的显式覆盖而另一个不是有效的IL时,我编写了这样的示例应用程序:
namespace ClassLibrary1 {
public interface IX { void M(); }
public class Class1 : IX {
void IX.M() { Console.WriteLine("IX.M()"); }
public void M() { Console.WriteLine("M()"); }
}
public class Class2 {
public static void Main(string[] args) {
var x = new Class1();
x.M();
((IX)x).M();
}
}
}IL看起来是这样的:
// Token: 0x06000002 RID: 2 RVA: 0x00002050 File Offset: 0x00000250
.method private final hidebysig newslot virtual
instance void ClassLibrary1.IX.M () cil managed
{
.override method instance void ClassLibrary1.IX::M()
// Header Size: 1 byte
// Code Size: 13 (0xD) bytes
.maxstack 8
/* 0x00000251 00 */ IL_0000: nop
/* 0x00000252 7201000070 */ IL_0001: ldstr "IX.M()"
/* 0x00000257 280F00000A */ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
/* 0x0000025C 00 */ IL_000B: nop
/* 0x0000025D 2A */ IL_000C: ret
} // end of method Class1::ClassLibrary1.IX.M
// Token: 0x06000003 RID: 3 RVA: 0x0000205E File Offset: 0x0000025E
.method public hidebysig
instance void M () cil managed
{
// Header Size: 1 byte
// Code Size: 13 (0xD) bytes
.maxstack 8
/* 0x0000025F 00 */ IL_0000: nop
/* 0x00000260 720F000070 */ IL_0001: ldstr "M()"
/* 0x00000265 280F00000A */ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
/* 0x0000026A 00 */ IL_000B: nop
/* 0x0000026B 2A */ IL_000C: ret
} // end of method Class1::M注意不同的方法名称。
然后,我使用了生成的exe并编辑了ClassLibrary1.IX.M,使其成为Class1中的M (我使用了dnSpy来实现这一点)。PEVerify确实开始发布关于重复方法的相同问题,但是exe仍然按照预期的那样很好地打印M() IX.M()。
问题是,如果PEVerify在这里过于谨慎,还是真的有一个与我看不到的名字重合的问题?
发布于 2016-02-02 15:33:49
这两个方法共享相同的方法签名,这是完全不允许的。
对于CLR,方法签名由方法名称、泛型性、形式参数性、形式参数类型和类型以及返回类型组成。
.Net IL汇编程序中的Serge状态,第10章中的方法表有效性规则
任何重复的记录-归属于相同的TypeDef和具有相同的名称和签名-不应该存在,除非可访问性标志是私人录像。
当然,您可以在ECMA-335规范的第二.22.1分区中找到这一规则:
唯一行:任何表都不能包含重复行,其中“重复”是根据其键列定义的,或者是列的组合。
https://stackoverflow.com/questions/35157288
复制相似问题