6

我编写了一些自定义 IL,但它不会通过 PEVerify。我得到的错误是

$ peverify foo.exe

Microsoft (R) .NET Framework PE 验证程序。版本 4.0.30319.17929
版权所有 (c) 微软公司。版权所有。

[IL]:错误:[Z:\virtualbox_shared\foo.exe : HelloWorld.Program::Main][offset 0x00000021] 所有点的堆栈高度必须在 IL 的单次前向扫描中确定。
1 验证 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

为什么我会收到此错误?

4

2 回答 2

6

必须在 IL 的单次前向扫描中确定

这是验证失败的关键部分。验证者不会尝试验证每一个分支路径,这需要解决停机问题。它对 POP 不满意,它无法在单次前向扫描中看到该操作码是由具有非空堆栈的后向分支到达的,因此是有效的。

于 2012-11-07T17:43:46.730 回答
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
于 2012-11-07T17:27:23.647 回答