2017-01-01 56 views
2

我正在研究一個在某些擴展生成器的情況下生成錯誤輸出的編譯器。 PEVerify只是說「類型加載失敗」,沒有給出任何解釋爲什麼。當我看到過去的時候,一般是因爲生成的類型的泛型參數數量錯了,但是這裏的一切似乎都匹配了。如何診斷「類型加載失敗」來自PEVerify

有沒有什麼好方法可以獲得關於生成類型出錯的更多詳細信息?除此之外,有沒有什麼好的技巧和技巧來找出錯誤?從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崗位。

回答

2

在生成此代碼的任何內容中,您的類型參數的綁定有些問題。由此產生的IL可以進行彙編,但是如此無效以至於PE徹底扼殺了它(這可以說是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 0x00ELEMENT_TYPE_MVAR 0),你想0x13 0x00ELEMENT_TYPE_VAR 0),對應於

.field assembly !0 $value$5 

這是一個有點令人驚訝的是ILASM和反彙編甚至允許這樣做,我希望他們能多一點挑剔。顯然,PEVerify的作者也是如此,儘管這不是理由。

我不確定你是如何生成這樣的代碼;它可能是一個地方的錯誤,導致其餘的無效。

+0

我用CCI生成類似這樣的代碼,它將會愉快地生成完全可笑的IL ......但與Reflection.Emit不同,它將*實際生成它,*而不是窒息類型問題並給我一個黑盒子錯誤無法運行ILDasm和PEVerify來找出錯誤。 –

+0

所以,謝謝。我會研究泛型類型的綁定。這實際上是有道理的。編譯器正在將泛型方法轉換爲生成器,並且將方法局部變量提升到生成器類的字段中,這意味着它們仍然被識別爲使用始發方法中的泛型類型參數。有時間來解決這個問題。 –

+0

好的,工作。標記爲已接受。 –