2017-01-01 3 views
2

발전기를 확장하는 특정 경우에 잘못된 출력을 생성하는 컴파일러에서 작업 중입니다. PEVerify는 이유에 대해 설명하지 않고 단순히 "유형로드에 실패했습니다"라고 말합니다. 과거에 이것을 보았을 때 일반적으로 생성 된 유형의 수가 제네릭 매개 변수 개수가 잘못 되었기 때문에 발생했습니다. 그러나 모든 것이 여기에 일치하는 것 같습니다.PEVerify에서 "유형로드 실패"진단 방법

생성 된 유형에 어떤 문제가 있었는지에 대한 자세한 정보를 얻을 수있는 좋은 방법이 있습니까? 그 오류를 추적하는 방법에 대한 유용한 팁과 기술이 있습니까? PEVerify에서

출력 : ILDASM에서

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

종합 덤프 그것이 SO 게시물에 넣어 너무 큰 것에 따라, here입니다.

답변

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 참조 일반적인 방법의 첫 번째 유형 매개 변수, 당신은 방법에 필드를 선언 할 수 없습니다, 그래서이 그냥 항상 잘못입니다. 그것은 당신이

.field assembly !0 $value$5 

그것은 ILASM와 ILDASM도이를 허용하는 것이 조금 의외에 해당하는 0x13 0x00 (ELEMENT_TYPE_VAR 0)를 원 0x1e 0x00 (ELEMENT_TYPE_MVAR 0)에 조립, 나는 좀 더 안목으로 그들에게 기대. 명백히 PEVerify의 저자도 마찬가지였습니다. 변명의 여지가 없습니다.

나는 이렇게 코드를 생성하는 방법을 잘 모르겠습니다. 한 곳에서 오류가 발생하여 나머지는 유효하지 않게 될 수도 있습니다.

+0

저는 CCI로 코드를 생성합니다. CCI를 사용하면 행복하게 완전히 우스꽝스럽게 무효 인 IL을 생성 할 수 있습니다 ... 그러나 Reflection.Emit와는 달리 * 실제로 타입 문제를 질식시키고 블랙 박스를 제공하지 않습니다. ILDasm과 PEVerify를 실행하여 오류의 원인을 찾아 낼 방법이없는 오류. –

+0

감사합니다. 제네릭 형식 바인딩을 살펴 보겠습니다. 그것은 실제로 의미가 있습니다. 컴파일러는 제네릭 메소드를 생성기로 변환하고 메소드 locals를 생성기 클래스의 필드로 들어 올리므로 원래 메소드에서 제네릭 유형 매개 변수를 사용하는 것으로 식별됩니다. 그 문제를 해결할 시간. –

+0

좋습니다. 허용 된 것으로 표시합니다. –

관련 문제