我正在研究在某些扩展生成器的情况下会产生错误输出的编译器。 PEVerify简单地说"类型加载失败"没有给出任何解释为什么。当我在过去看到这个时,通常是因为生成的类型具有错误的通用参数数量,但是这里的所有内容似乎都匹配。
有没有什么好方法可以获得有关生成类型出错的更详细信息?除此之外,是否有任何关于如何追踪错误的好技巧和技巧?
PEVerify的输出:
C:\ Build \ Test> peverify testcase.exe / VERBOSE / UNIQUE
Microsoft(R).NET Framework PE Verifier。版本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] - 尝试加载格式不正确的程序。
[token 0x02000004]类型加载失败。
3个错误验证testcase.exe
来自ILDasm的全面转储是here,因为它太大而无法放入SO帖子。
答案 0 :(得分: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的作者也是如此,尽管这不是理由。
我不确定你是如何生成这样的代码的;在一个地方可能是一个错误导致其余部分也无效。