3

我正在开发一个编译器,该编译器在某些扩展生成器的情况下会产生错误的输出。PEVerify 只是说“类型加载失败”而没有解释原因。当我过去看到这种情况时,通常是因为生成的类型具有错误数量的泛型参数,但这里似乎一切都匹配。

有什么好方法可以获取有关生成的类型出了什么问题的更详细信息?除此之外,是否有任何好的提示和技术来追踪错误?

PEVerify 的输出:

C:\Build\Test>peverify testcase.exe /VERBOSE /UNIQUE

Microsoft (R) .NET Framework PE 验证程序。版本 4.0.30319.0 版权所有 (c) Microsoft Corporation。版权所有。

[IL]:错误:[C:\Build\Test\testcase.exe:Testing.Linq_operatorModule::IndexWhereImpl[T]][mdToken=0x6000002][offset 0x00000002] 无法解析令牌。

[IL]:错误:[C:\Build\Test\testcase.exe : Testing.Linq_operatorModule+$IndexWhereImpl$3`1[T]::.ctor][mdToken=0x6000006] [HRESULT 0 x8007000B] - 尝试加载格式不正确的程序。

[令牌 0x02000004] 类型加载失败。

3 验证 testcase.exe 的错误

ILDasm 的综合转储在这里,因为它太大而无法放入 SO 帖子。

4

1 回答 1

2

在生成此代码的任何内容中绑定类型参数都有问题。生成的 IL 可以组装,但非常无效,以至于 PEVerify 彻底窒息了它(这可以说是 PEVerify 中的一个错误,但像 Mono.Cecil 这样的东西一点也不喜欢这段代码)。

例如:

  .method /*06000002*/ private hidebysig static 
          class [mscorlib/*23000004*/]System.Collections.Generic.IEnumerable`1/*01000003*/<int32> 
          IndexWhereImpl<T>(class [mscorlib/*23000004*/]System.Collections.Generic.IEnumerable`1/*01000003*/<!!T> coll,
                            class [mscorlib/*23000004*/]System.Func`2/*01000004*/<!!T,bool> 'filter') cil managed
  {
    // Code size       8 (0x8)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldarg.1
    IL_0002:  newobj     instance void Testing.Linq_operatorModule/*02000002*//$IndexWhereImpl$3`1/*02000003*/::.ctor(class [mscorlib/*23000004*/]System.Collections.Generic.IEnumerable`1/*01000003*/<!!T>,
                                                                                                                      class [mscorlib/*23000004*/]System.Func`2/*01000004*/<!!T,bool>) /* 06000006 */
    IL_0007:  ret
  } // end of method Linq_operatorModule::IndexWhereImpl

反汇编的构造函数调用无效;正确的电话是

newobj instance void class Testing.Linq_operatorModule/$IndexWhereImpl$3`1<!!T>::.ctor(
    class [mscorlib]System.Collections.Generic.IEnumerable`1<!0>,
    class [mscorlib]System.Func`2<!0,bool>
)

原始调用适用于泛型方法,但我们调用的不是泛型方法,而是泛型类的实例方法。

剩下的代码是这样的,包括参数引用无效的字段:

.field assembly !!0 $value$5

!!0引用泛型方法的第一个类型参数,并且您不能在方法中声明字段,所以这总是错误的。它组装成0x1e 0x00( ELEMENT_TYPE_MVAR 0),你想要0x13 0x00( ELEMENT_TYPE_VAR 0),对应于

.field assembly !0 $value$5

ilasm 和 ildasm 甚至允许这样做有点令人惊讶,我希望他们更有洞察力。显然,PEVerify 的作者也是如此,尽管这不是借口。

我不确定您如何生成这样的代码;可能是某个地方的错误导致其余部分也无效。

于 2017-01-02T15:26:39.970 回答