static instance method?

Topics: Metadata Model, PE Writer
Dec 3, 2010 at 5:53 PM

Hello.

I'm getting this method  with both static and instance flags. How can it happen?

 

.method public hidebysig static instance void $Main() cil managed
{
    .entrypoint
    .maxstack 8
    L_0000: ldc.r8 3.546
    L_0009: ldc.r8 0.456456456464
    L_0012: add 
    L_0013: pop 
    L_0014: ldstr "something!"
    L_0019: call void [mscorlib]System.Console::WriteLine(string)
    L_001e: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
    L_0023: pop 
    L_0024: ret 
}

 
 

I'm using a class that implements IMethodDefinition but the IsStatic implementation returns true. Shouldn't that be enough? Should I check anything else?

This is the entry point of a console executable that is throwing 

"Unhandled exception: System.TypeLoadException: The signature is incorrect"

when I run it. Can this be (part of) the problem?

Thanks.

 

 

 

Coordinator
Dec 3, 2010 at 6:12 PM

Can you clarify this a bit? Did you generate $Main? A method cannot (legally) be both static and instance, although it is possible to emit metadata that have both flag bits set at the same time.

Dec 3, 2010 at 6:22 PM

The code above is emitted by your CCI code, processing a class of mine that implements IMethodDefinition. The class represents the main method of an application.

There could be a bug in my class and not in your code but I don't where to look at. Or maybe something in my IMethodDefinition is triggering a bug in your code. I have no idea.  My class's IsStatic implementation returns true.

This is copied and pasted from the VS Watch window:

 

methodDef	{PerPlexEd.Language.Compiler.MethodDefinition}	Microsoft.Cci.IMethodDefinition {PerPlexEd.Language.Compiler.MethodDefinition}
[PerPlexEd.Language.Compiler.MethodDefinition]	{PerPlexEd.Language.Compiler.MethodDefinition}	PerPlexEd.Language.Compiler.MethodDefinition
Body	{Microsoft.Cci.MutableCodeModel.SourceMethodBody}	Microsoft.Cci.IMethodBody {Microsoft.Cci.MutableCodeModel.SourceMethodBody}
GenericParameters	Count = 0	System.Collections.Generic.IEnumerable<Microsoft.Cci.IGenericMethodParameter> {PerPlexEd.Cci.Metadata.ShortCollection<Microsoft.Cci.IGenericMethodParameter>}
HasDeclarativeSecurity	false	bool
HasExplicitThisParameter	false	bool
IsAbstract	false	bool
IsAccessCheckedOnOverride	false	bool
IsCil	true	bool
IsConstructor	false	bool
IsExternal	false	bool
IsForwardReference	false	bool
IsHiddenBySignature	true	bool
IsNativeCode	false	bool
IsNeverInlined	false	bool
IsNeverOptimized	false	bool
IsNewSlot	false	bool
IsPlatformInvoke	false	bool
IsRuntimeImplemented	false	bool
IsRuntimeInternal	false	bool
IsRuntimeSpecial	false	bool
IsSealed	false	bool
IsSpecialName	false	bool
IsStatic	true	bool  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<--------------
IsStaticConstructor	false	bool
IsSynchronized	false	bool
IsUnmanaged	false	bool
IsVirtual	false	bool
Parameters	Count = 0	System.Collections.Generic.IEnumerable<Microsoft.Cci.IParameterDefinition> {PerPlexEd.Cci.Metadata.ShortCollection<Microsoft.Cci.IParameterDefinition>}
PlatformInvokeData	{Microsoft.Cci.DummyPlatformInvokeInformation}	Microsoft.Cci.IPlatformInvokeInformation {Microsoft.Cci.DummyPlatformInvokeInformation}
PreserveSignature	false	bool
RequiresSecurityObject	false	bool
ReturnValueAttributes	{Microsoft.Cci.ICustomAttribute[0]}	System.Collections.Generic.IEnumerable<Microsoft.Cci.ICustomAttribute> {Microsoft.Cci.ICustomAttribute[]}
ReturnValueIsMarshalledExplicitly	false	bool
ReturnValueMarshallingInformation	{Microsoft.Cci.DummyMarshallingInformation}	Microsoft.Cci.IMarshallingInformation {Microsoft.Cci.DummyMarshallingInformation}
SecurityAttributes	{Microsoft.Cci.ISecurityAttribute[0]}	System.Collections.Generic.IEnumerable<Microsoft.Cci.ISecurityAttribute> {Microsoft.Cci.ISecurityAttribute[]}

 

the context is this method in PeWriter:

 

    private static ushort GetMethodFlags(IMethodDefinition methodDef) {
      ushort result = GetTypeMemberVisibilityFlags(methodDef);
      if (methodDef.IsStatic) result |= 0x0010;
      if (methodDef.IsSealed) result |= 0x0020;
      if (methodDef.IsVirtual) result |= 0x0040;
      if (methodDef.IsHiddenBySignature) result |= 0x0080;
      if (methodDef.IsNewSlot) result |= 0x0100;
      if (methodDef.IsAccessCheckedOnOverride) result |= 0x0200;
      if (methodDef.IsAbstract) result |= 0x0400;
      if (methodDef.IsSpecialName) result |= 0x0800;
      if (methodDef.IsRuntimeSpecial) result |= 0x1000;
      if (methodDef.IsPlatformInvoke) result |= 0x2000;
      if (methodDef.HasDeclarativeSecurity) result |= 0x4000;
      if (methodDef.RequiresSecurityObject) result |= 0x8000;
      return result;
    }

 

which is where, in my understanding, the flags are collected.

 

 

 

Coordinator
Dec 3, 2010 at 6:29 PM

Actually, come to think of it, a method can be marked (incorrectly) as static and virtual at the same time, but not as static and instance (the latter is simply the negation of the former), so it is extremely confusing to see both static and instance showing up in the ildasm output.

Could you post a small binary that exhibits this problem so that I can have a look at what is actually in the flags?

Dec 3, 2010 at 6:49 PM

I sent a 2kbyte assembly at your email address.

 

Dec 3, 2010 at 7:05 PM

I started ildasm for the first time in my life and it shows the same "static instance" flag combination:

.method public hidebysig static instance void 
        $Main() cil managed
{
  .entrypoint
  // Code size       37 (0x25)
  .maxstack  8
  IL_0000:  ldc.r8     3.5459999999999998
  IL_0009:  ldc.r8     0.45645645646400002
  IL_0012:  add
  IL_0013:  pop
  IL_0014:  ldstr      "something!"
  IL_0019:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001e:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  IL_0023:  pop
  IL_0024:  ret
} // end of method $Application::$Main

Coordinator
Dec 3, 2010 at 7:07 PM

peverify is helpful here:

C:\bug>peverify helloread.pe

 

Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.1

Copyright (c) Microsoft Corporation. All rights reserved.

 

[MD]: Error: TypeDef is marked HasSecurity but has no security information. [token:0x02000002]

[MD]: Error: Method is marked Static but calling convention=0x00000020 is marked HASTHIS. [token:0x06000001]

2 Error(s) Verifying helloread.pe

 

Dec 3, 2010 at 7:14 PM

Time to learn to use another tool, it seems. I'll run it routinely when I generate any assembly from now on. Thanks.