c# - 如何从 PEVerify 诊断 "Type load failed"

标签 c# .net cil ildasm peverify

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

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

PEVerify 的输出:

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

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

[IL]: Error: [C:\Build\Test\testcase.exe : Testing.Linq_operatorModule::IndexWhereImpl[T]][mdToken=0x6000002][offset 0x00000002] Unable to resolve token.

[IL]: Error: [C:\Build\Test\testcase.exe : Testing.Linq_operatorModule+$IndexWhereImpl$3`1[T]::.ctor][mdToken=0x6000006] [HRESULT 0 x8007000B] - An attempt was made to load a program with an incorrect format.

[token 0x02000004] Type load failed.

3 Error(s) Verifying testcase.exe

来自 ILDasm 的综合转储是 here ,因为它太大而无法放入 SO 帖子。

最佳答案

在生成此代码的任何内容中,您的类型参数的绑定(bind)有问题。生成的 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 的作者也是如此,尽管这不是借口。

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

关于c# - 如何从 PEVerify 诊断 "Type load failed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41415355/

相关文章:

c# - 为什么编译器会自动为匿名类型生成一个 Debugger 属性?

c# - 在c#中有没有类似java的Character.digit(char ch, int radix)的东西?

c# - 通过 Web 代理与 WCF 服务通信;从 Windows 服务中

c# - 清除DataTable中的多个列值

c# - Amazon EC2 开发堆栈

c# - 学习用 C# 编写多线程应用程序的引用资料?

c# - 尝试读取或写入 protected 内存。这通常表明其他内存已损坏

c# - 如何检查给定进程已创建到 Internet 的哪些连接

CIL指令 "isinst <valuetype>"

c# - CIL是汇编语言,JIT是汇编程序吗