2017-01-01 9 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 может быть собран, но настолько отчаянно недействителен, что 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, хотя это не оправдание.

Я не уверен, как вы генерируете такой код; это может быть ошибка в одном месте, что приводит к тому, что остальные также недействительны.

+0

Я генерирую код, подобный этому, с CCI, который с удовольствием произведет полностью, смехотворно недействительный IL ... но в отличие от Reflection.Emit, он будет * фактически производить его *, а не задыхаться от проблем типа и давать мне черный ящик ошибка без возможности запуска ILDasm и PEVerify, чтобы выяснить, что происходит не так. –

+0

Итак, спасибо. Я рассмотрю типичные привязки типов. Это действительно имеет смысл. Компилятор преобразует общий метод в генератор и локализует его в поля класса генератора, а это означает, что они все еще идентифицируются как используемые параметры типового типа из исходного метода. Время работать над исправлением этого. –

+0

Хорошо, это сработало. Маркировка как принято. –