2012-11-07 33 views
6

我有一点自定义IL我写,它不会通过PEVerify。我得到的错误是为什么.Net IL无法验证?

 
$ peverify foo.exe 

Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.17929 
Copyright (c) Microsoft Corporation. All rights reserved. 

[IL]: Error: [Z:\virtualbox_shared\foo.exe : HelloWorld.Program::Main][offset 0x00000021] Stack height at all points must be determinable in a single forward scan of IL. 
1 Error(s) Verifying foo.exe 

该程序将运行良好,没有任何例外。下面是相关方法的IL:

.method private static hidebysig 
    default void Main (string[] args) cil managed 
{ 
// Method begins at RVA 0x2050 
.entrypoint 
// Code size 54 (0x36) 
.maxstack 2 

//custom IL 
ldc.i4 1 
ldc.i4 1 
ceq 
switch(first, second) 

first: 
ldc.i4 1 
br.s temp 
popit: pop 
br.s second 

temp: ldc.i4 1 
brfalse temp2 
temp2: br.s popit 

second: 
ldc.i4 2 
pop 

ret 

} // end of method Program::Main 

完整的源代码在pastebin

为什么会出现这个错误?

+0

我不完全理解其中的逻辑,但看起来涉及到1.7.5反向分支约束上(http://books.google.com/books?id=50PhgS8vjhwC&pg=PA500&lpg=PA500&dq=1.7.5+Backward+ Branch + Constraints&source = bl&ots = vZJvWiy5mP&sig = SGz2IS1A4ynarLdB5aMg2ZGQ16g&hl = en&sa = X&ei = b5KaUOzZNuHWiwK87IGgCw&ved = 0CFYQ6AEwBQ#v = onepage&q&f = false) – Prescott

+0

@Prescott我真的没有把这看作是在这里应用。查看通过验证的[this](http://pastebin.com/YSPY5szf)代码(特别是IL_0018标签) – Earlz

回答

6

必须在IL

的一个正向扫描这就是确定核查失败的关键部分。验证者不会尝试验证每一个分支路径,这将需要解决停机问题。它对POP不满意,它不能在中看到一个正向扫描这个操作码是由非空堆栈的后向分支到达的,因此是有效的。

+0

因此,即使我的“解决方法”只是恰好通过了微软的peverify。查看ECMA规范的分区III 1.7.5,此代码看起来完全不符合要求。我认为在这种情况下应该使用本地变量而不是堆栈 – Earlz

+1

这是真正的编译器会做的,是的。 –

0

我不完全理解为什么是这样的答案,但是这也造成PEVerify:

.method private static hidebysig 
    default void Main (string[] args) cil managed 
{ 
// Method begins at RVA 0x2050 
.entrypoint 
// Code size 54 (0x36) 
.maxstack 2 

//custom IL 
ldc.i4 1 
ldc.i4 1 
ceq 
switch(first, second) 

first: 
ldc.i4 1 
br.s temp 
ldc.i4 1 //not reached, but required! 
popit: pop 
br.s second 

temp: ldc.i4 1 
brfalse temp2 
temp2: br.s popit 

second: 
ldc.i4 2 
pop 

ret 

} // end of method Program::Main