Program47.csc

Public void DisplayAllMethods(int typeindex)

{

methodstring = methodstring + CreateSpaces(spacesforrest + 2 + spacesfornested) +  "// Code size       0 (0x0)" + "\r\n";

if ( IsGlobalMethod(methodindex))

methodstring = methodstring + CreateSpaces(spacesforrest+ spacesfornested) + "} // end of global method " + NameReserved(GetString(MethodStruct[methodindex].name)) + "\r\n";

else

methodstring = methodstring + CreateSpaces(spacesforrest+ spacesfornested) + "} // end of method " + NameReserved(GetString(TypeDefStruct[typeindex].name)) + "::" + NameReserved(GetString(MethodStruct[methodindex].name)) + "\r\n";

Console.WriteLine(methodstring);

}

public void DisplayTypeDefsAndMethods ()

{

notprototype = true;

if ( TypeDefStruct.Length != 2)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

}

Console.WriteLine();

Console.WriteLine("// =============== GLOBAL FIELDS AND METHODS ===================");

Console.WriteLine();

DisplayGlobalFields();

DisplayGlobalMethods();

if ( TypeDefStruct.Length != 2)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

}

 

public void DisplayGlobalFields ()

{

int start , startofnext =0;

if ( TypeDefStruct == null || FieldStruct == null)

return;

start =  TypeDefStruct[1].findex ;

if ( TypeDefStruct.Length == 2 )

startofnext = FieldStruct.Length;

else

startofnext = TypeDefStruct[2].findex ;

if ( start != startofnext )

{

Console.WriteLine("//Global fields");

Console.WriteLine("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

DisplayAllFields (1);

}

}

public void DisplayGlobalMethods ()

{

int start , startofnext=0;

start =  TypeDefStruct[1].mindex ;

if ( TypeDefStruct == null || MethodStruct == null)

return;

 

if ( TypeDefStruct.Length == 2 )

startofnext= MethodStruct.Length;

else

startofnext = TypeDefStruct[2].mindex ;

if ( start != startofnext )

{

Console.WriteLine("//Global methods");

Console.WriteLine("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

spacesforrest = 0;

DisplayAllMethods(1);

spacesforrest = 2;

}

}

public bool IsGlobalMethod (int methodrow)

{

int start , startofnext=0;

methodrow , TypeDefStruct.Length);

if ( TypeDefStruct.Length == 2)

return true;

start =  TypeDefStruct[1].mindex ;

if ( TypeDefStruct.Length == 1 )

{

startofnext= MethodStruct.Length;

}

else

startofnext = TypeDefStruct[2].mindex;

if ( methodrow >= start && methodrow < startofnext )

return true;

else

return false;

}

 

e.il

.namespace kkk

{

.method static private void a1()

{

}

.field static private int32 i

}

.class zzz

{

}

 

Output

// =============================================================

 

 

// =============== GLOBAL FIELDS AND METHODS ===================

 

//Global fields

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.field /*04000001*/ private static int32 i

//Global methods

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.method /*06000001*/ private static void

        a1() cil managed

// SIG: 00 00 01

{

  // Method begins at RVA 0x2050

  // Code size       0 (0x0)

} // end of global method a1

 

 

// =============================================================

 

In this small program we display all the global method and fields that we have in the il file. Most newer languages do not support the concept of global fields and variables but we are fortunate that il does. We told you a long time ago that we always have a extra type that will handle global entities.

 

We have in the DisplayAllMethods a if statement at the very end that checks whether we have a global function or not. We have written a function IsGlobalMethod that tells us whether the current method is global or not by passing it the method number. In this method we first check if there are only global methods in the il file.

 

This happens if the length of the TypeDef array is 2, remember it is always larger by one. We also told you that there is always a global type available. We then find out as before the first and last method owned by this global type. If the method row falls within this range we return true or else we return false.

 

The only change is that as always we no not check for the last type but for the first type. If this method returns true, we do display the type name that is Module but add the words global instead. In the method DisplayTypeDefsAndMethods we have add two lines in the beginning that call the methods DisplayGlobalFields and DisplayGlobalMethods.

 

The method DisplayGlobalFields first checks whether they are global fields available. It does this by setting start to the findex of the first TypeDef entity that is module. Then it sets the startofnext to the second Typedef.

 

At times there is only a single type and hence we then set startofnext to the length of the number of rows in the Field table. If start and startofnext are the same, we have global fields and therefore display some text and call the DisplayAllFields method with the type row number as 1.

 

We do the same for the DisplayGlobalMethods but now also set the spacesforrest at 2 for the rest of the method that will follow the global methods. The setting of the variable has no effect on the global methods as there is no global namespace for global fields or methods and if we even add one, it gets removed.

 

Program48.csc

 

e.il

.assembly extern mscorlib

{

}

.mresource aa

{

.custom instance void [mscorlib]a18::.ctor() = (65)

}

.assembly extern vijay

{

.custom instance void [mscorlib]a15::.ctor() = (65)

}

.assembly e.dll

{

.custom instance void [vijay]a14::.ctor() = (65)

}

.module extern kk.dll

.custom instance void [vijay]a12::.ctor() = (65)

.module aa.dll

.custom instance void [vijay]a7::.ctor() = (65)

.file aa

.custom instance void [mscorlib]a177::.ctor() = (65)

.class extern xxx

{

.custom instance void [mscorlib]a17::.ctor() = (65)

.file aa

}

.class uuu

{

.permissionset assert = (12 )

.custom instance void [vijay]a8::.ctor() = (65)

}

.class zzz

{

.custom instance void [vijay]a4::.ctor() = (65)

.field public int32 pqr

.custom instance void [vijay]a2::.ctor() = (65)

.method public void abc(int32 i , int32 j)

{

.param [1] = int8(10)

.custom instance void [vijay]a5::.ctor() = (65)

}

.method public void abc1()

{

.custom instance void [vijay]a1::.ctor() = (65)

}

/*

.method void xyz()

{

call void [vijay]yyy::pqr()

.custom instance void [vijay]a6::.ctor() = (65)

}

*/

.property instance int32 aa()

{

.custom instance void [vijay]a9::.ctor() = (65)

.get instance void zzz::abc1()

}

.event [vijay]re a

{

.custom instance void [vijay]a10::.ctor() = (65)

.addon instance void zzz::abc1()

}

}

.class interface iii

{

.custom instance void [vijay]a5::.ctor() = (65)

}

.custom ([vijay]a3) instance void [vijay]a33::.ctor() = (65)

//.custom ([vijay]a6::abc()) instance void [vijay]a66::.ctor() = (65)

 

We have not made any major additions to this program but simply added a series of DisplayCustomAttribute methods calls at many places. Thus we will start with the il file and show you code fragments of the functions where we have added the call of the method DisplayCustomAttribute. We have also tried to show you the il output and the method together. The first is the function abc where we move the method CreateSignatures above the method DisplayModuleRefs as we would like all the arrays to be filled up earlier.

 

public void abc(string [] args)

{

CreateSignatures();

DisplayModuleRefs ();

DisplayAssembleyRefs();

}

 

public void DisplayAssembleyRefs ()

{

if (AssemblyRefStruct == null)

return;

for ( int i = 1 ; i < AssemblyRefStruct.Length ; i++)

{

Console.WriteLine(".assembly extern /*23{0}*/ {1}", i.ToString("X6") , NameReserved(GetString(AssemblyRefStruct[i].name)));

Console.WriteLine("{");

DisplayCustomAttribute ("AssemblyRef" , i , 2 );

 

.assembly extern /*23000002*/ vijay

{

  .custom /*0C00000A:0A000002*/ instance void [mscorlib/* 23000001 */]a15/* 01000002 */::.ctor() /* 0A000002 */ = "e"

  .ver 0:0:0:0

}

 

We have a custom attribute in the AssemblyRef table and thus we add the method DisplayCustomAttribute just after the { brace.

 

public void DisplayAssembley ()

{

if (AssemblyStruct.Length == 1)

return;

Console.WriteLine(".assembly /*20000001*/ {0}" , NameReserved(GetString(AssemblyStruct[1].name)));

Console.WriteLine("{");

DisplayCustomAttribute("Assembly" , 1 , 2 + spacefornamespace);

 

.assembly /*20000001*/ e.dll

{

  .custom /*0C000006:0A000003*/ instance void [vijay/* 23000002 */]a14/* 01000003 */::.ctor() /* 0A000003 */ = "e"

  .ver 0:0:0:0

}

 

The second place is the Assembly table as this table has only one row we have used the row number as 1.

 

public void DisplayClassExtern ()

{

 

Console.Write(".class extern /*27{0}*/ {1}" , ii.ToString("X6") , ss1 );

Console.WriteLine(ss);

Console.WriteLine("{");

DisplayCustomAttribute("ExportedType" , ii , 2);

 

}

 

.class extern /*27000001*/ xxx

{

  .custom /*0C000007:0A000006*/ instance void [mscorlib/* 23000001 */]a17/* 01000006 */::.ctor() /* 0A000006 */ = "e"

  .file aa/*26000001*/

}

 

The third place is the Class Extern directive or what we call the Exported Type.

 

public void DisplayModuleAndMore()

{

Console.WriteLine(".module {0}" , NameReserved(GetString(ModuleStruct[1].Name)));

Console.Write("// MVID: ");

DisplayGuid(ModuleStruct[1].Mvid);

Console.WriteLine();

DisplayCustomAttribute("Module"  , 1 , 0);

 

.module aa.dll

// MVID: {AF4812DF-31BB-48D0-87D5-964909ECF751}

.custom /*0C000003:0A000005*/ instance void [vijay/* 23000002 */]a7/* 01000005 */::.ctor() /* 0A000005 */ = "e"

 

The fourth place is the Module table and once again the row number is 1.

 

public void DisplayAllFields (int typeindex)

{

Console.WriteLine("{0}" , returnstring);

DisplayCustomAttribute("FieldDef" , fieldindex , spacesfornested + spacesforrest);

}

}

 

  .field /*04000001*/ public int32 pqr

  .custom /*0C000001:0A000009*/ instance void [vijay/* 23000002 */]a2/* 0100000A */::.ctor() /* 0A000009 */ = "e"

 

The fifth one is the attribute with fields and we place it right at the end of the function.

 

Console.WriteLine("{");

DisplayCustomAttribute("Event" , eventrow , spacesfornested + spacesforrest+2);

for ( int kk = 1 ; kk < MethodSemanticsStruct.Length ; kk++)

{

 

  .event /*14000001*/ [vijay/* 23000002 */]re/* 0100000E */ /*0100000E*/ a

  {

    .custom /*0C000005:0A00000D*/ instance void [vijay/* 23000002 */]a10/* 0100000F */::.ctor() /* 0A00000D */ = "e"

    .addon instance void zzz/* 02000003 */::abc1() /* 06000002 */

  } // end of event zzz::a

 

With an event the attribute is placed at the beginning like that of  a property.

 

public void DisplayAllProperties (int typeindex)

{

DisplayCustomAttribute("Property" , propertyrow , 2 + spacesforrest + spacesfornested);

for ( int kk = 1 ; kk < MethodSemanticsStruct.Length ; kk++)

{

 

}

 

  .property /*17000001*/ instance int32 aa()

  {

    .custom /*0C000004:0A00000C*/ instance void [vijay/* 23000002 */]a9/* 0100000D */::.ctor() /* 0A00000C */ = "e"

    .get /*06000002*/ instance void zzz/* 02000003 */::abc1() /* 06000002 */

  } // end of property zzz::aa

 

public void DisplayEnd()

{

string nspace = NameReserved(GetString(TypeDefStruct[TypeDefStruct.Length-1].nspace));

if ( ! placedend)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

placedend = true;

}

if ( nspace == "")

DisplayCustomAttribute("TypeRef" , 0 , 0);

 

.custom /*0C00000D*/ ([vijay/* 23000002 */]a3/* 01000010 *//*01000010*/ ) instance void [vijay/* 23000002 */]a33/* 01000011 */::.ctor() /* 0A00000E */ = "e"

//*********** DISASSEMBLY COMPLETE ***********************

 

We then need to add the TypeRef custom attribute at the very end of the output and thus use  the DisplayEnd if the namespace is null. Also we need the TypeRef for the case where the namespace is not null.

 

public void DisplayOneTypeDefEnd (int typeindex )

{

if ( nspace1 != nspace2 )

{

if ( lasttypedisplayed == typeindex && notprototype  )

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

placedend = true;

DisplayCustomAttribute("TypeRef" , 0 , 2);

}

}

 

public void DisplayFileTable ()

{

 

DisplayCustomAttribute ("File" , ii , 0);

}

}

 

.file /*26000001*/ aa

.custom /*0C000007:0A000006*/ instance void [mscorlib/* 23000001 */]a177/* 01000006 */::.ctor() /* 0A000006 */ = "e"

 

We have added the method DisplayCustomAttribute at the end of the DisplayFileTable method.

 

Customs that did not happen

 

e.il

.assembly extern vijay

{

}

.mresource aa

{

.custom instance void [vijay]a18::.ctor() = (65)

}

.class zzz

{

}

 

.mresource /*28000001*/ aa

{

  // WARNING: managed resource file aa created

}

 

We have a custom attribute in the mresource directive and ilasm just does not create an entry in the CustomAttribute table for it. In the next series of examples we will manually add a custom attribute and figure out how ildasm handles it.

 

e.il

.assembly extern vijay

{

}

.mresource aa

{

}

.class zzz

{

.custom instance void [vijay]a18::.ctor() = (65)

}

 

We create a simple il file with a custom attribute in a type and a single mresource directive. We print out the initial bytes of the custom attribute table and search for these bytes in a hex editor. We used Ultra Edit as explained earlier. In our case the first six bytes of the CustomAttribute table are 43 0 B 0 5 0. The first two bytes are the parent coded index. The first 5 bits of the first byte 43 are the table number. This is 3 the table number of a TypeDef and the last 13 bits have a value of 2. This is as the first TypeDef we create is number as the global type def is number 1. We change the first byte to 32 as the first 5 bits are 18, the code for a manifest resource and the last three bits taken by themselves are 1, to stand for row number 1. When we run ildasm on e.dll, we get the following output.

 

.mresource /*28000001*/ aa

{

  .custom /*0C000001:0A000001*/ instance void [vijay/* 23000001 */]a18/* 01000002 */::.ctor() /* 0A000001 */ = "e"

  // WARNING: managed resource file aa created

}

 

Thus ildasm recognizes a custom attribute and ilasm does not. We have not added code to our mresource directive to display a custom attribute.

 

.assembly extern vijay

{

}

.module extern aa.dll

.custom instance void [vijay]a18::.ctor() = (65)

.class zzz

{

}

 

We have added a custom attribute to the module extern directive and ilasm ignores it. We once again get back to the earlier program and now change the first byte from 43 to 2C as we want the first 5 bits to be 12 the code for a module ref table and the last three bits to be 1.

 

.module extern aa.dll /*1A000001*/

.custom /*0C000001:0A000001*/ instance void [vijay/* 23000001 */]a18/* 01000002 */::.ctor() /* 0A000001 */ = "e"

 

When we run ildasm on e.dll, we see the custom attribute below the module extern directive.

 

.assembly extern vijay

{

}

.class zzz

{

.permissionset assert = ( 41 42)

.custom instance void [vijay]a18::.ctor() = (65)

}

 

We have added the .permissionset directive and a custom attribute below it. Ilasm instead of associating the custom directive with the Decl security associates it with the type. We once again change the first byte to 28 as 8 is the number for security. When we run ildasm we get the following output.

 

  .permissionset assert = (41 42 )                                           // AB

  .custom /*0C000001:0A000001*/ instance void [vijay/* 23000001 */]a18/* 01000002 */::.ctor() /* 0A000001 */ = "e"

 

Once again ildasm passes where ilasm fails.

 

.assembly extern vijay

{

}

.class zzz implements iii

{

}

.class interface iii

{

}

.class yyy

{

.custom instance void [vijay]a18::.ctor() = (65)

}

 

In this case the  first byte is 83 as the TypeDef row is now 3 and not 2. We change it to 25 as we want row 1 and 5 is the code for the interface implementation. In this case the custom attribute comes at the bottom as.

 

.custom /*0C000001*/ (UNKNOWN_OWNER/*09000001*/ ) instance void [vijay/* 23000001 */]a18/* 01000003 */::.ctor() /* 0A000001 */ = "e"

 

The InterfaceImpl table has a number of 9. We have three more MemberRef, TypeSpec and StandAloneSig that we will do later.

 

Program49.csc

Public void DisplayAllMethods(int typeindex)

{

string vtentrystring = GetVtentryString(methodindex);

methodstring = vtentrystring;

methodstring = methodstring + CreateSpaces(spacesforrest + 2 + spacesfornested) +  "// Method begins at RVA 0x" + MethodStruct[methodindex].rva.ToString("x4");

Console.Write(methodstring);

long fileoffset = ConvertRVA(MethodStruct[methodindex].rva);

mfilestream.Seek(fileoffset , SeekOrigin.Begin);

DisplayFatFormat (NameReserved(GetString(TypeDefStruct[typeindex].name)) , NameReserved(GetString(MethodStruct[methodindex].name)) ,  methodindex );

}

}

public void DisplayFatFormat(string classname , string methodname , int methodindex)

{

DisplayInitialMethodHeader(methodindex);

DisplayMethodILCode(classname , methodname , methodindex);

}

public void DisplayInitialMethodHeader (int methodindex)

{

int tiny = mbinaryreader.ReadByte();

if ( (tiny & 0x03) == 0x03)

tinyformat = false;

else

{

Console.WriteLine(".....{0}" , tiny);

tinyformat = true;

}

mfilestream.Seek(-1,SeekOrigin.Current);

string methodstring = "";

if ( !tinyformat )

{

long where = mfilestream.Position;

short first = mbinaryreader.ReadInt16();

first12 = (short)(first & 0x0fff);

short stacksize = mbinaryreader.ReadInt16();

codesize = mbinaryreader.ReadInt32();

methodstring =  "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + "// Code size       " + codesize.ToString() + " (0x" + codesize.ToString("x") + ")\r\n";

methodstring = methodstring + CreateSpaces(spacesforrest + 2+ spacesfornested) + ".maxstack  " + stacksize.ToString();

int standalonesig = mbinaryreader.ReadInt32();

int rowstandalonesig = standalonesig  & 0x00ffffff;

Console.WriteLine(".....{0}" , standalonesig.ToString("X8"));

if (StandAloneSigStruct != null && standalonesigarray == null)

standalonesigarray = new string[StandAloneSigStruct.Length];

if ( rowstandalonesig != 0 )

{

CreateSignatureForEachType (5 , StandAloneSigStruct[rowstandalonesig ].index , rowstandalonesig);

if (standalonesigarray [rowstandalonesig ] != "")

{

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2+ spacesfornested) +  ".locals /*11" + rowstandalonesig.ToString("X6") + "*/ ";

if ((first12&0x10) == 0x10 )

methodstring = methodstring + "init (" ;

else

methodstring = methodstring + "(" ;

methodstring = methodstring + standalonesigarray[rowstandalonesig ];

methodstring = methodstring + ")";

}

}

}

else

{

mbinaryreader.ReadByte();

codesize = tiny >> 2;

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested ) +  "// Code size       " + codesize.ToString() + " (0x" + codesize.ToString("x") + ")";

if (codesize != 0)

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2+ spacesfornested) +  ".maxstack  8" ;

}

Console.WriteLine(methodstring);

}

public void CreateSignatureForEachType (byte type , int index , int row)

{

int uncompressedbyte , count , howmanybytes;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blob1 = new byte[count];

Array.Copy(blob , index + howmanybytes , blob1 , 0 , count);

if ( type == 7)

CreatePropertySignature(blob1 , row);

if ( type == 6)

CreateFieldSignature(blob1 , row);

if ( type == 5)

CreateLocalVarSignature(blob1 , row);

if ( type == 1)

CreateMethodDefSignature(blob1 , row);

if ( type == 2)

CreateMethodRefSignature(blob1 , row);

}

public void CreateLocalVarSignature (byte [] blobarray , int row)

{

int index = 0;

standalonesigarray[row] = "";

if ( blobarray[index] != 0x07)

return;

index++;

int howmanybytes,uncompressedbyte ;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + howmanybytes;

string returnstring = "";

for ( int l = 1 ; l <= uncompressedbyte ; l++)

{

string typestring = GetElementType(index , blobarray ,  out howmanybytes , 0 , "");

typestring = typestring.Replace("^",",");

int variableVindex = l - 1 ;

returnstring = returnstring + typestring +  " V_" + variableVindex.ToString() ;

if ( l != uncompressedbyte)

returnstring = returnstring + ",\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + CreateSpaces(9);

index = index + howmanybytes;

}

standalonesigarray [row] = returnstring;

}

public void DisplayMethodILCode ( string classname , string methodname  ,int methodindex)

{

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

if (GetTypeForMethod (methodindex)== 1)

Console.WriteLine(" // end of global method {0}\r\n" , methodname);

else

Console.WriteLine(" // end of method {0}::{1}\r\n" , classname , methodname);

}

string [] standalonesigarray;

int codesize ;

bool tinyformat;

int first12;

}

 

e.il

.class zzz

{

.method void xyz()

{

}

.method void xyz()

{

.locals ( int32 V_1 , int8 j)

.maxstack 2

ret

}

.method void xyz()

{

.locals init (  int8 j)

ret

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050.....2

    // Code size       0 (0x0)

  } // end of method zzz::xyz

 

  .method /*06000002*/ privatescope instance void

          xyz$PST06000002() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2054.....11000001

    // Code size       1 (0x1)

    .maxstack  2

    .locals /*11000001*/ (int32 V_0,

             int8 V_1)

  } // end of method zzz::xyz

 

  .method /*06000003*/ privatescope instance void

          xyz$PST06000003() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2064.....11000002

    // Code size       1 (0x1)

    .maxstack  8

    .locals /*11000002*/ init (int8 V_0)

  } // end of method zzz::xyz

 

 

Now is when the fun starts as we are actually moving to display or disassemble all the il code in a method. We first start off with the DisplayAllMethods methods where for the last time we make any changes. We replace the last lines with the above lines. The Method array has a field rva that tells us where the code for this method is to be found in memory.

 

We use the ConvertRVA method to tell us where this location is on disk. We then use the Seek function to move the file pointer to this position and call a method named DisplayFatFormat to write out all the il code for us. We pass this method the typename, the method name and the method index.

 

When we arrive at this function, we find that we are calling two more functions, so lets look at the first DisplayInitialMethodHeader which is simply passed the methodindex variable. The first thing we do is read the first byte of the method structure. This is the byte that tells us what is the type of method structure, tiny or large.

 

Actually we only need to look at the first bits of the first byte. If its value is 2, then method header is tiny or else for the large type is 3. As there is no third type, we get away with a simple if and else. This distinction is made mainly depending upon the size of code.

 

We have a instance variable tinyformat that is set to true if the first three bits are not 3. Now that we have read the first byte, we need to move the file pointer back one and then reread the bytes again depending upon whether it is a tiny or large format.

 

Thus the method DisplayFatFormat should have be renamed DisplayFatAndTinyFormat as it reads both. Lets start with the more complex format the fat one. This is normally the default format and applies to methods where the code size is larger than 5 bits or larger than 32 bytes.

 

Also methods that have exceptions, local variables, extra data sections and the operand stack needs to handle more than 8  entities all need the fat format. As we said before the tint format is foe the methods that really do nothing. We store in the variable where the current position of the file pointer that we will use later.

 

We also re-read the first short whose three bytes told us the type of format. We need only the first 12 bits and thus we mask off the last four bits. The top most four bits gives us a size of the header that we will see later. Remember these 12 bits are called flags even though we have only 4 flags of which the tiny and fat have already been done.

 

Thus we have two flags only to decipher. This flags is followed by a short that tells us the size of the stack. Then we have a int that is the size of the code and we immediately first add the Code Size to the methodstring variable. This is followed by the size of the stack. The codesize is not a directive but maxstack is.

 

Then a method may have variables that are local. These are enclosed within the .locals directive and have the same format as parameters, but they cannot have names like parameters but computer generated names beginning with V_ and the local variable ordinal number. The last int gives us a token which tells us where the local variables can be found.

 

For those of you with a short memory, the top byte of a token is the table number and the remaining three bytes the row number. As we have displayed the signature token, the first byte will be 11 the stand alone signature table number. If this row number is zero, then we know that the method has no local variables.

 

Earlier we made a simple mistake. Before our program started displaying stuff we calculated all the method signatures in the CreateSignatures method. Now that way was written in stone and hence he have used another way. We first check whether the array StandAloneSigStruct is not null and our standalonesigarray string array is also not null.

 

The first check is to make sure that we have some method that has local variables and the second to make sure that we create our string array standalonesigarray only once.

 

Then we check whether this method has local variables and if yes, we call the method CreateSignatureForEachType with a number 5, the type for stand alone signatures and then followed by the blob array offset and the StandAloneSig table row number rowstandalonesig to set the standalonesigarray array member to.

 

This simply sets one member of the array to a signature. We will come to the CreateSignatureForEachType method a little later. Now if the corresponding standalonesigarray array member is not null we write out the directive locals along with the signature.

 

The locals directive has one more keyword init that will call the default constructors for all the local variables. This flags has a value of 0x10 and we then write out the open and close brackets of the locals directive. This completes the fat format the tiny format is really very simple.

 

We read the first byte and then right shift it by two to remove the first two bits that were the flags. This now give us the size of the code that we write out and if the code size is not zero, the size of the stack is 8. This completes the initial reading of the method header.

 

In the CreateSignatureForEachType method, we simply call the method CreateLocalVarSignature. This is once again a signature that is easy for us as the first byte is always 7. The next byte is the count of the number of local variables that make up the signature. This is followed by the individual local variable data types that we pick up using the GetElementType method.

 

We also replace the ^ with the comma for arrays. We then need to write out the name of the variable and hence start with V_ and the loop variable l minus 1 as the count starts with 0. We then need to place a comma, followed with a enter as each of these variables needs to be on a new line with the right amount of spaces.

 

Thus this code cannot be called for the earlier signatures as then we do not have the value of the variables spacesfornested and spacesforrest. We finally set the standalonesigarray array with the returnstring variable.

 

We have the method DisplayMethodILCode that only displays some spaces and then depending upon whether it is a global method or not displays the end of the method. We could have used the method IsGlobalMethod instead of GetTypeForMethod at all times.

 

Now coming to the IL code generated by our program, we have the first function show us that it has the tiny format as the else is true and the firstbyte has a value of 2 which also gives the code a size of zero.

 

For the second two methods, the local var token starts with 0x11 and then we have the row numbers in the StandAloneSig table and not the method table. If we specify a maxstack, then ours gets used or else a default value of 8 is taken. Also for the tint format the maxstack has no place where it can be stored.

 

If we make the mistake of giving a local variable a name, ilasm removes the name and we then have to generate a standard name for it.

 

Program50.csc

public void DisplayMethodILCode ( string classname , string methodname  ,int methodindex)

{

byte [] codearray = new byte[codesize];

for ( int i = 1 ; i <= codesize ; i++)

{

codearray[i-1] = mbinaryreader.ReadByte();

Console.Write(" {0}" , codearray[i-1].ToString("X") );

}

Console.WriteLine();

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

}

 

e.il

.class zzz

{

.method void xyz()

{

.locals ( int32 V_1 , int8 j)

.maxstack 2

ret

nop

ret

nop

ret

}

}

 

.method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       5 (0x5)

    .maxstack  2

    .locals /*11000001*/ (int32 V_0,

             int8 V_1)

 2A 0 2A 0 2A

  } // end of method zzz::xyz

 

Now is when we start out book. It is in the method DisplayMethodILCode that we get our hands on the il code. This il code is available just after the initial method structure.  We need to store this code in an array codearray that we initialize to the size of the code that we have stored in the instance variable codesize.

 

We read each byte into the array and then simply display the members of the array.  What we see is the ret instruction that must be present as the last instruction of every method has a value of 0x2a. The nop instruction that behaves like most of the world has a value of zero as it is supposed to do nothing.

 

Thus after the method structure we have a series of bytes that we will have to decipher into il code. The next program does just that.

 

Program51.csc

using System.Reflection;

using System.Reflection.Emit;

 

public void abc(string [] args)

{

ReadPEStructures(args);

DisplayPEStructures();

ReadandDisplayImportAdressTable();

ReadandDisplayCLRHeader();

ReadStreamsData();

FillTableSizes();

ReadTablesIntoStructures();

DisplayTablesForDebugging();

ReadandDisplayVTableFixup();

ReadandDisplayExportAddressTableJumps();

FillArray();

FillOpCodeArray ();

CreateSignatures();

}

OpCode [] OpCodesArray; 

OpCode [] OpCodesArray1; 

public void FillOpCodeArray()

{

OpCodesArray = new OpCode[66000];

OpCodesArray1 = new OpCode[32];

FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

foreach (FieldInfo f in fields)

{

OpCode o = (OpCode) f.GetValue(null);

if ( o.Value <= 255 && o.Value >= 0)

OpCodesArray[(short)o.Value] = o;

}

}

public void DisplayMethodILCode ( string classname , string methodname  ,int methodindex)

{

byte []codearray = new byte[codesize];

for ( int i = 1 ; i <= codesize ; i++)

codearray[i-1] = mbinaryreader.ReadByte();

for ( int arrayoffset = 0 ; arrayoffset  < codesize ; )

{

int instructionbyte  = codearray[arrayoffset];

OpCode opcode;

opcode = OpCodesArray [instructionbyte];

string strings = CreateSpaces(spacesforrest+2+ spacesfornested);

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X2") + "   | ";

int sizeofinstructionanddata  = DecodeILInstrcution2( opcode , arrayoffset  , codearray , methodindex , strings);

Console.WriteLine();

arrayoffset  = arrayoffset  + sizeofinstructionanddata;

}

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

if ( GetTypeForMethod(methodindex)== 1)

Console.WriteLine(" // end of global method {0}\r\n" , methodname);

else

Console.WriteLine(" // end of method {0}::{1}\r\n" , classname , methodname);

}

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

int sizeofinstructiondata = 0;

if ( opcode.OperandType == OperandType.InlineNone)

{

Console.Write(strings);

Console.Write("{0}*/ {1}",CreateSpaces(17) ,  opcode.Name);

if ( opcode.Name == "ret" && codeindex != (codearray.Length -1) )

Console.WriteLine();

if ( opcode.Name == "throw" && codeindex != (codearray.Length -1) )

Console.WriteLine();

sizeofinstructiondata =1;

}

return sizeofinstructiondata;

}

}

 

e.il

.class zzz

{

.method void xyz()

{

.locals ( int32 V_1 , int8 j)

.maxstack 2

sub

ret

add

mul

nop

ret

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       6 (0x6)

    .maxstack  2

    .locals /*11000001*/ (int32 V_0,

             int8 V_1)

    IL_0000:  /* 59   |                  */ sub

    IL_0001:  /* 2A   |                  */ ret

 

    IL_0002:  /* 58   |                  */ add

    IL_0003:  /* 5A   |                  */ mul

    IL_0004:  /* 00   |                  */ nop

    IL_0005:  /* 2A   |                  */ ret

  } // end of method zzz::xyz

 

Finally we have some il code disassembled. When you look at the il file, we have a series of il instructions popularly  called opcodes. We have used ones like ret and nop earlier and now add, mul etc. These opcodes have one thing in common, they all take no parameters. The il world has divided the il instructions into a family depending upon the parameters or operands that they take.

 

All il instructions that have the same operand type behave in a similar manner. The il world has also given us a enum called OperandType that tells us how many different types of operands a il instruction takes. What we now need to do is handle each operand type.

 

What we cannot do is tell ourselves that we have a series of if statements that takes each opcode and figures out what the name of the opcode is and what is its operand type. We need a more generic way of handling the above problem. Lets take a look at method abc first.

 

We have introduced a new method FillOpCodeArray just before we create the method signatures. We have also defined two instance arrays OpCodesArray and OpCodesArray1 of type OpCode. These classes are from the System.Reflection namespace. The OpCode structure represents a Il instruction.

 

It has properties like Name that tells us the name of the Il instruction, OperandType that tell us the Operand types that this instruction takes and Value that tell us the byte value or number of the il instruction. For example the above program showed us that 0x2a is the value of the ret instruction, and 0 for nop.

 

Thus we now need fill up the OpCodesArray with a valid OpCode object that represents each opcode. As 0x2A represents a ret instruction, the 2a member of the OpCodesArray array should stand for the ret instruction. In the method FillOpCodeArray, this is what we do.

 

We first initialize the OpCodesArray array to a very large value of members 66000 and the second array to 32 members only. This second array will be used later. The foreach loop lets us iterate through an object. The FieldInfo class simply provides access to the metadata for field attributes.

 

The GetFields function which is part of the Type class gets us all the fields from the Type that calls it. In this case we require all the fields from the class OpCodes. Every valid opcode in the IL instruction set is a field in the OpCode class. Thus if we have 500 il instructions we will have 500 fields in the OpCode class.

 

These fields are static and read only. To be specific, the OpCode class has 221 fields in all. This way we can figure out all the fields that a certain class has. The parameter to the GetFields function allows us to get at those fields that meet certain conditions like they must be static or public etc.

 

Now that we have all the IL instructions with us in the FieldInfo array we simply use the GetValue method to give us the actual field. The array on the left is type OpCode and GetValue returns an object and hence the cast. Thus variable o now is the OpCode object where o.Name is the name of the OpCode say ret and o.Value is its byte value 0x2a.

 

Now all that we have to do is initialize the 2a member of the array with o which is what we do in the next line. We only take those opcodes that lie between 0 and 255 only. The other cases we will handle differently a little later. Thus we now have an array with all the opcode values, name and types of parameters.

 

Lets now move on to the method DisplayMethodILCode which first reads all the byte codes into the codearray array. Then we use another for loop to iterate through this array. We first pick up the first or zeroth byte from the codearray using the loop variable arrayoffset.

 

We know that this byte is an opcode value and not data and thus pick up the relevant OpCode structure that represents it from the OpCodesArray array. Thus if variable instructionbyte had a value 0x2a, then opcode would stand for the OpCode for the ret instruction.

 

We write out the initial spaces as always and then the words IL_ followed by the instruction offset within the code bytes. This is represented by the loop variable arrayoffset. We then have to add a colon some spaces and then in comments the actual opcode value, 2a for a ret.

 

Then some more spaces and a or sign | . Some instructions write some data after the or sign. Thus what we have done so far is what is the same for each instruction. We now call the method DecodeILInstrcution2 to write out the actual instruction for us.

 

We pass it the OpCode representing the instruction, the array offset from the beginning of the first byte of code arrayoffset, the entire codearray of all the bytes, the methodindex of the method and finally the initial string that we have just created of the instruction stored in the variables strings.

 

This function after writing out the entire single instruction, will then return a answer that will give us how many bytes this instruction has taken. This is important as the il instructions take up a variable number of bytes.

 

We add this return value to arrayoffset  so that the arrayoffset  variable points to the next il instruction at the start of the loop. Thus all our focus from now on will be on the DecodeILInstrcution2 method. Lets move there now.

 

In this method we have a series of if statements that handle each operand type. The first one we check for is InLineNone where we have no operands at all. Thus we use the parameter opcode and check whether its field OperandType equals the value of the enum OperandType InLineLine.

 

If we find a match we first write out the initial bytes that we are passed and then the name of the opcode. The name does not have to ret as there are a hundred opcodes that have a type InLineNone. This is why we simply use the Name property and we do have to worry about the name of the OpCode.

 

This way we do have a hundred if statements that check each opcode value and write out a name. The only problem is that only if the opcode name is ret or throw and we are not the last instruction, we should write out a enter. Thus if a ret or throw is the last instruction, a extra enter will now be written out, else it will be.

 

Also the variable sizeofinstructiondata will return the number of bytes taken up by this instruction type and for no operands the value is obviously one. This way we will handle each Operand Type. Lets sum up what we have done so far. As there are far too many IL instructions for our liking, we create an array of OpCode structures that will handle each IL instruction. What we need to know is the name and operand types that this IL instruction will take. We read each byte from the codesize array and then read the corresponding OpCode from the OpCodesArray array. Then we figure out its operand type and handle each operand type differently. Lets see it work with the next example. 

 

e.il

.class zzz

{

.method void xyz()

{

arglist

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       2 (0x2)

    .maxstack  8

    IL_0000:  /* FE   |                  */ prefix1

    IL_0001:  /* 00   |                  */ nop

  } // end of method zzz::xyz

 

Things just do not cut it. We have used a simple IL instruction arglist and for some reason we get two instructions. Why. The guys who designed the IL instruction set toke some inspiration from the Java guys who had the concept of a byte code which said that every instruction should not be larger than one byte or have a value ranging from 0 to 255.

 

Unfortunately there are too many IL instructions and hence they

designed a different way of giving them values. The first 225 or 0 to 224 IL opcodes have a direct value. From now on things change. The arglist has a value FE 00 as FE stands for Prefix 1 and there are seven such prefixes.

 

Thus we first need to check the first byte and if it is larger than F8 we have a prefix byte. FF is the last single byte instruction and is called the prefixref. Thus for two byte instructions we have to ignore the first byte and simply read the second. Thus we have to make modifications in our program to handle two byte instructions.

 

Program52.csc

public void FillOpCodeArray()

{

OpCodesArray = new OpCode[256];

OpCodesArray1 = new OpCode[32];

FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

foreach (FieldInfo f in fields)

{

OpCode o = (OpCode) f.GetValue(null);

if ( o.Value <= 255 && o.Value >= 0)

OpCodesArray[(short)o.Value] = o;

OpCodesArray1[(ushort) 0x00] = OpCodes.Arglist;

OpCodesArray1[(ushort) 0x01] = OpCodes.Ceq;

OpCodesArray1[(ushort) 0x02] = OpCodes.Cgt;

OpCodesArray1[(ushort) 0x03] = OpCodes.Cgt_Un;

OpCodesArray1[(ushort) 0x04] = OpCodes.Clt;

OpCodesArray1[(ushort) 0x05] = OpCodes.Clt_Un;

OpCodesArray1[(ushort) 0x06] = OpCodes.Ldftn;

OpCodesArray1[(ushort) 0x07] = OpCodes.Ldvirtftn;

OpCodesArray1[(ushort) 0x09] = OpCodes.Ldarg;

OpCodesArray1[(ushort) 0x0A] = OpCodes.Ldarga;

OpCodesArray1[(ushort) 0x0B] = OpCodes.Starg;

OpCodesArray1[(ushort) 0x0C] = OpCodes.Ldloc;

OpCodesArray1[(ushort) 0x0D] = OpCodes.Ldloca;

OpCodesArray1[(ushort) 0x0E] = OpCodes.Stloc;

OpCodesArray1[(ushort) 0x0F] = OpCodes.Localloc;

OpCodesArray1[(ushort) 0x11] = OpCodes.Endfilter;

OpCodesArray1[(ushort) 0x12] = OpCodes.Unaligned;

OpCodesArray1[(ushort) 0x13] = OpCodes.Volatile;

OpCodesArray1[(ushort) 0x14] = OpCodes.Tailcall;

OpCodesArray1[(ushort) 0x15] = OpCodes.Initobj;

OpCodesArray1[(ushort) 0x17] = OpCodes.Cpblk;

OpCodesArray1[(ushort) 0x18] = OpCodes.Initblk;

OpCodesArray1[(ushort) 0x1A] = OpCodes.Rethrow;

OpCodesArray1[(ushort) 0x1C] = OpCodes.Sizeof;

OpCodesArray1[(ushort) 0x1D] = OpCodes.Refanytype;

}

}

public void DisplayMethodILCode ( string classname , string methodname  ,int methodindex)

{

byte [] codearray = new byte[codesize];

for ( int i = 1 ; i <= codesize ; i++)

codearray[i-1] = mbinaryreader.ReadByte();

for ( int arrayoffset = 0 ; arrayoffset  < codesize ; )

{

int instructionbyte  = codearray[arrayoffset ];

OpCode opcode;

string strings = "";

if ( instructionbyte == 0xFE)

{

instructionbyte = codearray[arrayoffset +1];

opcode = OpCodesArray1 [instructionbyte] ;

strings = CreateSpaces(spacesforrest+2+ spacesfornested);

strings = strings + "IL_" + arrayoffset.ToString("x4") + ":  /* " + opcode.Value.ToString("X") + " | ";

arrayoffset  = arrayoffset  + 1;

}

else

{

opcode = OpCodesArray[instructionbyte];

strings = CreateSpaces(spacesforrest+2+ spacesfornested);

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X2") + "   | ";

}

int sizeofinstructionanddata  = DecodeILInstrcution2 ( opcode , arrayoffset  , codearray , methodindex , strings);

Console.WriteLine();

arrayoffset  = arrayoffset  + sizeofinstructionanddata;

}

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

if ( GetTypeForMethod(methodindex)== 1)

Console.WriteLine(" // end of global method {0}\r\n" , methodname);

else

Console.WriteLine(" // end of method {0}::{1}\r\n" , classname , methodname);

}

 

e.il

.class zzz

{

.method void xyz()

{

ret

arglist

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       3 (0x3)

    .maxstack  8

    IL_0000:  /* 2A   |                  */ ret

 

    IL_0001:  /* FE00 |                  */ arglist

  } // end of method zzz::xyz

 

Lets start with the method FillOpCodeArray. Here we have reduced the size of the first array to a reasonable 256 as the one byte opcodes will not exceed 255. Thus the array OpCodesArray will store for us all the single byte opcodes.

 

Then we have a second array OpCodesArray1 that will store the two byte opcodes. These unfortunately have to be keyed in manually and they are 30 of them. Thus we will now have to search in two arrays for our opcode. This is what we do in the method DisplayMethodILCode.

 

We read the first byte from the codearray and then check if it is the prefix1 opcode. If it is, we then pick up the second or the next byte and use this as an offset into the OpCodesArray1 array to give us the right opcode.

 

The key point is that we are reading the second byte and then picking the opcode from the second and not the first opcode array. We then set the strings variable to the initial number of spaces as well as the initial parts of the Il instruction which is the IL_ and the line number stored in the arrayoffset variable.

 

We stop at the or sign as before. As we are dealing with a 2 byte instruction, the arrayoffset variable is increased by 1. If it is  a one byte instruction, we do what we did earlier.

 

Thus when we call the method DecodeILInstrcution2, it does not care whether it is a one byte or two byte instruction set. The strings variable has a extra space for a one byte instruction set.

 

Finally we will list out all the InLineNone operand types or those that take up no parameters. We are decoding instructions depending upon the types of parameters they take. They are 146 instructions that take no operand. These are nop , break , ldarg.0 , ldarg.1 , ldarg.2 , ldarg.3 , ldloc.0 , ldloc.1 , ldloc.2 , ldloc.3 , stloc.0 , stloc.1 , stloc.2 , stloc.3 , ldnull , ldc.i4.m1 , ldc.i4.0 , ldc.i4.1 , ldc.i4.2 , ldc.i4.3 , ldc.i4.4 , ldc.i4.5 , ldc.i4.6 , ldc.i4.7 , ldc.i4.8 , dup , pop , ret , ldind.i1 , ldind.u1 , ldind.i2 , ldind.u2 , ldind.i4 , ldind.u4 , ldind.i8 , ldind.i , ldind.r4 , ldind.r8 , ldind.ref , stind.ref , stind.i1 , stind.i2 , stind.i4 , stind.i8 , stind.r4 , stind.r8 , add , sub , mul , div , div.un , rem , rem.un , and , or , xor , shl , shr , shr.un , neg , not , conv.i1 , conv.i2 , conv.i4 , conv.i8 , conv.r4 , conv.r8 , conv.u4 , conv.u8 , conv.r.un , throw , conv.ovf.i1.un , conv.ovf.i2.un , conv.ovf.i4.un , conv.ovf.i8.un , conv.ovf.u1.un , conv.ovf.u2.un , conv.ovf.u4.un , conv.ovf.u8.un , conv.ovf.i.un , conv.ovf.u.un , ldlen , ldelem.i1 , ldelem.u1 , ldelem.i2 , ldelem.u2 , ldelem.i4 , ldelem.u4 , ldelem.i8 , ldelem.i , ldelem.r4 , ldelem.r8 , ldelem.ref , stelem.i , stelem.i1 , stelem.i2 , stelem.i4 , stelem.i8 , stelem.r4 , stelem.r8 , stelem.ref , conv.ovf.i1 , conv.ovf.u1 , conv.ovf.i2 , conv.ovf.u2 , conv.ovf.i4 , conv.ovf.u4 , conv.ovf.i8 , conv.ovf.u8 , ckfinite , conv.u2 , conv.u1 , conv.i , conv.ovf.i , conv.ovf.u , add.ovf , add.ovf.un , mul.ovf , mul.ovf.un , sub.ovf , sub.ovf.un , endfinally , stind.i , conv.u , prefix7 , prefix6 , prefix5 , prefix4 , prefix3 , prefix2 , prefix1 , prefixref , arglist , ceq , cgt , cgt.un , clt , clt.un , localloc , endfilter , volatile. , tail. , cpblk , initblk , rethrow , refanytype. This is just for completeness.

 

Program53.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

int sizeofinstructiondata = 0;

if ( opcode.OperandType == OperandType.InlineI)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(8));

Console.Write(" */ {0} {1} 0x{2}", opcode.Name , CreateSpaces(3) , token.ToString("x"));

sizeofinstructiondata = 5;

}

return sizeofinstructiondata;
}
 
e.il

.class zzz

{

.method void xyz()

{

ldc.i4 14

ldc.i4 -4

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       10 (0xa)

    .maxstack  8

    IL_0000:  /* 20   | 0E000000         */ ldc.i4     0xe

    IL_0005:  /* 20   | FCFFFFFF         */ ldc.i4     0xfffffffc

  } // end of method zzz::xyz

 

The Operand Type InlineI requires a single 32 bit integer. We call the ldc.i4 instruction with a single 32 bit integer. This means that in the codearray, the instruction 0x20 will be followed by a 32 bit integer. Thus we use our trusty ToInt32 method and also use the index into the codearray passed as a parameter codeindex plus 1.

 

We have to display the 32 bit integer as a hex number but after the or sign we also have to display all the individual bytes in hex also. Thus we read the four bytes in variables b1 to b4 and display them in the same order. The size in bytes of this operand type is 5, one for the instruction byte, four for the 32 bit integer.

 

There is no special handling for negative numbers. Also there is only one instruction ldc.i4 that takes a 32 bit integer.

 

Program54.csc

if ( opcode.OperandType == OperandType.InlineI8)

{

Console.Write(strings);

long token = BitConverter.ToInt64( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

Console.Write("{0}{1}{2}{3}{4}{5}{6}{7}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

Console.Write(" */ {0} {1} 0x{2}", opcode.Name , CreateSpaces(3) , token.ToString("x"));

sizeofinstructiondata = 9;

}

return sizeofinstructiondata;

}

 

e.il

.class zzz

{

.method void xyz()

{

ldc.i8 14

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       9 (0x9)

    .maxstack  8

    IL_0000:  /* 21   | 0E00000000000000 */ ldc.i8     0xe

  } // end of method zzz::xyz

 

We now add one more if statement to handle a 64 bit integer and this operand type is InLineI8. Unlike the earlier program we have a 64 bit integer and not a 32 but integer following the ldc.i8 instruction.

 

Thus we use the ToInt64 method to read the integer and also use 8 byte variables to read and display the 64 bit integer. The size of this instruction is obviously 8. Also there is only one instruction ldc.i8 that takes this operand type.

 

Program55.csc

if ( opcode.OperandType == OperandType.ShortInlineI)

{

Console.Write(strings);

int token = codearray[codeindex+1];

Console.Write("{0}",token.ToString("X2"));

Console.Write(CreateSpaces(14));

if ( token >= 128)

token =  token - 256;

if ( opcode.Name == "unaligned." )

Console.Write(" */ {0} {1}", opcode.Name , token.ToString());

else

Console.Write(" */ {0}   {1}", opcode.Name ,  token.ToString());

sizeofinstructiondata = 2;

}

 

e.il

.class zzz

{

.method void xyz()

{

ldc.i4.s 12

ldc.i4.s 127

ldc.i4.s 128

ldc.i4.s 129

ldc.i4.s 130

unaligned. 14

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       13 (0xd)

    .maxstack  8

    IL_0000:  /* 1F   | 0C               */ ldc.i4.s   12

    IL_0002:  /* 1F   | 7F               */ ldc.i4.s   127

    IL_0004:  /* 1F   | 80               */ ldc.i4.s   -128

    IL_0006:  /* 1F   | 81               */ ldc.i4.s   -127

    IL_0008:  /* 1F   | 82               */ ldc.i4.s   -126

    IL_000a:  /* FE12 | 0E               */ unaligned. 14

  } // end of method zzz::xyz

 

The next type is the ShortInlineI that takes a 8 bit integer and not a 16 bit one as the documentation suggests. Thus we read a single byte off the codearray array and display it as a hex byte after the or sign. We then write out 14 spaces for padding and then check whether we have a plus or a minus number.

 

Anything over 128 is a negative number. Thus 128 gets displayed as –128, 129 is one less –127 and so on. Thus if variable token is larger than 128, we subtract 256 from it to give the number with a negative sign. There are only two possible instructions for this type, ldc.i4.s and unaligned. .

 

We have to writ them out separately as they are of different lengths and we need to align then token variable displayed at the end. This is displayed in decimal and not hex.

 

Program56.csc

if ( opcode.OperandType == OperandType.InlineBrTarget)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1);

string returnstring = "";

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(9) + "*/ ");

token = token + codeindex + 5;

int len = opcode.Name.Length;

returnstring = opcode.Name + " " +  CreateSpaces(9 - len) + " IL_" + token.ToString("x4");

Console.Write(returnstring);

if ( ! (codearray.Length == codeindex + 5 ))

Console.WriteLine();

sizeofinstructiondata = 5;

}

 

.class zzz

{

.method void xyz()

{

br 1

ret

br 1234567

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       11 (0xb)

    .maxstack  8

    IL_0000:  /* 38   | 01000000         */ br         IL_0006

 

    IL_0005:  /* 2A   |                  */ ret

 

    IL_0006:  /* 38   | 87D61200         */ br         IL_12d692

  } // end of method zzz::xyz

 

There are 14 instructions that take a operand type of InlineBrTarget. These are br ,brfalse,brtrue ,beq ,bge , bgt , ble , blt , bne.un , bge.un , bgt.un , ble.un , blt.un and leave. This instruction type also takes a 32 bit signed number after it that we read into the variable token.

 

As always we also need to display the individual bytes of the 32 bit signed integer. We write out the bytes, and the closing comment with spaces. This Operand type is actually a jump instruction. The 32 integer stands for a instruction that we want to transfer control to. 

 

Thus when we write br 1, we would like to jump 1 from where we are. We are at IL_0000 and this br instruction will take 5 bytes from IL_0000 to IL_0004. Thus had we wrote br 0, we would want to jump to the instruction byte Il_0005 and br 1 would takes us to the byte code at IL_0006.

 

Thus we need to find out the IL_ that we need to jump to and this we do by adding the codeindex or where we are to the token variable token and then we also add 5 as this is the amount of bytes this instruction type takes up. This is the new value of token that we display along with the IL_.

 

We also need to write out the name of the opcode and then put a certain number of spaces which is 9 minus the length of the name of the opcode. If this operand type is the last instruction it must be not preceded with a new line or else it must be.

 

If we write a negative number, we get nonsensical answers.

 

e.il

.class zzz

{

.method void xyz()

{

br IL_0007

nop

IL_0007: nop

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       7 (0x7)

    .maxstack  8

    IL_0000:  /* 38   | 01000000         */ br         IL_0006

 

    IL_0005:  /* 00   |                  */ nop

    IL_0006:  /* 00   |                  */ nop

  } // end of method zzz::xyz

 

If we write a actual label after the br instruction, then IL_0007 must be a actual label in the method. A label is any word that ends in a colon and il ilasm removes all labels from our code and puts a offset into the codearray for the br instruction instead of our label. We have to rewrite our entire code  with the labels put in fresh and hence in the output we have IL_0006 as the label instead of what we wrote out IL_0007.

 

Program57.csc

if ( opcode.OperandType == OperandType.ShortInlineBrTarget)

{

Console.Write(strings);

int token = codearray[codeindex + 1];

string returnstring = "";

Console.Write("{0}" , token.ToString("X2"));

Console.Write(CreateSpaces(15) + "*/ ");

if ( token >= 128)

{

token = 0xff - token ;

token = codeindex + 1 - token;

}

else

token = token + codeindex + 2;

int len = opcode.Name.Length;

returnstring = opcode.Name + " " +  CreateSpaces(9 - len) + " IL_" + token.ToString("x4");

Console.Write(returnstring);

if ( ! (codearray.Length == codeindex + 2 ))

Console.WriteLine();

sizeofinstructiondata = 2;

}

 

e.il

.class zzz

{

.method void xyz()

{

nop

nop

br.s 2

br.s -3

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       6 (0x6)

    .maxstack  8

    IL_0000:  /* 00   |                  */ nop

    IL_0001:  /* 00   |                  */ nop

    IL_0002:  /* 2B   | 02               */ br.s       IL_0006

 

    IL_0004:  /* 2B   | FD               */ br.s       IL_0003

  } // end of method zzz::xyz

 

The operand type ShortInlineBrTarget is similar to the one above and the only change is that we read a byte of the codearray and not a int32. Also we check for the token to be greater than 128 like earlier and subtract the 0xff from it.

 

Then we subtract token from where we are codeindex and then add 1. If it is a positive offset like it should be we add both codeindex and token like before and then add 2 as this is size of this instruction type. All else remains the same and we set sizeofinstructiondata to 2.

 

There are 14 instructions that all end in s for this Operand Type. This is the same number as the earlier type. These are br.s , brfalse.s , brtrue.s , beq.s , bge.s , bgt.s , ble.s , blt.s , bne.un.s , bge.un.s , bgt.un.s , ble.un.s , blt.un.s and leave.s

 

Program58.csc

if ( opcode.OperandType == OperandType.InlineSwitch)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(9 ));

Console.Write("*/ switch     ( ");

if ( token == 0)

Console.Write(")");

else

for ( int ii = 1 ; ii <= token ; ii++)

{

Console.Write("\r\n" + CreateSpaces(spacesforrest+2 + spacesfornested));

Console.Write(CreateSpaces(10 ) + "/*      | ");

int index = BitConverter.ToInt32( codearray , codeindex + 1 + ii*4);

b1 = codearray[codeindex+1 + ii*4];

b2 = codearray[codeindex+2 + ii*4];

b3 = codearray[codeindex+3 + ii*4];

b4 = codearray[codeindex+4 + ii*4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

int tot = codeindex+index+1 + token*4 + 4;

Console.Write(CreateSpaces(9) + "*/" + CreateSpaces(13) + "IL_{0}" , tot.ToString("x4"));

if ( ii != token)

Console.Write(",");

else

Console.Write(")");

}

sizeofinstructiondata = 5 + token*4;

}

 

e.il

.class zzz

{

.method void xyz()

{

switch ( 2 , 3, 4)

switch ( )

switch ( 2, -2)

ret

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       36 (0x24)

    .maxstack  8

    IL_0000:  /* 45   | 03000000         */ switch     (

              /*      | 02000000         */             IL_0013,

              /*      | 03000000         */             IL_0014,

              /*      | 04000000         */             IL_0015)

    IL_0011:  /* 45   | 00000000         */ switch     ( )

    IL_0016:  /* 45   | 02000000         */ switch     (

              /*      | 02000000         */             IL_0025,

              /*      | FEFFFFFF         */             IL_0021)

    IL_0023:  /* 2A   |                  */ ret

  } // end of method zzz::xyz

 

The switch instruction is the only one in the family of Operand Type InlineSwitch. As it is little complex lets first look at both the il file and the output. The switch is nothing but a series of jump statements or labels and thus implements a jump table. We have specified three jumps 2, 3 and 4.

 

These jumps are offsets after the end of the switch statement. An empty switch statement takes up 5 bytes, the first for the instruction itself, the remaining four for how many 32 bit integers we have or howmany entries in the jump table.

 

As we have 3, the total size of the switch statement is 17 bytes and thus the next valid instruction is at offset 17 or 11 hex. Thus the offsets 2, 3 and 4 and from this number 0x11 and thus we see 0x13, 0x14 and 0x15 in the jump table. The last switch starts at 0x16 or 22 decimal.

 

As it has two entries in the jump table, its size is 5 + 8, 13 and thus the ret statement is at decimal 35 or 0x23. The offsets 2 and –2 are from 0x23 and thus we get 0x25 or 0x21. Lets us see how we implement this in code. We first read into token the number of entries in our jump table.

 

We also read the individual bytes that we display. Then we write out 9 spaces and the words switch with a open bracket. If token is 0, then we have a empty switch and we close the bracket immediately. If we have a non zero value, we know that we have so many 32 bit numbers following and hence we use a for loop to display all the entire jump table using ii as the loop variable. 

 

We first write out the initial spaces on a new line as each jump table starts on a new line. We read the offset of each jump table as in int as well as individual bytes. We first display the individual bytes and then calculate the next label offset after the switch instruction.

 

We do this by adding the constant 5 for the empty switch and then the codeindex that tells us where we are and then the token itself stored in the variable index. We also multiply the token variable by 4 as it tells us how many tokens or jump table entries we have. Each jump table entry has a size of 4 bytes.

 

We write out this label and then either put a comma if it is not the last jump table entry or if it is the last a close bracket. We finally set  the size of the sizeofinstructiondata variable to 5 plus the size of the tokens.

 

Program59.csc

if ( opcode.OperandType == OperandType.InlineVar)

{

Console.Write(strings);

ushort token = (ushort)BitConverter.ToInt16(codearray , codeindex + 1);

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

Console.Write("{0}{1}" , b1.ToString("X2"),b2.ToString("X2"));

Console.Write(CreateSpaces(13) + "*/ {0}" , opcode.Name);

int len = opcode.Name.Length;

if (opcode.Name == "ldarg" || opcode.Name == "ldarga" || opcode.Name == "starg")

{

string methodattributeflags = GetMethodAttribute (MethodStruct[methodindex].flags , methodindex);

string sname = "";

if ( token > methoddefparamcount [methodindex] && methodattributeflags.IndexOf("static") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token > methoddefparamcount[methodindex]+1 && methodattributeflags.IndexOf("instance") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token == 0 && methodattributeflags.IndexOf("instance") != -1 )

sname = "0";

else

{

if ( methodattributeflags.IndexOf("static") != -1)

token++;

sname = GetParamNameForMethod ( methodindex , 0 , token);

}

Console.Write("{0}{1}" , CreateSpaces(11 - len) , sname);

}

else

Console.Write("{0}V_{1}" , CreateSpaces(11 - len) , token);

sizeofinstructiondata = 3;

}

 

e.il

.class zzz

{

.method void xyz(int32 i , int32 j , int32 k)

{

ldarg 0

ldarg 1

ldarg 2

ldarg 3

ldarg 4

ldarg 5

}

.method static void pqr(int32 i , int32 j , int32 k)

{

ldarg 0

ldarg 1

ldarg 2

ldarg 3

ldarg 4

ldarg 5

}

.method void xyz1(int32 i , int32 j , int32 k)

{

ldloc 0

ldloc 1

ldloc 2

ldloc 3

ldloc 4

ldloc 5

}

.method static void pqr1(int32 i , int32 j , int32 k)

{

ldloc 0

ldloc 1

ldloc 2

ldloc 3

ldloc 4

ldloc 5

}

}

 

.class zzz

{

.method void xyz(int32 i , int32 j , int32 k)

{

ldarg 0

ldarg 1

ldarg 2

ldarg 3

ldarg 4

}

.method static void pqr(int32 i , int32 j , int32 k)

{

ldarg 0

ldarg 1

ldarg 2

ldarg 3

ldarg 4

}

.method void xyz1(int32 i , int32 j , int32 k)

{

ldloc 0

ldloc 1

ldloc 2

ldloc 3

ldloc 4

}

.method static void pqr1(int32 i , int32 j , int32 k)

{

ldloc 0

ldloc 1

ldloc 2

ldloc 3

ldloc 4

}

}

 

  .method /*06000001*/ privatescope instance void

          xyz$PST06000001(int32 i,

                          int32 j,

                          int32 k) cil managed

  // SIG: 20 03 01 08 08 08

  {

    // Method begins at RVA 0x2050

    // Code size       24 (0x18)

    .maxstack  8

    IL_0000:  /* FE09 | 0000             */ ldarg      0

    IL_0004:  /* FE09 | 0100             */ ldarg      i

    IL_0008:  /* FE09 | 0200             */ ldarg      j

    IL_000c:  /* FE09 | 0300             */ ldarg      k

    IL_0010:  /* FE09 | 0400             */ ldarg      A_4

    IL_0014:  /* FE09 | 0500             */ ldarg      5 // ERROR: invalid arg index (>=4)

  } // end of method zzz::xyz

 

  .method /*06000002*/ privatescope static

          void  pqr$PST06000002(int32 i,

                                int32 j,

                                int32 k) cil managed

  // SIG: 00 03 01 08 08 08

  {

    // Method begins at RVA 0x2069

    // Code size       24 (0x18)

    .maxstack  8

    IL_0000:  /* FE09 | 0000             */ ldarg      i

    IL_0004:  /* FE09 | 0100             */ ldarg      j

    IL_0008:  /* FE09 | 0200             */ ldarg      k

    IL_000c:  /* FE09 | 0300             */ ldarg      A_3

    IL_0010:  /* FE09 | 0400             */ ldarg      4 // ERROR: invalid arg index (>=4)

    IL_0014:  /* FE09 | 0500             */ ldarg      5 // ERROR: invalid arg index (>=4)

  } // end of method zzz::pqr

 

  .method /*06000003*/ privatescope instance void

          xyz1$PST06000003(int32 i,

                           int32 j,

                           int32 k) cil managed

  // SIG: 20 03 01 08 08 08

  {

    // Method begins at RVA 0x2082

    // Code size       24 (0x18)

    .maxstack  8

    IL_0000:  /* FE0C | 0000             */ ldloc      V_0

    IL_0004:  /* FE0C | 0100             */ ldloc      V_1

    IL_0008:  /* FE0C | 0200             */ ldloc      V_2

    IL_000c:  /* FE0C | 0300             */ ldloc      V_3

    IL_0010:  /* FE0C | 0400             */ ldloc      V_4

    IL_0014:  /* FE0C | 0500             */ ldloc      V_5

  } // end of method zzz::xyz1

 

  .method /*06000004*/ privatescope static

          void  pqr1$PST06000004(int32 i,

                                 int32 j,

                                 int32 k) cil managed

  // SIG: 00 03 01 08 08 08

  {

    // Method begins at RVA 0x209b

    // Code size       24 (0x18)

    .maxstack  8

    IL_0000:  /* FE0C | 0000             */ ldloc      V_0

    IL_0004:  /* FE0C | 0100             */ ldloc      V_1

    IL_0008:  /* FE0C | 0200             */ ldloc      V_2

    IL_000c:  /* FE0C | 0300             */ ldloc      V_3

    IL_0010:  /* FE0C | 0400             */ ldloc      V_4

    IL_0014:  /* FE0C | 0500             */ ldloc      V_5

  } // end of method zzz::pqr1

 

In this program we work with the Operand type InlineVar that has only six instructions. These are ldarg, ldarga, starg, ldloc, ldloca and 

Stloc. Before we look at code lets us understand the ldarg instruction. A C programmer deals extensively with a area of memory that is used  to store parameters and local variables called the stack.

 

A C# or VB programmer does not bother about the stack at all. But for an IL programmer the stack is the most important part of their programming life. Thus we need a instruction that will take the value of a parameter passed to our method and place it on the stack. Thus if we look at method xyz, it has three parameters i, j , k.

 

It also has a hidden parameter called this as it is a instance method. We start with the parameter 0 passed and irrespective of the number of parameters passed, this shows up as a zero in the output. The is because the ildasm writer preferred the zero to the words this.

 

The next three ldarg instructions have a 1,2 and 3 and these show up as I, j and k, the three parameters. Thus the parameters from our point of view are numbered from 1 onwards. Normally we will not place a parameter that does not exist on the stack and thus we will never have a number after ldarg larger than the param count.

 

If we do like in the second last case, there is no error but the name of the parameter becomes A_4. The problem is that if we have a value of 5, i.e. two more, we get an error stating that the number of parameters is more than what is allowed.

 

The trick in our code is given a number after the ldarg instruction, how do we convert it into a parameter name. But before that lets move on to the second function xyz , similar to the first but being static in type and not instance. Most rules now change.

 

A static method has no this parameter passed and hence the count of parameters is from zero onwards. This is why we first see I, j, k and then as we cross the last parameter we get no error but A_3. The minute we cross two more, we get an error instead. Thus a mistake of 1 is pardoned but not of two or more.

 

If we get an error we are also told about the number of parameters plus 1 that the method takes. They are two more instructions in this family called ldarga and starg. There is another set of instructions ldloc, ldloca and stloc that deal with local variables and the stack.

 

The ld loads a value on the stack and the st ones do the reverse, set the value of the entity from what is available off the stack. These are very simple, No error checks, no bother about static or not, simple add V_ and the token number, the count starts from zero.

 

As always we write out the strings variable and then pick up the unsigned short or bytes after this operand type. The reason we say unsigned is because we have a short that is allowed only positive numbers and not negative. A positive or negative number is only how we interpret the sign bit.

 

We then write out the individual bits and then find out the length of the instruction name. The rules for the instruction that deal with parameters is different from those for local variables and the if statement takes care of that. As explained before we need to find out whether the method was static or instance and thus we again use the method GetMethodAttribute.

 

The first thing we do is check whether the token is beyond the count of parameters stored in the methoddefparamcount array. For instance variables it must be one more than static variables and we store the error message in the variable sname.

 

Then we add one more check on whether we have a token of zero and the method being instance we do not display the this but a 0. Finally we call our trusty GetParamNameForMethod method that takes the token or param number and figures out the name. The second parameter to this function is unused.

 

If the method is static we increase the token by 1 as the token count here is 0 but in our method GetParamNameForMethod the sequence number is always one for static or instance members. We finally write out the sname variable and in the else handle the local variables. The size of this instruction is 3 bytes.

 

 

Program60.csc

if ( opcode.OperandType == OperandType.ShortInlineVar)

{

Console.Write(strings);

int token = codearray[codeindex+1];

Console.Write("{0}" , token.ToString("X2"));

Console.Write(CreateSpaces(15) + "*/ {0}" , opcode.Name);

int len = opcode.Name.Length;

if (opcode.Name == "ldarg.s" || opcode.Name == "ldarga.s" || opcode.Name == "starg.s")

{

string methodattributeflags = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

string sname = "";

if ( token > methoddefparamcount[methodindex] && methodattributeflags.IndexOf("static") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token > methoddefparamcount[methodindex]+1 && methodattributeflags.IndexOf("instance") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token == 0 && methodattributeflags.IndexOf("instance") != -1 )

sname = "0";

else

{

if ( methodattributeflags.IndexOf("static") != -1)

token++;

sname = GetParamNameForMethod( methodindex , 0 , token);

}

Console.Write("{0}{1}" , CreateSpaces(11 - len) , sname);

}

else

Console.Write("{0}V_{1}" , CreateSpaces(11 - len) , token);

sizeofinstructiondata = 2;

}

 

This program deals with the ShortInlineVar type that is similar to the InlineVar. The only difference is that the six instructions have a .s following them and the token is on byte and not two. The code has been simply cut, copied and pasted. We could have merged the two into one but chose not to do so. The size of these instructions is 2 bytes and not three.

 

Program61.csc

if ( opcode.OperandType == OperandType.InlineType )

{

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

int seriouserror;

DecodeTokenIL (token , opcode , methodindex , strings , out seriouserror);

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

if ( table == 0x0a)

{

bool b = HasCustomAttribute ("MemberRef" , token );

if ( b)

{

Console.WriteLine();

DisplayCustomAttribute("MemberRef" , token, 2 + spacesforrest + spacesfornested);

}

}

if (seriouserror == 1)

sizeofinstructiondata = codearray.Length + 1;

else

sizeofinstructiondata = 5;

}

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

Console.Write(strings);

if (table == 0x01)

{

string returnstring  = "(01)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + typerefnames [token];

Console.Write(returnstring);

}

}

 

e.il

 

.assembly extern vijay

{

}

.module extern vijay1

.class zzz

{

.method void abc()

{

newarr [vijay]aa.bb/cc

newarr [vijay]aa.bb

newarr yyy

newarr [.module vijay1]cc.dd

}

}

.class public yyy

{

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       20 (0x14)

    .maxstack  8

    IL_0000:  /* 8D   | (01)000003       */ newarr     [vijay/* 23000001 */]aa.bb/* 01000002 *//cc/* 01000003 */

    IL_0005:  /* 8D   | (01)000002       */ newarr     [vijay/* 23000001 */]aa.bb/* 01000002 */

    IL_000a:  /* 8D   | (01)000004       */ newarr     yyy/* 01000004 */

    IL_000f:  /* 8D   | (01)000005       */ newarr     [.module vijay1/* 1A000001 */]cc.dd/* 01000005 */

  } // end of method zzz::abc

 

Row #2

ResolutionScope   : AssemblyRef[1]

Name              : "bb"

Namespace         : "aa"

Row #3

ResolutionScope   : TypeRef[2]

Name              : "cc"

Namespace         : ""

Row #4

ResolutionScope   : Module[1]

Name              : "yyy"

Namespace         : ""

Row #5

ResolutionScope   : ModuleRef[1]

Name              : "dd"

Namespace         : "cc"

 

In this example we start with the il file first to explain a instruction newarr that lets us create a array given a type as a parameter. This newarr instruction takes a type as a parameter and we can either specify a type ref or a type def as a parameter.

 

As we have seen before a TypeRef can be very complex and can take up a lot of bytes. These types are stored in tables and thus we come back to the concept of a token. We will now work with a set of instructions that take a token which is nothing but the top 8 bits for the table type and the remaining 24 bits for the row within the table.

 

Thus in the il file we specify a type ref, but in the exe file will go a token specifying the table and row number of the type and not the type itself. Lets look at our DecodeILInstrcution2 method first where we check for the operand type to be InlineType.

 

If it is we know that we have a token or a 32 bit number following and therefore we use the ToInt32 method to extract the token. We then call the DecodeTokenIL method to display the entire for us and we next handle a special case.

 

If the token table is MemberRef, we check whether we have a Custom Attribute on this MemberRef row number using the HasCustomAttribute method. If in the affirmative, we write out a new line and display the CustomAttribute for this MemberRef.

 

Also the DecodeTokenIL method takes a out parameter seriouserror that if is set to 1 on return means a serious error has occurred and we set the sizeofinstructiondata not to 5, the length of the instruction but beyond the last byte as need to abort dis-assembling this method.

 

Normally the assembler should catch these errors but we will show you later how you can willfully place bytes that generate these errors. The InlineType operand type has the following instructions in its repertoire - cpobj , ldobj castclass , isinst , unbox , stobj , box , newarr , ldelema , refanyval , mkrefany , initobj and sizeof.

 

To understand better we have also displayed the last 4 rows of the type table. Row 2 stands for the type bb in the namespace aa comes from the Assembly Ref row 1 or assembly vijay. Row 3 stands for a type cc that depends on row 2 as type cc is nested within type bb.

 

Row 4 stands for type yyy that actually should have been a TypeDef as we are creating it in our code but the Resolution scope is Module row 1 which is the current module. Thus all classes found in the TypeDef table can also be found in the TypeRef table.

 

Finally row 5 refers to class dd in a module ref row 1 or vijay1. To understand better we have also displayed the last 4 rows of the type table. Row 2 stands for the type bb in the namespace aa comes from the Assembly Ref row 1 or assembly vijay. Row 3 stands for a type cc that depends on row 2 as type cc is nested within type bb.

 

Row 4 stands for type yyy that actually should have been a TypeDef as we are creating it in our code but the Resolution scope is Module row 1 which is the current module. Thus all classes found in the TypeDef table can also be found in the TypeRef table. Finally row 5 refers to class dd in a module ref row 1 or vijay1.

 

In the method DecodeToken all that we do is set the variable seriouserror to0 be default and then extract the table by anding the first 24 bits by 0 and then right shifting the top 8 bits by 24. We extract the row number by masking off the higher or top 8 bits. We write out the initial string and then check for a TypeRef table code 1.

 

In this if statement we write out the table code number 01 for the TypeRef table in brackets followed by the variable token that contains only the row number. We figure out the length of the name of the opcode, put some spaces ad then call figure out the type name using the typerefnames array that contains all the TypeRef table names.

 

Program62.csc

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

Console.Write(strings);

if ( table == 0x02)

{

string returnstring = "(02)" + token.ToString("X6") + "       */ " + opcode.Name;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + typedefnames[token];

Console.Write(returnstring);

}

}

 

e.il

.class zzz

{

.method void abc()

{

newarr zzz

}

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       5 (0x5)

    .maxstack  8

    IL_0000:  /* 8D   | (02)000002       */ newarr     zzz/* 02000002 */

  } // end of method zzz::abc

 

Row #1

Name              : "<Module>"

Row #2

Name              : "zzz"

 

The next example is easier as we use the same newarr instruction and pass it a TypeDef object and not a TypeRef object. These instructions need a type and we can either pass it a TypeRef or a TypeDef object. If we specify a class zzz, then the token is 02 and the table number 000002 as we have show above.

 

In our DecodeTokenIL we simply add a if statement  that checks for the table number to be 2 and then prints the Type name form the typedefnames array and not the typerefnames array.

 

Program63.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

if ( opcode.OperandType == OperandType.InlineType || opcode.OperandType == OperandType.InlineMethod  )

{

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

int seriouserror;

}

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

if (table == 0x06) //Method

{

string returnstring = "(06)" + token.ToString("X6") + "       */ " + opcode.Name;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberDefToken (token);

Console.Write(returnstring);

}

}

public string DecodeMemberDefToken (int token)

{

string returnstring = "";

if ( token >= MethodStruct.Length)

return returnstring;

string name = NameReserved(GetString(MethodStruct[token].name));

string methodattributes = GetMethodAttribute(MethodStruct[token].flags , token );

if ( methodattributes.IndexOf("privatescope ") != -1)

name = name + "$PST06" + token.ToString("X6");

int typeindex = GetTypeForMethod(token);

returnstring = methoddeftypearray [token] + methoddefreturnarray [token] + typedefnames [typeindex] ;

returnstring = returnstring + "::" + name + "(" ;

int len = returnstring.Length + 53 + spacesforrest + spacesfornested;

string sfinal = methoddefparamarray1 [token];

returnstring = returnstring + ParamOnMultipleLines(sfinal , len )  + ")";

returnstring = returnstring + " " + "/* 06" + token.ToString("X6") + " */";

return returnstring;

}

}

 

e.il

.class zzz

{

.method void abc()

{

call instance void zzz::.ctor(int32 , int32)

call instance void zzz::pqr(int32)

}

.method public instance void .ctor(int32 , int32 )

{

}

.method public instance void pqr(int32 )

{

}

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       10 (0xa)

    .maxstack  8

    IL_0000:  /* 28   | (06)000002       */ call       instance void zzz/* 02000002 */::.ctor(int32,

                                                                                              int32) /* 06000002 */

    IL_0005:  /* 28   | (06)000003       */ call       instance void zzz/* 02000002 */::pqr(int32) /* 06000003 */

  } // end of method zzz::abc

  .method /*06000002*/ public specialname rtspecialname

          instance void  .ctor(int32 A_0,

                               int32 A_1) cil managed

  // SIG: 20 02 01 08 08

  {

    // Method begins at RVA 0x205b

    // Code size       0 (0x0)

  } // end of method zzz::.ctor

  .method /*06000003*/ public instance void

          pqr(int32 A_0) cil managed

  // SIG: 20 01 01 08

  {

    // Method begins at RVA 0x205c

    // Code size       0 (0x0)

  } // end of method zzz::pqr

 

In this example we deal with the method table. We add one more operand type InlineMethod to the if statement for the DecodeILInstrcution2 method but call the same DecodeTokenIL method. Here we add one more if statement for table type 6 or the method table. In this if statement we simply do what we mostly did in the earlier two cases but also call the method DecodeMemberDefToken.

 

The principle in the token examples is that we are given a row number of a table and need to display a string representing that row entity. If it is a TypeDef then we need to display the name of the type in certain manner. In this specific case we need to display the entire method in a certain format.

 

We start with the type of the method instance or static , then the return type, the full name of the method and the parameters passed without parameter names. This was something we did when displayed the method definition and the DecodeMemberDefToken method does something similar.

 

We start with checking that the row number or token can never be larger than the Method table and once again figure out the name and attributes of the methods. Most of this code will sound familiar. We add the string PST06 if the methods attribute is privatescope and then we find out the type that this method belongs to.

 

We next concatenate the type of the method stored in the methoddeftypearray array using the row number variable token as the index, then the return value stored in the methoddefreturnarray and finally the type that this method called comes from stored in the typedefnames array.

 

This is why we need the type the method belongs to. We then add two colons and the name and a open bracket. Finally we need the parameters to this method which is stored in the  methoddefparamarray1 array as this array only contains the types of the parameters, not th parameter names.

 

These parameters are to be placed on multiple lines and 43 is what we figured out was the other stuff that gets displayed. We end with the Method table row number. We have called the call instruction twice, once with a constructor and the second time method pqr defined in the same type. Thus calling a method which is defined by us in our code places a table type 6 in the token.

 

Both cases the table type is 06 and we display the entire method call plus parameters. The other instructions that make up this Operand type are jmp , callvirt , newobj , ldftn and ldvirtftn.

 

Program64.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

if ( opcode.OperandType == OperandType.InlineType || opcode.OperandType == OperandType.InlineMethod || opcode.OperandType == OperandType.InlineSig  )

{

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

}

}

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

int table = (int)(token & 0xff000000);

table = table >> 24;

int originaltoken = token;

token = token & 0x00ffffff;

 

if ( table == 0x11) //StandAlonesig

{

int b1 = token & 0xff;

int b2 = (token & 0xff00) >> 8;

int b3 = (token & 0xff0000) >> 16;

string returnstring =  b1.ToString("X2") + b2.ToString("X2") + b3.ToString("X2") + table.ToString("X2");

returnstring = returnstring + "         */ " + opcode.Name + "      ";

string dummy = CreateSignatureForCalli (token);

int len = opcode.Name.Length;

if ( dummy == "error")

returnstring = "(" + table.ToString("X2") + ")" + token.ToString("X6") + "       */ " + opcode.Name + CreateSpaces(11-len) + "<unknown token type 0x" + table.ToString("X2")+">" ;

else

returnstring = returnstring + dummy + " /*" + originaltoken.ToString("X8") + "*/";

Console.Write(returnstring);

}

}

public string CreateSignatureForCalli(int row)

{

int aa = -1;

int howmanybytes,uncompressedbyte , count;

if ( row >= StandAloneSigStruct.Length)

return "error";

int index = StandAloneSigStruct[row].index ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blobarray = new byte[count];

Array.Copy(blob , index + howmanybytes , blobarray , 0 , count);

if ( row == aa)

{

for ( int i = 0 ; i < count ; i++)

Console.Write("{0} " , blobarray[i].ToString("X"));

Console.WriteLine();

}

string types = DecodeFirstByteofMethodSignature ( blobarray[0] , row);

index = 1;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

count = uncompressedbyte;

index = index + howmanybytes ;

string returnstring =types;

int dummyint1;

returnstring = returnstring + GetElementType( index , blobarray , out dummyint1 , 0 , "");

index = index + dummyint1;

returnstring = returnstring + "(";

for ( int l = 1 ; l <= count ; l++)

{

if ( blobarray[index] == 0x41 )

{

returnstring = returnstring + "...,";

index = index + 1;

}

string dummy = GetElementType(index , blobarray , out howmanybytes ,0 , "");

returnstring = returnstring + dummy ;

if ( l != count )

returnstring = returnstring + ",";

index = index + howmanybytes;

}

if ( index < blobarray.Length && blobarray[index] == 0x41)

returnstring = returnstring +  ",..." ;

returnstring = returnstring + ")";

return returnstring;

}

 

e.il

.class zzz

{

.method void abc()

{

calli vararg int32 ( int64,  int8 , ...)

}

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       5 (0x5)

    .maxstack  8

    IL_0000:  /* 29   | 01000011         */ calli      vararg int32(int64,int8,...) /*11000001*/

  } // end of method zzz::abc

 

The next instruction belongs to the Operand Type InlineSig. Therefore we add one more operand type in the if statement for the DecodeILInstrcution2 and as always call the DecodeTokenIL method with a table type 0x11 which is for the table StandAloneSig. All signatures are stored in the metadata blob heap for us.

 

These signatures are accessed by reading a metadata table as there is some column that contains there offset in the blob. There are however two cases where we will find a signature in the blob and no column in any table will contain an offset to them.

 

Each time we have local variables in a method, a row gets created in the standalonesig table. This table has only one column. The second case that interests us is when we have a calli instruction. In this case the token generated will contain the table type 0x11 and the row will contain the call site signature for a pointer to a function.

 

These pointer signatures describe the calling convention, we have used unmanaged stdcall, then we have the return type and the parameters data types only along on the same line.

 

There is no name for the function call as these are pointer to functions and they call into any method provided the above signature is the same as that of the method called indirectly through the pointer. Obviously it is our responsibility to push the address of the function on the stack first.

 

We store in the DecodeTokenIL method the original token that contained the table name and row number in a variable originaltoken first before removing the table name from the token variable. The format for this operand type is a little different. We display the row numbers as bytes first and then the table number without brackets.

 

Earlier it was the other way around. Then we have a method CreateSignatureForCalli that gives us the pointer to method signature. After this is display an error message if the above functions returns an error and then standalonesig table row number in comments.

 

Lets us now figure out how to generate the stand alone signature in the method CreateSignatureForCalli. We start as always by making sure that we have a valid row number in the standalonesig table or else we return an error.

 

We have explained all of this signature earlier and thus will rush thorough the entire explanation. The field index is an offset into the blob array and we first find out the length of this signature stored at the start. Then we copy this signature into an array blobarray.

 

The first real byte after the count is the calling convention that we read using our earlier method DecodeFirstByteofMethodSignature. Then we read the count of the number of parameters and use the index variable as an offset into the signature.

 

We use the GetElementType to get at the return value and then in a loop get each of the parameters without the names of the parameters that are not stored anywhere and all these parameters are on the same line. We also have to add the sentinel byte as shown in the il file.

 

Program65.csc

e.il

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

if ( table == 0x1b) // Typespec

{

string returnstring =  "("  + table.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

string types =  CreateSignatureForTypeSpec (token);

types = types.Replace("^",",");

returnstring = returnstring + CreateSpaces(11-len) + types ;

Console.Write(returnstring);

}

}

public string CreateSignatureForTypeSpec(int row)

{

string returnstring = "";

int howmanybytes,uncompressedbyte , count;

int index = TypeSpecStruct[row].signature ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blobarray = new byte[count];

Array.Copy(blob , index + howmanybytes , blobarray , 0 , count);

returnstring = GetElementType( 0 , blobarray , out howmanybytes ,0 , "");

return returnstring;

}

 

.class zzz

{

.method void abc()

{

castclass  valuetype yyy

}

}

.class yyy

{

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       5 (0x5)

    .maxstack  8

    IL_0000:  /* 74   | (1B)000001       */ castclass  valuetype yyy/* 01000002 */

  } // end of method zzz::abc

 

We simply add one more table type 0x1b or the Typespec table to the DecodeTokenIL method. We display the table name in brackets and follow this with the row number bytes and call a method CreateSignatureForTypeSpec that reads the signature from the TypeSpec table.

 

This method is very simple as all that it does is copy the bytes as before into the blobarray array and then read the single type stored in the signature. The point again is that there is only a single type stored and not a signature.

 

If we look at the two bytes we find 0x11 the element type for a value type followed by 9 the token. Like the standalonesig table the typespec also has only one column. Normally array operations use the TypeSpec but we have used the castclass instruction that lets us cast types.

 

The TypeSpec token can be used with any IL instruction that takes a Typedef or a TypeRef token like castclass, cpobj, initobj, isinst, ldelema, ldobj, mkrefany, newarr, refanyval, sizeof, stobj, box and unbox.

 

Program66.csc

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

if (table == 0x0a) //MemberRef

{

string returnstring = "(0A)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberRefToken(token , methodindex , opcode);

Console.Write(returnstring);

}

}

public string DecodeMemberRefToken (int token , int methodindex , OpCode opcode)

{

string returnstring = "";

if ( token >= MemberRefStruct.Length )

return " $MR$" + token.ToString("X2") + "() /* 0A0000" + token.ToString("X2") + " */";

int row = MemberRefStruct[token].clas;

string codedindextable = GetMemberRefParentCodedIndexTable (row);

int codedindexrow = row >> 3;

string initialstring = "";

if ( codedindextable == "ModuleRef")

{

initialstring = methodreftypearray[token] + methodrefreturnarray[token] + " ";

string name = NameReserved(GetString(ModuleRefStruct[codedindexrow].name));

initialstring = initialstring + "[.module " + name + "/* 1A" + codedindexrow.ToString("X6") + " */]" ;

}

if ( codedindextable == "TypeSpec") //arrays.exe

{

string returnarray = methodrefreturnarray[token];

string typeplusreturn  = methodreftypearray[token] + returnarray;

string types = CreateSignatureForTypeSpec(codedindexrow);

types = types.Replace("^",",");

initialstring = typeplusreturn  + " " + types ;

}

else if ( codedindextable == "MethodDef")

{

initialstring = methodreftypearray[token] + methodrefreturnarray[token] + " ";

int typeindex = GetTypeForMethod(codedindexrow);

initialstring = initialstring + typedefnames[typeindex];

}

else if ( codedindextable == "TypeRef")

{

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

initialstring = initialstring + typerefnames[codedindexrow];

}

string methodparmarraystring = methodrefparamarray1 [token];

string nameplusparams = "";

if ( methodparmarraystring != null)

{

nameplusparams =  NameReserved(GetString(MemberRefStruct[token].name))  + "(";

int len = 55 + spacesforrest+spacesfornested + nameplusparams.Length + initialstring.Length;

nameplusparams = nameplusparams + ParamOnMultipleLines(methodparmarraystring,len);

nameplusparams = nameplusparams + ")";

}

else

nameplusparams =  NameReserved(GetString(MemberRefStruct[token].name))  ;

returnstring = initialstring + "::" +  nameplusparams + " /* 0A" + token.ToString("X6") + " */";

return returnstring;

}

public string GetMemberRefParentCodedIndexTable(int memberrefparentcodedindex)

{

string returnstring = "";

memberrefparentcodedindex = memberrefparentcodedindex & 0x07;

if ( memberrefparentcodedindex == 1 )

returnstring = "TypeRef";

if ( memberrefparentcodedindex == 2 )

returnstring = "ModuleRef";

if ( memberrefparentcodedindex == 3 )

returnstring = "MethodDef";

if ( memberrefparentcodedindex== 4 )

returnstring = "TypeSpec";

return returnstring;

}

 

e.il

.assembly extern vijay

{

}

.module extern vijay1

.class zzz

{

.method void pqr()

{

}

.method void abc()

{

call instance void [vijay]zzz::pqr2()

call instance void [vijay]zzz::pqr1()

newobj     instance void int32[0...,0...]::.ctor(int32,int32)

call instance void [.module vijay1]::pqr2()

}

}

.class public yyy

{

.method void pqr()

{

}

}

 

  .method /*06000002*/ privatescope instance void

          abc$PST06000002() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2051

    // Code size       20 (0x14)

    .maxstack  8

    IL_0000:  /* 28   | (0A)000001       */ call       instance void [vijay/* 23000001 */]zzz/* 01000002 */::pqr2() /* 0A000001 */

    IL_0005:  /* 28   | (0A)000002       */ call       instance void [vijay/* 23000001 */]zzz/* 01000002 */::pqr1() /* 0A000002 */

    IL_000a:  /* 73   | (0A)000003       */ newobj     instance void int32[0...,0...]::.ctor(int32,

                                                                                             int32) /* 0A000003 */

    IL_000f:  /* 28   | (0A)000004       */ call       instance void [.module vijay1/* 1A000001 */]::pqr2() /* 0A000004 */

  } // end of method zzz::abc

 

Row #1

Class             : TypeRef[2]

Name              : "pqr2"

Row #2

Class             : TypeRef[2]

Name              : "pqr1"

Row #3

Class             : TypeSpec[1]

Name              : ".ctor"

Row #4

Class             : ModuleRef[1]

Name              : "pqr2"

 

In this example we deal with the table type 0xa or MemberRef. Thus in the DecodeTokenIL we add a if statement that checks for table type 0xa and then calls a method DecodeMemberRefToken to handle the member ref table.

 

We start with checking whether we have a row larger than the length of the MemberRef table and if so we return a string beginning with $MR$ and the row number. The clas field of the MemberRef table is a complex coded index that can take up to four table types. These are TypeRef, ModuleRef, TypeSpec and Method.

 

The specs allow for a fifth table TypeDef but have not given us its coded index value. Thus we use the method GetMemberRefParentCodedIndexTable to give us one of these four tables as a string and then right shift the coded index to give us the relevant row number in that table.

 

For the first time we have not used a function to do this. The member ref table stores references to each method that we make that do not lie within the type the method that makes the member reference lies in.

 

Lets look at the first coded index table ModuleRef. This happens when we call method pqr2 in the module vijay1 that is external. The output also informs us that row 4 of the member ref table is what we have displayed.

 

We start with writing out the type of the method and the return value from the methodref arrays. Then we get the name of the method from the ModuleRef table and  the variable codedindexrow is an offset into this table.

 

We write out the directive .module and then the module ref table number in comments. Once we are done with this we need the parameters passed to this function without the param names and this is stored in the methodrefparamarray1 array.

 

We now need to find out the length of spaces if the parameters are on more than one line and this is done by using the same principles enumerated above. We end by writing out the member ref table row number. Now lets look at the next coded index table type TypeSpec.

 

This occurs when we have used a IL instruction like newobj that creates a value type for us and has a array type as that type. The newobj instruction in our case calls the constructor  with two ints and is of type array type int32.

 

This makes the coded index as TypeSpec and row 3 of the MemberRef table confirms what we are saying. Then lets look at the next coded index type TypeRef that happens when we call a method defined somewhere else in some other assembly.

 

The method pqr1 is in assembly vijay and is present in row 2 of the MemberRef table and the clas field is a TypeRef row 2. This in turn points to an assembly ref row 1. The class zzz is represented by the second row of the TypeRef table and the Assembly Ref table row 1 is the assembly vijay.

 

The code of this if statement is easy as all that we do is concatenate the type, return and the name of the type from the typerefnames array. The only problem is that we could not simulate the last coded index table Method. Thus we have a extra call to the method pqr2.

 

We then found out that the first row of the member ref table has the following bytes 11 00 38 00. This is done by setting the debug variable to true. We search for these bytes in the e.dll file and change the first byte to 0x0b.

 

This is because the first 3 bits represent the coded index and a value of 3 represents the table MethodDef. Now we want row 1 to be method row which is method pqr. When we run ildasm on e.dll we see the first method call as.

 

(0A)000001       call       instance void zzz/* 02000002 */::pqr2() /* 0A000001 */

 

The member ref row number is 1 which specifies a coded index of Method and row 1 of the method table. The name of the method ref is pqr2 and the Method row 1 says that the name of the method is pqr and its type is class zzz.

 

Row 1

Class             : Method[1]

Name              : "pqr2"

 

Thus in our code we take the type and return value from the member ref array and then calculate the type that the Method falls under. This type is used for figuring out the name of the Type to be placed before the method.

 

The only problem is that when we do the same thing by ilasm, this assembler prefers specifying a TypeRef instead of a Method to figure out the class name. This TypeRef points to a class zzz though the module coded index row 1. Thus we had to simulate it by actually changing the bytes on disk.

 

The point is that we want to know the class name and there are two ways of doing it, one using the coded index of Method and two by using a TypeRef that in turn uses a reference to the Module table that can have only one row and has the class name as zzz even though the same class name is found in the TypeDef table.

 

Thus even though we have told you that the TypeRef table has classes they are contained somewhere else, classes that we create can also be present in the TypeRef table. These classes will have a coded index of module and the module directive only get written if it is a external module.

 

Program67.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

if ( opcode.OperandType == OperandType.InlineType || opcode.OperandType == OperandType.InlineMethod || opcode.OperandType == OperandType.InlineSig || opcode.OperandType == OperandType.InlineField )

{

}

}

 

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror)

{

seriouserror = 0;

if ( table == 0x04)

{

string returnstring =  "("  + table.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

Console.Write(returnstring);

returnstring = fieldparamarray [token];

int len = opcode.Name.Length;

Console.Write(CreateSpaces(11-len));

Console.Write(returnstring);

int typeindex = GetTypeForField (token);

string finalstring = typedefnames[typeindex];

Console.Write(" {0}::" , finalstring , typeindex.ToString("X6"));

string name = NameReserved(GetString(FieldStruct[token].name));

if (fieldflagsarray[token].IndexOf("privatescope ") != -1)

name = name + "$PST04" + token.ToString("X6");

name = name + " /* 04" + token.ToString("X6") + " */";

Console.Write(name);

}

}

public int GetTypeForField (int fieldrow)

{

int ii = 0;

for ( ii = 1 ; ii < TypeDefStruct.Length - 1  ; ii++)

{

int start = TypeDefStruct[ii].findex;

int end = TypeDefStruct[ii+1].findex - 1;

if ( fieldrow >= start && fieldrow <= end)

return ii;

}

return ii;

}

 

e.il

.class zzz

{

.field int32 i

.method void abc()

{

ldfld int32 zzz::i

}

}

 

  .method /*06000001*/ privatescope instance void

          abc$PST06000001() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       5 (0x5)

    .maxstack  8

    IL_0000:  /* 7B   | (04)000001       */ ldfld      int32 zzz/* 02000002 */::i$PST04000001 /* 04000001 */

  } // end of method zzz::abc

 

We now deal with a field. We start as always when we are dealing with a new Operand Type InlineField by adding it to the if statement to the DecodeILInstrcution2 method.

 

We then move on to the DecodeTokenIL method and here check for a table code of 4. We first write out the table name in brackets and then the row number and the name of the opcode. These can be one of six, ldfld , ldflda , stfld , ldsfld , ldsflda and stsfld.

 

We then need the data type of the field stored in the wrongly named array fieldparamarray followed by some spaces. We then need to write out the type that this field belongs to. Like we had a method GetTypeForMethod we also have a GetTypeForField method.

 

The only difference is that instead of looking at the field mindex we look at the field findex. Nothing else changes. We use the typedefnames array to get at the type name and then write out the name of the field. As always we look at the privatescope attribute before we do. Thus fields tokens are very simple to work with unlike method tokens.

 

Program68.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

int sizeofinstructiondata = 0;

if ( opcode.OperandType == OperandType.InlineType || opcode.OperandType == OperandType.InlineMethod || opcode.OperandType == OperandType.InlineSig || opcode.OperandType == OperandType.InlineField || opcode.OperandType == OperandType.InlineTok )

{

}

return sizeofinstructiondata;

}

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror )

{

seriouserror = 0;

if ( table == 0x04)

{

string returnstring =  "("  + table.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

Console.Write(returnstring);

int typeindex = GetTypeForField(token);

if ( opcode.Name == "ldtoken" )

Console.Write("    field ");

else

{

int len = opcode.Name.Length;

Console.Write(CreateSpaces(11-len));

}

Console.Write(fieldparamarray[token]);

string finalstring = typedefnames[typeindex];

Console.Write(" {0}::" , finalstring , typeindex.ToString("X6"));

string name = NameReserved(GetString(FieldStruct[token].name));

if (fieldflagsarray[token].IndexOf("privatescope ") != -1)

name = name + "$PST04" + token.ToString("X6");

name = name + " /* 04" + token.ToString("X6") + " */";

Console.Write(name);

}

if (table == 0x06) //Method

{

string returnstring = "(06)" + token.ToString("X6") + "       */ " + opcode.Name;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberDefToken(token , opcode);

Console.Write(returnstring);

}

if (table == 0x0a) //MemberRef

{

string returnstring = "(0A)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberRefToken(token , methodindex , opcode );

Console.Write(returnstring);

}

}

public string DecodeMemberDefToken (int token , OpCode opcode)

{

string returnstring = "";

if ( token >= MethodStruct.Length)

return returnstring;

string name = NameReserved(GetString(MethodStruct[token].name));

string methodattributes = GetMethodAttribute(MethodStruct[token].flags , token );

if ( methodattributes.IndexOf("privatescope ") != -1)

name = name + "$PST06" + token.ToString("X6");

int typeindex = GetTypeForMethod(token);

if ( opcode.Name == "ldtoken")

returnstring = "method ";

returnstring = returnstring + methoddeftypearray[token] + methoddefreturnarray[token] + typedefnames[typeindex] ;

}

 

public string DecodeMemberRefToken (int token , int methodindex , OpCode opcode )

{

string returnstring = "";

//Console.WriteLine(".......{0}" , token.ToString("X"));

if ( token >= MemberRefStruct.Length )

return " $MR$" + token.ToString("X2") + "() /* 0A0000" + token.ToString("X2") + " */";

int row = MemberRefStruct[token].clas;

string codedindextable = GetMemberRefParentCodedIndexTable(row);

int codedindexrow = row >> 3;

string initialstring = "";

else if ( codedindextable == "TypeRef")

{

if ( opcode.Name == "ldtoken")

{

int typeindex1 = 0;

string typename = NameReserved(GetString(TypeRefStruct[codedindexrow].name));

string typenamespace = NameReserved(GetString(TypeRefStruct[codedindexrow].nspace));

for ( int typecnt = 1 ; typecnt < TypeDefStruct.Length ; typecnt++)

{

if ( typename == NameReserved(GetString(TypeDefStruct[typecnt].name)) && typenamespace == NameReserved(GetString(TypeDefStruct[typecnt].nspace)))

{

typeindex1 = typecnt;

//Console.WriteLine("...{0}" , typename , );

break;

}

}

int start , startofnext;

start =  TypeDefStruct[typeindex1].findex ;

if ( typeindex1 == (TypeDefStruct.Length - 1) )

startofnext= FieldStruct.Length;

else

startofnext = TypeDefStruct[typeindex1+1].findex ;

bool found = false;

for ( int fieldindex = start ; fieldindex < startofnext ; fieldindex++)

{

string name = NameReserved(GetString(MemberRefStruct[token].name));

if ( name == NameReserved(GetString(FieldStruct[fieldindex].name)))

{

found = true;

break;

}

}

if ( found )

initialstring = "field ";

else

initialstring = "method ";

}

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

initialstring = initialstring + typerefnames[codedindexrow];

//Console.WriteLine("......{0} {1}" , codedindexrow , typerefnames[codedindexrow] );

}

else if ( codedindextable == "TypeDef")

{

if ( opcode.Name == "ldtoken")

initialstring = "field ";

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

initialstring = initialstring + typedefnames[codedindexrow];

}

return returnstring;

}

public string GetMemberRefParentCodedIndexTable(int memberrefparentcodedindex)

{

string returnstring = "";

memberrefparentcodedindex = memberrefparentcodedindex & 0x07;

if ( memberrefparentcodedindex == 0 )

returnstring = "TypeDef";

if ( memberrefparentcodedindex == 1 )

returnstring = "TypeRef";

if ( memberrefparentcodedindex == 2 )

returnstring = "ModuleRef";

if ( memberrefparentcodedindex == 3 )

returnstring = "MethodDef";

if ( memberrefparentcodedindex== 4 )

returnstring = "TypeSpec";

return returnstring;

}

 

e.il

.assembly extern vijay

{

}

.class zzz

{

.field public int32 ii

.field public int32 jj

.method public void abc()

{

ldtoken    [vijay]XmlSerializationHowTo.PurchaseOrder

ldtoken    zzz

ldtoken    valuetype yyy/* 01000004 */

ldtoken    method instance void zzz::abc()

ldtoken    field int32 ii

ldtoken    field int32 zzz::ii

ldtoken    field int32 yyy::jj

ldtoken    method instance int32 [vijay]qqq::hhh()

}

.method void abc1()

{

call instance int32 [vijay]qqq::hhh()

castclass  valuetype yyy

}

}

.class public yyy

{

.field public int32 jj

}

 

  .method /*06000001*/ public instance void

          abc() cil managed

  // SIG: 20 00 01

  {

    // Method begins at RVA 0x2050

    // Code size       40 (0x28)

    .maxstack  8

    IL_0000:  /* D0   | (01)000002       */ ldtoken    [vijay/* 23000001 */]XmlSerializationHowTo.PurchaseOrder/* 01000002 */

    IL_0005:  /* D0   | (02)000002       */ ldtoken    zzz/* 02000002 */

    IL_000a:  /* D0   | (1B)000001       */ ldtoken    valuetype yyy/* 01000003 */

    IL_000f:  /* D0   | (06)000001       */ ldtoken    method instance void zzz/* 02000002 */::abc() /* 06000001 */

    IL_0014:  /* D0   | (0A)000001       */ ldtoken    field int32 '<Module>'/* 02000001 */::ii /* 0A000001 */

    IL_0019:  /* D0   | (0A)000002       */ ldtoken    field int32 zzz/* 01000004 */::ii /* 0A000002 */

    IL_001e:  /* D0   | (0A)000003       */ ldtoken    field int32 yyy/* 01000003 */::jj /* 0A000003 */

    IL_0023:  /* D0   | (0A)000004       */ ldtoken    method instance int32 [vijay/* 23000001 */]qqq/* 01000005 */::hhh() /* 0A000004 */

  } // end of method zzz::abc

 

This program deals with the instruction ldtoken that has a operand type of InlineTok. This is the only instruction that this operand type has and hence we add one more condition in the DecodeILInstrcution2 method. We will explain the extra code added in the table type 4 a little later.

 

The ldtoken instruction takes a token and places its runtime representation on the stack. The ldtoken instruction cannot handle all the table types and the ones it can handle we give you an example. The rest are disallowed and we do not display the error message when we give a wrong table type.

 

The first three ldtoken instructions deal with the TypeRef, TypeDef and TypeSpec tables. There is no change at all for these table types. The fourth table is the MethodDef table. We are calling a method abc from the type zzz. The only change in syntax is that we have to add the word method at the very start or else we get a error.

 

Thus in the method DecodeMemberDefToken that handles a method, we have to at the very start check if the opcode name is ldtoken. If it is we set the returnstring that was null to method. We finally were able to show you an example where the coded index table name was Typedef.

 

We have added a if statement to the GetMemberRefParentCodedIndexTable where if the byte value is 0, we return a table type of TypeDef. If we look at the 5th ldtoken, we are writing the words field , its data type and the field name ii. We are on purpose not specifying the type and it is assumed to be zzz.

 

When such a case happens, the coded index table name in the TypeRef table is TypeDef and if the opcode is ldtoken we add the word field at the beginning. We then use the methodref arrays for the type and return value and the typedefnames array for the type name.  Now comes the problem case.

 

In the next two ldtoken instructions we are referring to two fields from the class zzz and yyy. In these case the coded index table is TypeRef. The problem is that we need to figure out whether to write the words field or method as the next ldtoken is used with a MethodRef and this has the word method preceding it.

 

How do we decide whether the entity following is a field or a method. Lets look at how our code is handling it. We start by checking whether the opcode name is ldtoken. We now that the TypeRef struct will store the name and namespace of the entity that contains the type.

 

Thus for the first field the TypeRef table will contain the class name zzz and for the second class yyy. Thus we now know the type from which the field or method comes from. We scan the type def table from start to end and find that name and namespace that we got from the type ref table.

 

The minute we find a match, we break out of that loop and typeindex contains the type name of the type that was stored in the TypeRef table. Now we need to figure out whether it is a field or a method. We now find out the first and last field owned by the type stored in the variable typeindex.

 

We do this like before and also store the starting and ending field numbers in start and startofnext. We have simply copied this code from the earlier examples. We now a for loop scan these row numbers in the field table for a name matching the name we found in the MemberRef table row number specified by the token variable.

 

If a match is found we set the found variable to true. We then depending upon the value of this variable found decide to start the string initialstring to field or method. We are assuming that if the field name is not found in the Field table, it must be a method. A better way would be to also scan the member ref table also.

 

We are not scanning the entire field table, but only those that are owned by our type. There was one specific we could not show you and that was the table type 4 for a field. The compiler generates the il code and the C# compiler uses the ldtoken instruction with a table type of 4.

 

When we give ilasm the same ldtoken instruction, it converts it to a member ref table type instead. Thus if we meet with a field type 4 and the instruction is ldtoken, we first write out words field and then in the else take care of the spaces as before. Thus the only change is the word field to be added and adjustment of spaces.

 

Program69.csc

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror )

{

seriouserror = 0;

int originaltoken = token;

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

//if ( opcode.Name == "ldtoken")

//Console.WriteLine("........");

if ( table == 4 && token > FieldStruct.Length )

{

Console.Write("     ********* ERROR DISASSEMBLING THE METHOD IL CODE ***********");

seriouserror = 1;

return ;

}

if ( table == 1 && token > TypeRefStruct.Length )

{

Console.Write("     ********* ERROR DISASSEMBLING THE METHOD IL CODE ***********");

seriouserror = 1;

return ;

}

Console.Write(strings);

if ( table == 0)

{

Console.Write("({0}){1}       */ {2}{3}0x{4} " , table.ToString("X2") ,token.ToString("X6"), opcode.Name, CreateSpaces(11-opcode.Name.Length) , token.ToString("X2") );

}

if ( table >= 60 || table < 0)

{

byte dummybyte = (byte) table;

string returnstring =  "("  + dummybyte.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

Console.Write(returnstring);

int len = 31 - returnstring.Length;

Console.Write(CreateSpaces(len));

Console.Write("<unknown token type 0x" + dummybyte.ToString("x2") + ">");

}

if (table == 0x01)

{

string returnstring  = "(01)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + typerefnames[token];

Console.Write(returnstring);

}

 

This program can be ignored as it deals with error checks. There are a series of classes that generate the il code for you. This is the class ILGenerator. We are allowed to place any bytes into the code stream. Thus the examples we went through had all sorts of errors and we handled each one.

 

Thus if the table type is 1, the Typeref table, the token or the table row in this case can never be larger than the rows of the TypeRef struct. If this happens, we display a certain error and it is here that we set the variable seriouserror to 1 and then return.

 

When we come back, we need to abort this method only and thus we set the code count beyond the length of the code array and quit out of this method.

 

Program60.csc

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings)

{

if ( opcode.OperandType == OperandType.InlineR)

{

Console.Write(strings);

double token = BitConverter.ToDouble( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

Console.Write("{0}{1}{2}{3}{4}{5}{6}{7}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

Console.Write(" */ {0} {1} ", opcode.Name , CreateSpaces(3));

DisplayR8 (token, codearray , codeindex);

sizeofinstructiondata = 9;

}

 

public void DisplayR8(double token , byte [] codearray , int codeindex)

{

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

string doubles = token.ToString();

int pos = doubles.IndexOf("E-");

int d2 = 0;

if ( pos != -1)

{

string d1 = doubles.Substring(pos+2);

d2 = Convert.ToInt32(d1);

}

if ( doubles.IndexOf("Infinity") != -1 || doubles.IndexOf("NaN") != -1 || d2 >= 308)

Console.Write("({0} {1} {2} {3} {4} {5} {6} {7})",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

else if ( token == 0 && b8 == 0x80)

Console.Write("-0.0" );

else if ( token == 0 && b8 == 0x00)

Console.Write("0.0" );

else

{

sss s1 = new sss();

string ss = s1.ReturnStringForR8 (token , 0);

Console.Write(ss);

}

}

}

 

e.il

.class zzz

{

.method public void abc()

{

ldc.r8 12.6

ldc.r8 12.61098767

ldc.r8 12

ldc.r8 0

ldc.r8 0.0

ldc.r8 -0.0

ldc.r8 (00 00 00 00 00 00 F0 7F) // INF

ldc.r8 1.2E+309 // INF

ldc.r8 (ff ff ff ff ff ff ff ff) //Nan

ldc.r8 (01 00 00 00 00 00 00 00) // 4.9406564584124654e-324

}

}

 

    IL_0000:  /* 23   | 3333333333332940 */ ldc.r8     12.6

    IL_0009:  /* 23   | 88D13960D3382940 */ ldc.r8     12.61098767

    IL_0012:  /* 23   | 0000000000002840 */ ldc.r8     12.

    IL_001b:  /* 23   | 0000000000000000 */ ldc.r8     0.0

    IL_0024:  /* 23   | 0000000000000000 */ ldc.r8     0.0

    IL_002d:  /* 23   | 0000000000000080 */ ldc.r8     -0.0

    IL_0036:  /* 23   | 000000000000F07F */ ldc.r8     (00 00 00 00 00 00 F0 7F)

    IL_003f:  /* 23   | 000000000000F07F */ ldc.r8     (00 00 00 00 00 00 F0 7F)

    IL_0048:  /* 23   | FFFFFFFFFFFFFFFF */ ldc.r8     (FF FF FF FF FF FF FF FF)

    IL_0051:  /* 23   | 0100000000000000 */ ldc.r8     (01 00 00 00 00 00 00 00)

 

In this program we will come do what we promised you a long time ago and that is how to handle numbers with decimal places. If we start with the file e.il first numbers like 12.6 are called floating point numbers as they have a decimal point in them. They are displayed as is. If we have a number like 12, a decimal point is added and no zero after it.

 

If the number has tons of decimal places like the third case, all the decimal places are displayed. The next case is that of a zero which is displayed as a zero with a decimal point and then a negative zero that requires a negative sign. We have to write the negative zero as –0.0 or else it becomes a positive 0. For the positive zero it is optional.

 

So far so good but the problem is with numbers like Infinity and NaN that stands for not a number. These have to be displayed within brackets. Before we explain what a NaN is lets understand that a Double takes up 8 bytes and represents a double precision floating point number.

 

The range for a double is negative 1.79769313486232e308 to positive 1.79769313486232e308. Thus when we cross this range on the higher or lower range we get to display the number in brackets. A NaN is not a number that happens when we divide by zero. Lets look at our code starting with the DecodeILInstrcution2. We add a if statement checking for operand type InLineR.

 

As eight bytes follow this operand type we use the ToDouble method to extract the byte as well as use the bytes b1 to b8 to individually extract them. We then write out the bytes in round brackets and then display the name of the op code. We then call a function DisplayR8 to actually display the floating point number and then set the sizeofinstructiondata to 9.

 

Thus it is the DisplayR8 method that does the grunt work. In this method we once again pick up the 8 bytes as individual bytes and then convert the double number stored in the variable token to a string using the ToString function of the object class. We then need to find out if this number is a very small number and the thus we find whether it contains a E-.

 

If pos is positive, we found the match and now we extract the string 2 bytes from the words E- to get a string that only contains the number after the exponent or E. We convert this to an integer stored in the variable d2. Now if the original floating point number in token is too large or is NaN, then when we convert to a string, we get Infinity.

 

This does not happen with numbers smaller than E-308 for some unknown reasons. We expected that if with large numbers we get Infinity when we convert it into a string, we expected the same behavior with smaller numbers that are out of range. This why we need to check for three conditions if the number should be in brackets.

 

If there is an infinity or NaN in the string and if d2 is larger than 308. In these cases we simply display the number in brackets. We then check for a positive or negative zero by looking at the last byte as the topmost bit is the sign bit. Now comes the problem. A number like 12 should be displayed as 12. and 12 by itself.

 

The original ildasm was written in C++ which has its own functions for displaying floating point numbers. Thus we decided in calling those functions that ildasm calls. Easier said than done. We created a class sss in which we have a method ReturnStringForR8 that takes the floating point number and a zero.

 

This method will be called for fields where this variable has a value of 1. We simply display the string that this function returns. Lets look at the code for this class sss first.

 

abcdef.cpp

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#using <mscorlib.dll>

using namespace System;

__gc public class sss

{

public:

};

String * sss::ReturnStringForR8(double e , int j)

{

char szprt[1000];

char szf[32],*pch;

gcvt(e , 17 , szf);

double df = strtod(szf , &pch);

if ( j == 0)

sprintf ( szprt , "%s", szf);

else if ( df == e )

sprintf ( szprt , "%s)", szf);

else

sprintf ( szprt , "0x%I64X) // %s", e , szf);

String *ss = szprt;

return ss;

}

 

We now write in a file abcdef.cpp in the same directory and this is in managed C++ very similar to C#. We start with some header files that carry no code but function prototypes. These header files are something that both Java and C# do not like and hence are not present in these languages.

 

We need to use the class String and make want to call code from the System class and hence we have the two using clauses. As we are calling this code from managed code, we want this class to be garbage collected and hence the keyword __gc. In C++ we place the prototypes of the methods in the class and the code outside the class.

 

Thus outside the class we preface the method name with the name of the class and two colons. We simply use the function gcvt that is a old C function to convert the double e into a string with 17 digits and store it in the array szf. As the value of j is 0, we simply write out the string that we have in the szf to szprt.

 

We could have copied the string from one array to another. The %s tells us that the parameter following is a string as %d would be a number. We know all this as we have first cut our teeth on C and then C++ and then Java and now C#. we then create a pointer to a sting class ss and equate it to the array szprt that we return.

 

The rest of the code we do a little later. Thus to display floating point numbers. We handle the exception cases first and then use C code to get us the number as a string. We looked at a file called dis.cpp that comes with the Shared Source and figured out how ildasm was displaying numbers.

 

Also we need to compile the above as

 

Cl /clr /ZD abcdef.cpp.

 

The cl is the C++ compiler, /clr tells it to produce .Net or managed code and /ZD to produce a dll. Now we have to add /R abcdef.dll to the C# compiler option.

 

Program61.csc

public void DisplayAllFields (int typeindex)

{

int len = returnstring.Length;

Console.Write(returnstring);

GetFieldConstantValue(fieldindex , len );

DisplayCustomAttribute("FieldDef" , fieldindex , spacesfornested + spacesforrest);

}

 

public void GetFieldConstantValue (int constantrow , int len )

{

int ii;

if ( ConstantsStruct == null )

{

Console.WriteLine();

return ;

}

for ( ii = 1 ; ii < ConstantsStruct.Length ; ii++)

{

int tabletype = ConstantsStruct[ii].parent & 0x03;

if ( tabletype == 0)

{

int constantrowcoded = ConstantsStruct[ii].parent >> 2;

if ( constantrowcoded == constantrow)

break;

}

}

if ( ii != ConstantsStruct.Length )

{

if ( ConstantsStruct[ii].dtype == 14)

GetFieldConstantValueAsString (constantrow , ConstantsStruct[ii].dtype ,ConstantsStruct[ii].value , len);

else

{

string ss = DisplayFromConstantsTable (constantrow,0 ,"FieldDef");

Console.Write(ss);

}

}

else

Console.WriteLine();

}

public string DisplayFromConstantsTable (int start , int end ,string tablename )

{

string returnstring = "";

if ( ConstantsStruct == null)

return "";

for ( int ii = 1 ; ii < ConstantsStruct.Length ; ii++)

{

string consttablename = GetHasConstTable(ConstantsStruct[ii].parent);

int constindex = GetHasConstValue(ConstantsStruct[ii].parent);

if ( consttablename == tablename )

{

if ( start == constindex )

{

if ( consttablename == "Property" || consttablename == "FieldDef")

returnstring = " = ";

else

returnstring = "  = ";

int value = ConstantsStruct[ii].value;

if ( ConstantsStruct[ii].dtype == 13)

{

returnstring = returnstring + "float64(" ;

Double val = BitConverter.ToDouble(blob , value+1);

//int dummy = BitConverter.ToInt32(blob , value+1);

sss s1 = new sss();

string ss = s1.ReturnStringForR8 (val , 1);

returnstring = returnstring + ss + "\r\n";

}

}

e.il

.class zzz

{

.field int64 j6 = float64(10.33)

.field int64 j5 = float64(0xA)

}

 

  .field /*04000001*/ privatescope int64 j6$PST04000001 = float64(10.33)

  .field /*04000002*/ privatescope int64 j5$PST04000002 = float64(0xA) // 4.9406564584124654e-323

 

In this program we once again display numbers with decimal places but now with reference to fields. Fields can have constant values that are stored in the constants table. We  have a method GetFieldConstantValue that simply displays the constant value of the field given the field row number and the length of the field directive so far.

 

In this method GetFieldConstantValue we as in the function DisplayFromConstantsTable scan the Constants table. If this table is null, we have no constants and thus no constant value for the field and hence we need to write out the enter. We then scan the Constants table for a coded index value of zero for the field table type and the row number.

 

If we meet a match we exit the loop and now check after the loop if the variable ii is a valid row number in the Constants table. If yes, we now check if its field type is 14, that of a string. If it is we have a function GetFieldConstantValueAsString that handles just the string type and then call the DisplayFromConstantsTable to handle all the other types.

 

If the constants table is not null and the field has no initializations done, we simply write out a new line. The method DisplayFromConstantsTable takes the field row number and the second parameter is not used. The third is the name of the table FieldDef. The method DisplayFromConstantsTable has only two small changes initially.

 

The first is that we add the table name FieldDef to the first if statement so that the returnstring variable gets one less space before the equal to sign. Two for the sake of convenience we also create a variable value and set it to the value field of the Constants table. We then check for the type to be 13 which stands for a floating point number.

 

We first write out the string float64 with a open bracket in the variable returnstring. We then read the double stored in the blob array. Now we do no other computation in C# but call the ReturnStringForR8 in the abcdef.dll to return the floating point staring.

 

As we are dealing with fields, we have the last parameter a 1 and not zero. In the ReturnStringForR8 method, as the value of variable j is 1 and not zero, the else if and the else get called. There is a method called strtod that converts a string back to a floating point number and returns this value.

 

The second parameter is a pointer to chars that will stop the scanning. We do not want the scanning to stop and hence give no chars. Thus we started with a floating point number and then converted it into a string using gcvt and then once converted it back to a double.

 

If there is no loss along the way, the two doubles will be the same and thus we display it as a string stored in the szf array with a  closed bracket. If there is a mismatch, then we display the floating point number in hex first along with the exponential notation in brackets.

 

Thus the first field 10.33 shows with the else if and the very small value of the second field shows up with comments. Thus we have let the C++ function handle all the cases. Thus floating point numbers with fields and in a il instruction are very different.

 

Program62.csc

if ( opcode.OperandType == OperandType.ShortInlineR)

{

Console.Write(strings);

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Single singlevalue = BitConverter.ToSingle(codearray, codeindex+1);

string s = singlevalue.ToString();

Console.Write("{0}{1}{2}{3}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(8));

Console.Write(" */ {0} {1} ", opcode.Name , CreateSpaces(3) );

if ( singlevalue == 0.015625)

Console.Write("1.5625e-002");

else if ( singlevalue == 1.5e+009)

Console.Write("1.5e+009");

else if ( singlevalue == 1.5e+008)

Console.Write("1.5e+008");

 else if ( singlevalue == 0 && b4 == 0x80)

 Console.Write("-0.0" );

 else if ( singlevalue == 0)

 Console.Write("0.0" );

 else if ( s.EndsWith(".5") || s.EndsWith(".25") || s.EndsWith(".75") || s.EndsWith("0625") || s.EndsWith("125")|| s.EndsWith(".375") )

 Console.Write(s);

else

{

//Console.WriteLine(".......A");

sss s4 = new sss();

string ss = s4. ReturnStringForR4(singlevalue );

if ( ss == "")

Console.Write("({0} {1} {2} {3})" , b1.ToString("X2"), b2.ToString("X2"), b3.ToString("X2"), b4.ToString("X2"));

else

Console.Write(ss);

}

sizeofinstructiondata = 5;

}

 

.method public void abc()

{

ldc.r4 15.1

ldc.r4 -15.1

ldc.r4 15.01

ldc.r4 15.1234

ldc.r4 15.256789

ldc.r4 12345.15

ldc.r4 0.6

ldc.r4 0.05

ldc.r4 34.5129

ldc.r4 0.115625

ldc.r4 -2000000000000000000

ldc.r4 0.075

ldc.r4 1000000

ldc.r4 21

ldc.r4 10

ldc.r4 16777216

ldc.r4 8.5

ldc.r4 8.25

ldc.r4 9.25

ldc.r4 9.75

ldc.r4 14.

ldc.r4 15.0

ldc.r4 1.5e+009

ldc.r4 10000001

ldc.r4 1500000000

ldc.r4 20000000

ldc.r4 10000001

}

 

    IL_0000:  /* 22   | 9A997141         */ ldc.r4     (9A 99 71 41)

    IL_0005:  /* 22   | 9A9971C1         */ ldc.r4     (9A 99 71 C1)

    IL_000a:  /* 22   | F6287041         */ ldc.r4     (F6 28 70 41)

    IL_000f:  /* 22   | 72F97141         */ ldc.r4     (72 F9 71 41)

    IL_0014:  /* 22   | CF1B7441         */ ldc.r4     (CF 1B 74 41)

    IL_0019:  /* 22   | 9AE44046         */ ldc.r4     (9A E4 40 46)

    IL_001e:  /* 22   | 9A99193F         */ ldc.r4     (9A 99 19 3F)

    IL_0023:  /* 22   | CDCC4C3D         */ ldc.r4     (CD CC 4C 3D)

    IL_0028:  /* 22   | 360D0A42         */ ldc.r4     (36 0D 0A 42)

    IL_002d:  /* 22   | CDCCEC3D         */ ldc.r4     (CD CC EC 3D)

    IL_0032:  /* 22   | 6B0BDEDD         */ ldc.r4     (6B 0B DE DD)

    IL_0037:  /* 22   | 9A99993D         */ ldc.r4     (9A 99 99 3D)

    IL_003c:  /* 22   | 00247449         */ ldc.r4     1000000.

    IL_0041:  /* 22   | 0000A841         */ ldc.r4     21.

    IL_0046:  /* 22   | 00002041         */ ldc.r4     10.

    IL_004b:  /* 22   | 0000804B         */ ldc.r4     16777216

    IL_0050:  /* 22   | 00000841         */ ldc.r4     8.5

    IL_0055:  /* 22   | 00000441         */ ldc.r4     8.25

    IL_005a:  /* 22   | 00001441         */ ldc.r4     9.25

    IL_005f:  /* 22   | 00001C41         */ ldc.r4     9.75

    IL_0064:  /* 22   | 00006041         */ ldc.r4     14.

    IL_0069:  /* 22   | 00007041         */ ldc.r4     15.

    IL_006e:  /* 22   | 5ED0B24E         */ ldc.r4     1.5e+009

    IL_0073:  /* 22   | 8196184B         */ ldc.r4     10000001

    IL_0078:  /* 22   | 5ED0B24E         */ ldc.r4     1.5e+009

    IL_007d:  /* 22   | 8096984B         */ ldc.r4     20000000

    IL_0082:  /* 22   | 8196184B         */ ldc.r4     10000001

 

This program now displays a single or half a double. This floating point is a single precision and takes up only four bytes. Its value ranges from negative 3.402823e38 to positive 3.402823e38, as well as the five exceptions , positive or negative zero, positive or negative infinity and NaN. Single is half a double or float in C. Lets look at the output first and check whether we can find some pattern. The first 12 floating point numbers show up as four numbers in brackets. Thus a 15.1 or 15.01 shows up as brackets but 15 by itself with a decimal point. A 0.05 and a 115625 are in brackets but 8.5 and 9.75 are shown as is. We got lost in trying to figure out whether we need to display in brackets or as a floating point number. Hence this part is not complete as we could not figure out how ildasm displays a floating point number with single precision. Even looking at the code in dis.cpp did not help. Thus lets look at the code in the last if statement in the method DecodeILInstrcution2. We read the Single value stored in the blob heap and write out the four individual bytes. We then account for some special cases. The gcvt function has some problem in displaying numbers that have the form 0.0<x>, where x is a sequence of digits. This is documented in the Microsoft Knowledge base article Q37794 where it displays the number in scientific notation and not the normal way. The first if statement handles this. When we have numbers like 15 and six or seven zeroes, these numbers also use the exponential notation.  We then handle the positive and negative zeroes as before and then if the number ends in .5 or .25 etc, we display it using the string value. Now we call the ReturnStringForR4 written in C++ to return the rest and if it returns a null, we use the default that is in brackets. Lets look at the C++ code first.

 

__gc public class sss

{

public:

String * ReturnStringForR8(double e , int );

String * ReturnStringForR4(float e );

};

String * sss::ReturnStringForR4(float e )

{

char szf[32],*pch;

gcvt(e , 8 , szf);

float  df = atof(szf );

char *s = strchr(szf , '.');

int result = (int) ( s - szf);

String *ss ;

ss = szf;

if ( (strlen(szf) - result ) == 1&&  e <= 9999999)

return ss;

else if ( strchr(szf,'.') == 0)

return ss;

else

ss = "" ;

return ss;

}

 

In this function we first use the gcvt method to give us the string representation of the float in the array szf. Then we use atof to convert the float string back into a float df. We also use the strchr method to find whether the float string has a decimal point.

 

If it does, we get a non zero pointer to where the decimal point is in the string szf. If the string does not have a decimal point, we get null or zero. In C a pointer can not have a null or zero value. The variable result will contain the where the decimal point is within the string.

 

Thus if the value is 2, it means that the decimal point is at the third place as in 15.9. We then subtract the length of the string got by using the strlen from this value and if it is one we return the value of ss or the string in array szf. It is this string that is non zero is displayed.

 

If the string is null, it means that the floating point number is to displayed in brackets.  Thus for 10000. the value of result is 5 and the difference is 1 as the if statement in English means that we have a number with a decimal point but no decimal places. If the number becomes 10000.1, it gets displayed in brackets.

 

If we simply display the value of the s variable in C#, we do not get the dot. Then we check whether the string does not have a dot. Thus 1.677722E+07 gives us true as there is no decimal place and 10000 gives us false as there is no decimal place. For threes numbers we return the same string back which is not in exponential form.

 

Else we return a null and let C# display the number in brackets. Thus we check in C++ for two cases one if it is the decimal point is at the very end and for no decimal point at all in the string. By writing such code, we have covered nearly all cases.

 

Program71.csc

if ( ConstantsStruct[ii].dtype == 12 )

{

returnstring = returnstring + "float32(" ;

Single singlevalue = BitConverter.ToSingle(blob, value+1);

int val = BitConverter.ToInt32(blob , value+1);

string s = singlevalue.ToString();

int decimalpoint = s.IndexOf(".");

if ( val == 0x4EB2D05E)

returnstring = returnstring + "1.5e+009" ;

else if ( decimalpoint == -1  &&  !(s.IndexOf("Infinity") != -1 || s.IndexOf("NaN") != -1))

returnstring = returnstring + s + "." ;

else

returnstring = returnstring + "0x" + val.ToString("X8");

returnstring = returnstring + ")\r\n";

//Console.WriteLine(returnstring);

}

 

.class zzz

{

.field public float64 i = float32(1.2)

.field public float64 i1 = float32(15)

.field public static literal float32 NaN = float32(0xFFC00000)

.field public static literal float32 PositiveInfinity = float32(0x7F800000)

.field public static literal float32 NegativeInfinity = float32(0xFF800000)

.field private static literal float32 TOO_BIG = float32(0x4EB2D05E)

}

 

  .field /*04000001*/ public float64 i = float32(0x3F99999A)

  .field /*04000002*/ public float64 i1 = float32(0x0000000F)

  .field /*04000003*/ public static literal float32 NaN = float32(0xFFC00000)

  .field /*04000004*/ public static literal float32 PositiveInfinity = float32(0x7F800000)

  .field /*04000005*/ public static literal float32 NegativeInfinity = float32(0xFF800000)

  .field /*04000006*/ private static literal float32 TOO_BIG = float32(1.5e+009)

 

In the last program for single precision floating point numbers we are dealing with fields as we did for double precision floating point numbers. We as before take into a account some special cases like 1.5e0009 as explained before. We need to display this value in a exponential notation.

 

We then figure out the decimal point and if it is not there and the string does not contain a infinity or a NaN we display it with a dot. This applies to numbers like 15.0. Finally we have to display the value as a hex number and thus we use the variable val to read the read the floating point number as a int. We do not call the code in the abcdef.dll file.

 

Program.

if ( opcode.OperandType == OperandType.InlineString)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

token = token & 0x00ffffff;

int howmanybytes, uncompressedbyte5;

howmanybytes= CorSigUncompressData(us  , token , out uncompressedbyte5);

int count = uncompressedbyte5 - 1;

if ( howmanybytes == 3)

howmanybytes++;

int startingpt = token + howmanybytes;

byte [] stringarray = new byte[count];

Array.Copy(us , startingpt, stringarray , 0 , count);

bool makearray = IsMakeArray (stringarray);

if ( makearray && count != 0)

{

Console.Write("(70){0}       */ {1}      " , token.ToString("X6") , opcode.Name);

Console.Write("bytearray (");

DisplayFormattedColumns (token, 62 + (spacesforrest+2+ spacesfortry + spacesfornested) , false , true);

}

else

{

string str = GetNameU (token , false , 0);

Console.Write("(70){0}       */ {1}      " , token.ToString("X6") , opcode.Name);

Console.Write("\"");

string returnstring;

returnstring = DisplayStringMethod (str,spacesforrest+2+ spacesfortry + spacesfornested , 0 , false);

Console.Write(returnstring);

Console.Write("\" /* 70{0} */" , token.ToString("X6"));

}

sizeofinstructiondata = 5;

}

bool IsMakeArray(byte [] stringarray)

{

int countascii = 0;

int index = 0;

bool makearray = false;

while ( index < stringarray.Length - 1 )

{

if ( stringarray[index] >= 129 )

countascii++;

if ( stringarray[index] <= 31 && !( stringarray[index] == 0x0d || stringarray[index] == 0x0a || stringarray[index] == 0x09 ))

countascii++;

if ( stringarray[index+1] != 0 )

countascii++;

index = index + 2;

}

if ( countascii >= 1)

makearray = true;

return makearray;

}

public string DisplayStringMethod(string str,int spaces , int tablerow , bool field)

{

bool notfirstline = false;

int len = str.Length ;

int countofchars = 0;

int totalcount = 0;

int bytecount = 49;

string returnstring = "";

int secondline = 101;

if ( field )

{

string s = GetFieldAttributes(tablerow);

secondline = s.Length + fieldparamarray[tablerow].Length + NameReserved(GetString(FieldStruct[tablerow].name)).Length + 74;

}

for ( int ii = 0 ; ii < len ; ii++)

{

if ( str[ii] == '\t')

returnstring  = returnstring  + "\\t" ;

else if ( str[ii] == '"')

returnstring  = returnstring  +  "\\\"" ;

else if ( str[ii] == '\\')

returnstring  = returnstring  + "\\\\";

else if ( str[ii] == 13)

returnstring  = returnstring  + "\\r";

else if ( str[ii] == 10)

returnstring  = returnstring  + "\\n";

else if ( str[ii] == '?')

returnstring  = returnstring  + "\\?";

else

returnstring  = returnstring  + str[ii];

if ( str.Length >= 50 &&  str[49] == '\\')

bytecount = 48;

if ( countofchars == bytecount && !notfirstline && !( len == 50 ||  len == 51 ||  len == 52) )

{

returnstring  = returnstring  + "\"\r\n" + CreateSpaces(spaces) + "+ \"" ;

notfirstline = true;

countofchars = 0;

}

else if ( notfirstline && (countofchars % secondline) == 0  )

{

int charsleft = len - totalcount ;

if ( charsleft >= 4)

returnstring  = returnstring  + "\"\r\n" + CreateSpaces(spaces) + "+ \"" ;

countofchars = 0;

}

totalcount++;

countofchars++;

}

return returnstring;

}

public string GetNameU(int starting , bool blobtable , int tablerow)

{

int howmanybytes , uncompressedbyte;

if ( blobtable )

howmanybytes = CorSigUncompressData(blob  , starting , out uncompressedbyte);

else

howmanybytes = CorSigUncompressData(us  , starting , out uncompressedbyte);

int len = uncompressedbyte;

System.Text.Encoding e = System.Text.Encoding.Unicode;

string  returnstring ;

if ( blobtable )

returnstring = e.GetString(blob, starting + howmanybytes  , len);

else

returnstring = e.GetString(us, starting + howmanybytes  , len);

return returnstring;

}

.class zzz

{

.method public void abc()

{

ldstr "My name is vijay mukhi. Please tell my wife sonal that I love her a lot and will "

ldstr bytearray (01 65 )

}

}

 

    IL_0000:  /* 72   | (70)000001       */ ldstr      "My name is vijay mukhi. Please tell my wife sonal "

    + "that I love her a lot and will " /* 70000001 */

    IL_0005:  /* 72   | (70)0000A6       */ ldstr      bytearray (01 65 )                                           // .e /* 700000A6 */

 

 

The last OperandType type is InlineString. There is just one instruction ldstr that falls in this family. We start as always adding a if statement for this type and then picking up the four byte number that gives us an offset into the us heap where this string is stored.

 

The us heap is where strings created by the programmer in code are stored. This heap also starts with a count byte that we store in the variable count and the variable startingpt gives us the actual start of the string. This we get by adding the howmanybytes that tell us how many bytes this strings length occupies to the token variable.

 

We then create an array stringarray of size count bytes and then use the Copy method from the array class to copy the string from the us heap to this array. We now have a method IsMakeArray that returns a true or false depending upon whether we have to display the string as a string or as series of bytes.

 

Lets now look at what this method has to offer. We pass this method our array of bytes and then scan each byte in  a loop. We then increment a variable countascii by one if we meet a non ascii character i.e. any number larger than 128.

 

We also increment this variable if we meet a byte that is smaller than 31, but we ignore the tab, and the two new line characters. Also as all our strings are unicode strings, the next byte or the odd byte must be zero and thus if we find a non zero odd byte, we also increase countascii by 1.

 

We increment the index variable by 2 as we are dealing with 16 bit unicode characters. When we leave the while, if we find any of the above characters, the variable countascii will be larger than 1 and we return true. Thus we display the bytes as bytes if we find that we do have a unicode string.

 

If we have some bytes to display and the variable makearray is true, we write out the offset in the us heap that has a number 0x70 and then the words bytearray. We then use the trusted DisplayFormattedColumns method to write out the bytes properly formatted one below the other.

 

If variable makearray is false, then we have to display the bytes as a string and we use the method GetNameU to give us the string stored in the us heap. In this method we take two parameters, the starting point of the string and a bool. The use of this boolean variable is to tell us whether this string is stored in the us heap or the blob heap.

 

Fields can also be initialized to a string and these strings are stored in the blob heap and not the us heap. Thus the second parameter is false for strings in the us heap. We repeat ourselves once again in this function and we get the count bytes once again and the length occupied by the count bytes.

 

We use the GetString method that takes a array of bytes and a starting point in that array and the length or count of the bytes and gives us a string in return. This is the unicode string that we return back.

 

We once again write out the offset of the string and now use a method DisplayStringMethod to write out the string on multiple lines passing it the actual string and the initial spaces as well as the last two parameters are used for fields and hence the last one is false as we are dealing with instructions. In this method the string has to be displayed properly formatted on multiple lines.

 

The variable notfirstline is false for the first line and then true for the second line onwards. The variable byte count is the number of characters that will be written on the first line and secondline tells us how many will be written on the second line. The variable ii will let us scan the entire string stored in the string variable str.

 

We first check for special characters like a tab and enter and we need to quote these characters as we are using the WriteLine function to write them out. Thus if the WriteLine method sees a enter or a 13, it will write out a new line and hence we have a add a backslash to escape the special characters. Thus we escape six special characters.

 

The entire string is stored in the returnstring variable along with the enters and the spaces also. The only problem is that if the last character on a line is a backslash, it is moved on to the next line by reducing the width of the line from 49 to 48 that is stored in the bytecount variable.

 

The variable countofchars starts at zero and is incremented for each character. When it touches 49 or bytecount, we know that we need to write on the next line. Thus the first if statement checks that the countofchars equals bytecount and the notfirstline is false.

 

If this condition is met we add a return with spaces and a plus sign to returnstring and set countofchars to zero. Thus this variable each time tells us how many characters we have written on a new line so far. We also set the notfirstline to true so that this if statement gets called only once.

 

Also if the length of the string is up to 52 characters, we do not display it on two lines but a single line and hence the final condition on the if statement. In the else we do not really need the first condition and check whether we written out enough characters for the second line onwards.

 

This number is store in the variable secondline. There is one small exception and that is if the last line will have less than four characters, we write them out on the same line and do not create a new line. Thus we first find out whether how many characters we have left to write out.

 

If this number is less than 4, we do not write out a new line.  We once again set the countofchars to zero and this else gets called for the second line onwards. We use totalcount to give us a count of all characters written out so far and is equal to the index variable ii.

 

Program.

public void GetFieldConstantValueAsString (int tablerow , int value , int len)

{

string returnstring  = " = ";

Console.Write(returnstring);

int howmanybytes=0,uncompressedbyte , count;

howmanybytes = CorSigUncompressData(blob , value , out uncompressedbyte);

count = uncompressedbyte;

value = value + howmanybytes;

byte [] stringarray = new byte[count];

Array.Copy(blob , value , stringarray , 0 , count);

bool makearray = IsMakeArray(stringarray);

if ( makearray && count != 0)

{

Console.Write("bytearray (");

DisplayFormattedColumns(value-howmanybytes, len+14 , false , false);

}

else

{

string str = "";

str = GetNameU(value - howmanybytes, true , tablerow);

returnstring = "\"";

returnstring = returnstring + DisplayStringMethod (str,spacesforrest+ spacesfortry + spacesfornested , tablerow , true);

returnstring = returnstring + "\"";

Console.WriteLine(returnstring);

}

return ;

}

 

.class zzz

{

.field public int8  bb = "My name is vijay mukhi. Please tell my wife sonal that I love her a lot and will "

.field public int8  cc = bytearray (01 48 49)

}

 

  .field /*04000001*/ public int8 bb = "My name is vijay mukhi. Please tell my wife sonal "

  + "that I love her a lot and will "

  .field /*04000002*/ public int8 cc = bytearray (01 48 )                                           // .H

 

The last program on strings deals with the displaying strings that we use to initialize a field with. The GetFieldConstantValueAsString method gets called with the field row number and then the offset in the blob heap where this string begins. The last parameter is length of the string written out so far. We as before pick up the count and howmanybytes and call the IsMakeArray function.

 

If it returns true we simply call the DisplayFormattedColumns methods. If it is false, we call the DisplayStringMethod with the last parameter being true signifying a field and the second last parameter the field row of the field that has the constant value. In the DisplayStringMethod we check if the variable field is true and if yes we now need to calculate the value of the secondline variable.

 

This value is decided by the length of the attributes describing the field, the return value and also the name of the field. To all these length we add a constant 74. We should have actually also checked for a namespace and for nested classes but left that as an exercise for the reader.

 

As three in the morning, you can go far and no further. Thus the only difference in the last two programs is calculating the length of characters on the second line and also the strings are stored in different places.

 

Exception Handling

 

public void DisplayInitialMethodHeader (int methodindex)

{

int tiny = mbinaryreader.ReadByte();

if ( (tiny & 0x03) == 0x03)

tinyformat = false;

else

tinyformat = true;

mfilestream.Seek(-1,SeekOrigin.Current);

string methodstring = "";

if ( !tinyformat )

{

long where = mfilestream.Position;

short first = mbinaryreader.ReadInt16();

first12 = (short)(first & 0x0fff);

short first4 = (short)(first & 0xf000);

first4 = (short) (first4 >> 12);

short stacksize = mbinaryreader.ReadInt16();

codesize = mbinaryreader.ReadInt32();

methodstring =  "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + "// Code size       " + codesize.ToString() + " (0x" + codesize.ToString("x") + ")\r\n";

if ( (first12&0x08) == 0x08 )

ReadExceptions(where , codesize , methodindex );

methodstring = methodstring + CreateSpaces(spacesforrest + 2+ spacesfornested) + ".maxstack  " + stacksize.ToString();

int standalonesig = mbinaryreader.ReadInt32();

int rowstandalonesig = standalonesig  & 0x00ffffff;

}

public void ReadExceptions (long pos, int codesize , int methodindex )

{

int aa = -1;

long where = mfilestream.Position;

long pos1 = pos + codesize + 12 ;

long extra = 0 ;

extra = pos1 % 4 ;

if ( extra != 0 )

extra = 4 - extra ;

long newpos = pos1 + extra;

mfilestream.Position = newpos;

int first = mbinaryreader.ReadByte();

if ( methodindex == aa)

Console.WriteLine("...........Flag={0}" , first.ToString("X"));

if ( (first & 0x40) != 0x40)

{

int second = mbinaryreader.ReadByte();

mbinaryreader.ReadInt16();

int cnt = (second - 4 ) / 12;

if ( methodindex == aa)

Console.WriteLine("................count={0}" , cnt);

ExceptionStruct = new ExceptionTable[cnt];

for ( int jj = 0 ; jj < cnt   ; jj++ )

{

ExceptionStruct[jj].flags = mbinaryreader.ReadInt16();

ExceptionStruct[jj].tryoffset = mbinaryreader.ReadInt16();

ExceptionStruct[jj].trylength = mbinaryreader.ReadByte();

ExceptionStruct[jj].handleroffset = mbinaryreader.ReadInt16();

ExceptionStruct[jj].handlerlength = mbinaryreader.ReadByte();

ExceptionStruct[jj].token = mbinaryreader.ReadInt32();

ExceptionStruct[jj].oneline =0;

}

if ( methodindex == aa)

Console.WriteLine("...........If Over" );

}

else

{

if ( methodindex == aa)

Console.WriteLine("............in else");

int a1 = mbinaryreader.ReadByte();

int a2 = mbinaryreader.ReadByte();

int a3 = mbinaryreader.ReadByte();

int second = a1 + a2 * 256 + a3 * 65536;

if ( methodindex == aa)

Console.WriteLine("............a1={0} a2={1} a3={2} second={3}" , a1 , a2 , a3 , second);

int cnt;

if ( second == 24)

cnt = 1;

else if ( second == 48)

cnt = 2;

else

cnt = (second - 4 ) / 24;

ExceptionStruct = new ExceptionTable[cnt];

if ( methodindex == aa)

Console.WriteLine("................count={0}" , cnt);

for ( int jj = 0 ; jj < cnt   ; jj++ )

{

ExceptionStruct[jj].flags = mbinaryreader.ReadInt32();

ExceptionStruct[jj].tryoffset = mbinaryreader.ReadInt32();

ExceptionStruct[jj].trylength = mbinaryreader.ReadInt32();

ExceptionStruct[jj].handleroffset = mbinaryreader.ReadInt32();

ExceptionStruct[jj].handlerlength = mbinaryreader.ReadInt32();

ExceptionStruct[jj].token = mbinaryreader.ReadInt32();

ExceptionStruct[jj].oneline =0;

}

}

mfilestream.Position = where;

}

 

public void DisplayMethodILCode ( string classname , string methodname  ,int methodindex )

{

byte [] codearray = new byte[codesize];

for ( int i = 1 ; i <= codesize ; i++)

{

codearray[i-1] = mbinaryreader.ReadByte();

}

spacesfortry = 0;

if ( (first12&0x08) == 0x08 && !tinyformat)

CreateExceptionArray (methodindex , codearray );

for ( int arrayoffset = 0 ; arrayoffset  < codesize ; )

{

int instructionbyte  = codearray[arrayoffset ];

OpCode opcode;

if ( (first12&0x08) == 0x08 && !tinyformat)

DisplayExceptions (arrayoffset , codearray );

string strings = "";

int twobyte = 0;

if ( instructionbyte == 0xFE)

{

instructionbyte = codearray[arrayoffset +1];

opcode = OpCodesArray1[instructionbyte] ;

strings = CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested);

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X") + " | ";

//Console.Write(strings);

arrayoffset  = arrayoffset  + 1;

twobyte = 1;

}

else

{

opcode = OpCodesArray[instructionbyte];

strings = CreateSpaces(spacesforrest+2+spacesfortry + spacesfornested);

twobyte = 0;

if ( ! (opcode.Value == 0 && opcode.Name != "nop"))

{

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X2") + "   | ";

//Console.Write(strings);

}

}

if ( opcode.Value == 0 && opcode.Name != "nop")

{

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + instructionbyte.ToString("X2") + "   | ";

strings = strings + CreateSpaces(17) + "*/ unused" ;

Console.WriteLine("{0}", strings );

arrayoffset  = arrayoffset  + 1;

}

else

{

int sizeofinstructionanddata  = DecodeILInstrcution2( opcode , arrayoffset  , codearray , methodindex , strings );

Console.WriteLine();

if ( (first12&0x08) == 0x08 && !tinyformat)

DisplayExceptions1(arrayoffset , codearray , twobyte);

arrayoffset  = arrayoffset  + sizeofinstructionanddata;

}

}

if ( (first12&0x08) == 0x08 && !tinyformat)

{

if ( ExceptionStruct[0].oneline == 2)

{

Console.Write(CreateSpaces(spacesforrest+ spacesfornested + 2 ));

Console.WriteLine("IL_{0:x4}:  " , codearray.Length);

Console.Write(CreateSpaces(spacesforrest+ spacesfornested + 2 ));

Console.WriteLine("// Exception count 1");

DisplayOneLineTry(0);

}

}

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

if ( GetTypeForMethod(methodindex)== 1)

Console.WriteLine(" // end of global method {0}\r\n" , methodname);

else

Console.WriteLine(" // end of method {0}::{1}\r\n" , classname , methodname);

}

 

public void CreateExceptionArray(int methodindex , byte [] codearray)

{

if (ExceptionStruct == null)

return;

if ( ExceptionStruct[0].handleroffset + ExceptionStruct[0].handlerlength == codearray.Length && ExceptionStruct.Length == 1)

ExceptionStruct[0].oneline = 2;

if ( ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset && ExceptionStruct.Length == 1)

ExceptionStruct[0].oneline = 1;

if ( ExceptionStruct.Length == 2)

{

bool a = ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset;

bool b = ExceptionStruct[1].tryoffset + ExceptionStruct[1].trylength != ExceptionStruct[1].handleroffset;

if ( a && b)

{

ExceptionStruct[0].oneline = 1;

ExceptionStruct[1].oneline = 1;

}

}

if ( ExceptionStruct.Length == 2)

{

bool a = ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset;

bool b = ExceptionStruct[1].tryoffset + ExceptionStruct[1].trylength == ExceptionStruct[1].handleroffset;

if ( a && b)

{

ExceptionStruct[0].oneline = 1;

ExceptionStruct[1].oneline = 0;

}

}

if ( ExceptionStruct.Length == 2)

{

if ( ExceptionStruct[0].tryoffset == ExceptionStruct[1].tryoffset  && ExceptionStruct[0].trylength == ExceptionStruct[1].trylength && ExceptionStruct[1].handleroffset + ExceptionStruct[1].handlerlength == codearray.Length -1 && ExceptionStruct[0].handlerlength == 1)

if ( ExceptionStruct[0].handleroffset + ExceptionStruct[0].handlerlength != ExceptionStruct[1].handleroffset)

ExceptionStruct[1].oneline = 1;

}

if ( ExceptionStruct.Length == 3 &&  ExceptionStruct[0].tryoffset == ExceptionStruct[1].tryoffset && ExceptionStruct[0].tryoffset > ExceptionStruct[2].tryoffset &&  ExceptionStruct[0].flags == ExceptionStruct[1].flags &&  ExceptionStruct[2].flags == ExceptionStruct[1].flags && ExceptionStruct[1].flags== 2)

{

ExceptionTable a = ExceptionStruct[0];

ExceptionStruct[0] = ExceptionStruct[2];

ExceptionStruct[2] = a;

}

for ( int ii = 0 ; ii < ExceptionStruct.Length - 1 ; ii++)

{

int secondtry = ExceptionStruct[ii].tryoffset +  ExceptionStruct[ii].trylength;

int thirdtry = ExceptionStruct[ii+1].tryoffset +  ExceptionStruct[ii+1].trylength;

if ( ExceptionStruct[ii].tryoffset > ExceptionStruct[ii+1].tryoffset && secondtry > thirdtry)

{

ExceptionTable a = ExceptionStruct[ii];

ExceptionStruct[ii] = ExceptionStruct[ii+1];

ExceptionStruct[ii+1] = a;

}

}

 

if ( methodindex == -1)

{

for (int ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

Console.WriteLine(" Flags {0} " , ExceptionStruct[ii].flags.ToString("X8"));

Console.WriteLine(" Try Offset {0} 0x{1}" , ExceptionStruct[ii].tryoffset , ExceptionStruct[ii].tryoffset.ToString("X"));

Console.WriteLine(" Try Length {0} 0x{1}" , ExceptionStruct[ii].trylength , ExceptionStruct[ii].trylength.ToString("X"));

Console.WriteLine(" Handler  Offset {0} 0x{1}" , ExceptionStruct[ii].handleroffset , ExceptionStruct[ii].handleroffset.ToString("X") );

Console.WriteLine(" Handler length {0} 0x{1}" , ExceptionStruct[ii].handlerlength , ExceptionStruct[ii].handlerlength.ToString("X"));

Console.WriteLine(" Token {0:X}" , ExceptionStruct[ii].token , ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength);

Console.WriteLine("EndTry={0:X} Endhandler={1:X} codearray={2:X} oneline={3}" , ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength, ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength , codearray.Length , ExceptionStruct[ii].oneline);

Console.WriteLine();

}

}

}

public void DisplayExceptions (int instructionnumber, byte [] codearray )

{

int ii ;

bool endtry = false;

for ( ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

bool showtry = true;

if ( ii >= 1 ) // to show a try or not

{

int first = ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength;

int second = ExceptionStruct[ii-1].tryoffset + ExceptionStruct[ii-1].trylength;

if ( first == second && ExceptionStruct[ii-1].oneline != 1)

showtry = false;

else

showtry = true;

}

if ( instructionnumber == ExceptionStruct[ii].tryoffset && showtry && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine(".try");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry+ spacesfornested));

Console.Write("{\r\n");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength && !endtry && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.WriteLine("}  // end .try");

spacesfortry = spacesfortry - 2;

endtry= true;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 0 && ExceptionStruct[ii].oneline == 0)

{

int token = ExceptionStruct[ii].token;

int table = token >> 24;

int tablerow = token & 0xffffff;

string typename="";

if ( table == 2)

typename = typedefnames[tablerow];

if ( table == 1)

typename = typerefnames[tablerow];

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("catch {0} " , typename);

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

//Console.WriteLine("........{0} {1}" , table, tablerow);

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 2 && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("finally");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 4 && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("fault");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength  && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.WriteLine("}  // end handler");

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.Write(DisplayExceptionBytes(ii));

spacesfortry = spacesfortry - 2;

}

}

}

public string DisplayExceptionBytes(int i)

{

string ss = "// HEX: " ;

ss = ss + ConvertInt32ToString(ExceptionStruct[i].flags);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].tryoffset);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].trylength);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].handleroffset);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].handlerlength);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].token);

ss = ss.Remove(ss.Length-1,1);

return ss + "\r\n";

}

public string ConvertInt32ToString (int i)

{

string ss = "";

int b1  = i & 0xff;

int b2 = (i & 0xff00 ) >> 8;

int b3 = (i & 0xff0000 ) >> 16;

int b4 = i >> 24;

if ( b4 == -1)

b4 = 0xff;

ss = b1.ToString("X2") + " " + b2.ToString("X2") + " " + b3.ToString("X2") + " " + b4.ToString("X2") + " " ;

return ss;

}

public void DisplayExceptions1 (int instructionnumber , byte [] codearray, int twobyte )

{

int ii ;

//Console.WriteLine(".......{0:X} {1:X}" , instructionnumber , codearray[instructionnumber] );

for ( ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

int trypos = ExceptionStruct[ii].tryoffset+ ExceptionStruct[ii].trylength ;

int handlerpos = ExceptionStruct[ii].handleroffset+ ExceptionStruct[ii].handlerlength ;

int offset;

//div_i4.exe div_i8.exe

if ( trypos > handlerpos)

offset = trypos;

else

offset = handlerpos;

if ( instructionnumber ==  offset + twobyte && ExceptionStruct[ii].oneline == 1 )

DisplayOneLineTry(ii);

}

}

public void DisplayOneLineTry ( int ii)

{

int token = ExceptionStruct[ii].token;

int table = token >> 24;

int tablerow = token & 0xffffff;

string typename="";

if ( table == 2)

typename = typedefnames[tablerow];

if ( table == 1)

typename = typerefnames[tablerow];

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.Write(".try IL_{0} to" , ExceptionStruct[ii].tryoffset.ToString("x4"));

int end = ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength;

Console.Write(" IL_{0} " , end.ToString("x4"));

if ( ExceptionStruct[ii].flags == 0)

Console.Write("catch {0} handler " , typename);

else if ( ExceptionStruct[ii].flags == 2)

Console.Write("finally handler " );

else if ( ExceptionStruct[ii].flags == 4)

Console.Write("fault handler " );

else

Console.Write("filter IL_{0} handler " , token.ToString("x4"));

Console.Write("IL_{0} to",ExceptionStruct[ii].handleroffset.ToString("x4"));

int end1 = ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength;

Console.WriteLine(" IL_{0}" , end1.ToString("x4"));

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested + 2));

Console.Write(DisplayExceptionBytes(ii));

ExceptionStruct[ii].oneline = 0;

}

 

The last major concept that we have to deal with is the issue of exceptions. When we wrote programs earlier, we would call functions to do our job. These functions normally did not returns answers but told us whether the function did its job or there was an error.

 

If the function returned zero, normally that meant that things were okay, any other value meant an error took place. Depending upon the error, a different number was returned. The problem with this approach was that if we were opening 10 files in our application calling the fopen function, we would have to repeat the error check 10 times and thus we would not even check for an error once.

 

The other problem was  that with the advent of constructors, programmers placed a lot of code in them and unfortunately  they cannot return any values. In today’s day and age, methods do not return error values but we place all our code in a .try directive and catch it in a catch block.

 

Thus all code that we want to check for errors now throw an exception that is caught by the catch block. The finally block is what gets executed at the end of the try. Thus when we want code to be called after the try gets over, we place it in the finally. If a method throws an exception, no code after that in the try gets called.

 

There are two other handler blocks called filter and fault. The tiny format does not support exceptions and we first need to read all the exceptions that are present for each function. These exceptions are not stored in tables but immediately after the IL code of the method.

 

In the method DisplayInitialMethodHeader we cal a function ReadExceptions only if this method has exceptions. We figure this out by anding the first 12 bits of the first short of the method structure. If this value is 8, we know that this method has exceptions.

 

We pass the method ReadExceptions the offset in the file, the size of the code and the method number. As we have read the first eight bytes of the method structure, we make sure that we save the file position in variable where and set it back to where it was as end of the function ReadExceptions.

 

We now jump to the start of where the exceptions are stored on disk. We get this value by adding the codesize to where we are in the method structure and then further adding a value 12. The exception structures begin at a 4 byte boundary and thus we add the necessary padding. We now read the first byte of the exception structure.

 

This value tells us which type of exception structure we are dealing with. There are two basic types that store the same basic information but differ on the size of the members. These two types are fat or small. If the first byte does not have a value of 0x40 or the fifth bit set, it belongs to the small exception type.

 

In this case we read the next byte that gives us the space occupied by the exceptions that are present. As everything is aligned on a 4 byte boundary, the next short is unused. Each small exception structure takes up 12 bytes and the initial header is 4 bytes. Thus we subtract 4 from this first byte and we get a count of the exceptions.

 

We then read the exceptions that follow in a array of structures structure ExceptionStruct that we set to a size of cnt. The first member of this structure is flags that tells us whether this exception is a catch or fault or finally. Then we have the try offset and the try length.

 

This is followed by the handler offset and length and finally a token. The oneline member is not stored in the exception structures on disk and is our own creation that we will come to later. The exception structures are laid out as per the handlers. If we have a try with a catch and a finally we get two exception structures with the same values for the try offset and length fields.

 

This also holds good if we have three catch handlers for the same try, we get three exception structures. The fat exception structure starts with the flags byte as before and then three bytes that tell us the length of the exception structures and not one like before.

 

We thus have to do the multiplication ourselves to get at the total size as three bytes is no data type in any language. We then subtract 4 the padding from here and divide by 24 as this is the size of the fat exception structure. The only problem is that if it is a number divisible by 24, we then have no padding to subtract.

 

The only difference between the fat and the small as mentioned earlier is the size of the structures. We once again read these structures into the same Exception array of structures and set the file pointer back to where its supposed to be. Now we move to the method DisplayMethodILCode that displays every instruction.

 

Before we start the display of each line we need to set right the ExceptionStruct. We do this calling a method  CreateExceptionArray that we pass two parameters, the methodindex that we really do not use and the array that contains all our code, codearray.

 

It is this function that sets the ExceptionStruct array so that we can display our exceptions. The exception directive is normally spread over multiple lines by having the try and catch on separate lines. But at times it gets displayed on one line.

 

Thus the oneline member is first always set to zero and then if it need to be displayed on one line, we set it to 1 or 2. We first take those special cases where there is only one exception in our method and thus only one exception structure.

 

A try can be followed by more than one handler but one of them will have a handler offset that is equal to the tryoffset plus the length. This is because the first handler has to follow the first try. If this is not the case, then the exception must be displayed on one line and we set the oneline member to 1.

 

The second case is when the handler offset and handler length equals the length of the code array, in this case we have one extra instruction offset to display along with the try on one line. Normally the handler offset and length will be one less than the number of lines in the codearray array. 

 

Then if we have two exceptions and both in both of them we have the try length and offset not equal to the handler offset, we have both exceptions on one line.

 

This is the same as the earlier one and we could have placed them in a loop checking that at least one exception structure should have a try offset and length equal to the handler offset. If not place all of them on one line.

 

Then we have another variation. The first try and handler do not match, but the second does. Thus the first should be on one line and the second should not.

 

The flags field is 0 for a catch, 1 for filter, two for finally and 4 for a fault. Then we found one special case where the condition was so compels that we has to place it on two lines. This condition applies to two exceptions only in a method and if the condition matches, we place the second  exception on one line.

 

The first is that the two try offsets and lengths must match which tells us that the two handlers are associated with the same try. Then the second handler must be placed at the very end of the method and the first handlers length is 1.

 

As the second handler does not start after the first handler as the first handlers offset and length is not equal to the second handlers offset which it should have been if they were part of the same try, we place the second try on a different line. Then we have one more special case.

 

If we have all three exceptions as a finally and the first try offset is equal to the second try offset but greater than the third try offset, then we need to interchange the first and third Exception structures.

 

We do this by saving the first exception structure in a variable a and then equating the third with the first and then the second to the variable a. Thus we now need to interchange Exception structures. This is a special case and the next for statement takes the same concept further.

 

We scan the exception structures from the start to one less and store in two variables the start of the handler for the current and next exception structures by adding the try offset and length. We would like the smallest handlers to come up in the exception structures.

 

Thus if the tryoffset of the current exception structure is larger than the next and the position of the handler also is, we interchange the two exception structures. Thus gets them in a order that makes it easier for us to display. Now is the time to display the actual exceptions.

 

If we look at the method DisplayMethodILCode at the very beginning before we display a line we first need to check whether we need to display a try or any one of the handlers. We as before check that we have exceptions or better still some extra method headers which today are only exception headers and it is not the tiny format which does not support exceptions.

 

If all this is true, we use the method DisplayExceptions to write out the exception. This method is passed the offset of the instruction stored in  variable arrayoffset and the codearray. This array offset variable is what we sue to write out the IL_ number that follows.

 

Thus this function is called each time before we print out an IL instruction. If we have 10 instructions, we will call the function DisplayExceptions 10 times and check if one of the four fields of the exception structure match the variable instructionnumber. This is why each time we scan all the entire exception array.

 

The first problem to resolve is that if a try has two catches and one finally, the tryoffset field will be the same for the three structures and we need to display the directive try only once. Thus the first time we display the try directive, the second time onwards for the same tryoffset we do not display it.

 

Thus we start with making the showtry variable true and when we come to the second exception structure onwards, we check if the current tryoffset and trylength are the same as the previous one. If it is so, we are dealing with the same try and hence we set the variable showtry to false.

 

If they are different it only means that we are dealing with a different try and hence we set showtry to false. All this assumes that we not dealing with a try that is displayed on one line. The first if statement displays first checks whether we need to display the .try or not.

 

We first check that the parameter instructionnumber matches the tryoffset variable and showtry has to be true which means that we are not displaying the same try again and the oneline must be 0 that signifies a multi line try. We write out the spaces as before and then the .try directive with an enter.

 

We then write out more spaces and a open bracket with an enter. We now increase the variable spacesfortry by 2 as the instructions following this try must be indented by 2. We now need to display the endtry and the next if statement takes care of that.

 

We first need to make sure that tryoffset and trylength fields equal the instructionnumber parameter and also that the end try is being displayed only once. Here we use the endtry variable which is set to false once and then again set to true once we have displayed the end try once.

 

Here we write out the spaces and the endtry in comments and most important reduce the variable spacesfortry by 2 as the indentation from now on must stop. We now would like to display the catch handler.

 

For all handlers we first check that the handleroffset field is equal to the parameter instructionnumber and the flags field is 0 for a catch and the oneline field is zero signifying a multi line try. The problem with the catch is that we also have a type reference to be displayed.

 

The token field is made up of a table code which occupies the topmost 8 bits and a row that occupies the first 24 bits. If the table code is 1, it is a index into the TypeRef table and 2 a TypeDef table. We have the typedefnames and typerefnames array that give us the type name.

 

We write out the spaces and then the typename and then a enter and a open brace and we also increase the spacesfortry variable by 2 as we need to indent the coming instructions. The next handler is the finally and hence the if statement remains the same excepting that the flags is 2.

 

For a finally there is no type name. Ditto for the fault handler that has a flags value of 4. Finally we have the last if statement that checks for the handler end that remains the same for all the three handlers. We do what we did before and decrease the spacesfortry by 2 but now need to write out the bytes of the exception structure.

 

We use a function DisplayExceptionBytes that writes out the exception structure. This is a simple function as we write out the words hex and now we need to convert every 32 bit field into 4 bytes.

 

We have a method ConvertInt32ToString that takes an int32 and extracts the four bytes from it by masking the relevant out the 24 bits and then right shifting it. We remove the last space and add a enter and return this string.

 

When we finish displaying a instruction, we now need to check whether we need to display the try directive on one line or not. The only difference is that the try on a line gets displayed after the instruction  gets displayed not before.

 

Thus the DisplayExceptions1 function gets called after we have displayed the instruction. In this function we scan the entire exception array and first figure out the try end and the handler end by adding the offset and the length.

 

We then set the offset variable to the larger of the two as the try directive on line will use this variable to decide where the display should start. The twobyte variable is zero or one depending upon whether the opcode is a one or two byte instruction. It is 1 for a two byte instruction and zero for a one byte instruction.

 

The main code is in the function DisplayOneLineTry and here is where we display the entire try and the handler.  We start by decoding the token and figuring out the type name. We then write out some spaces and the try directive and the tryoffset along with the IL_ prefix.

 

We then write out the end of the try and then depending upon the flags variable the respective handlers. The catch handler needs the name of the types and the fault and finally need no extra stuff. The fault handler displays the token as is. We then write out the handler end and display the individual bytes.

 

We also set the oneline field to zero so that we do not display this try again. Thus the DisplayException1 method handles the one line try only.

 

When we leave the method, we need to make one final check. If the oneline field has a value of 2 and if yes we need to first write out the instruction number that is one larger than the codearray and then display the try on one line.

-----------------------------------------------

Final program

using System;

using System.IO;

using System.Reflection;

using System.Reflection.Emit;

public struct FieldPtrTable

{

public int index;

}

public struct MethodPtrTable

{

public int index;

}

public struct ExceptionTable

{

public int tryoffset;

public int flags;

public int trylength;

public int handleroffset;

public int handlerlength;

public int token;

public int oneline;

}

public struct ExportedTypeTable

{

public int flags ;

public int typedefindex ;

public int name ;

public int nspace ;

public int coded ;

}

public struct NestedClassTable

{

public int nestedclass;

public int enclosingclass;

}

public struct MethodImpTable

{

public int classindex;

public int codedbody;

public int codeddef;

}

public struct ClassLayoutTable

{

public short packingsize ;

public int classsize ;

public int parent ;

}

public struct ManifestResourceTable

{

public int offset;

public int flags;

public int name;

public int coded; 

}

public struct ModuleRefTable

{

public int name;

}

public struct FileTable

{

public int flags;

public int name;

public int index;

}

public struct EventTable

{

public short attr;

public int name;

public int coded;  

}

public struct EventMapTable

{

public int index;

public int eindex; 

}

public struct MethodSemanticsTable

{

public short methodsemanticsattributes;

public int methodindex;

public int association;  

}

public struct PropertyMapTable

{

public int parent;

public int propertylist;

}

public struct PropertyTable

{

public int flags;

public int name;

public int type;

}

public struct ConstantsTable

{

public short dtype;

public int parent;

public int value ;

}

public struct FieldLayoutTable

{

public int offset;

public int fieldindex; 

}

public struct FieldRVATable

{

public int rva ;

public int fieldi;

}

public struct FieldMarshalTable

{

public int coded;

public int index; 

}

public struct FieldTable

{

public int flags;

public int name;

public int sig;

}

public struct ParamTable

{

public short pattr;

public int sequence;

public int name;

}

public struct TypeSpecTable

{

public int signature;

}

public struct MemberRefTable

{

public int clas;

public int name;

public int sig;  

}

public struct StandAloneSigTable

{

public int index;

}

public struct InterfaceImplTable

{

public int classindex;

public int interfaceindex;

}

public struct TypeDefTable

{

public int flags;

public int name;

public int nspace;

public int cindex;

public int findex;

public int mindex;

}

public struct CustomAttributeTable

{

public int parent;

public int type;

public int value;

}

public struct AssemblyRefTable

{

public short major,minor,build,revision;

public int flags ;

public int publickey ;

public int name ;

public int culture ;

public int hashvalue ;

}

public struct AssemblyTable

{

public int HashAlgId;

public int major, minor,build,revision ;

public int flags ;

public int publickey ;

public int name ;

public int culture ;

}

public struct ModuleTable

{

public int Generation;

public int Name;

public int Mvid;

public int EncId;

public int EncBaseId;

}

public struct TypeRefTable

{

public int resolutionscope;

public int name;

public int nspace;

}

public struct MethodTable

{

public int rva;

public int impflags;

public int flags;

public int name;

public int signature;

public int param;

}

public struct DeclSecurityTable

{

public int action;

public int coded;

public int bindex; 

}

public struct ImplMapTable

{

public short attr;

public int cindex;

public int name;

public int scope;

}

public class zzz

{

public void DisplayTablesForDebugging()

{

/*

Console.WriteLine("Strings Table:{0}" , strings.Length);

for ( int o = 0 ; o < strings.Length ; o++)

{

if ( strings[o] == 0)

{

Console.WriteLine();

Console.Write("{0}:" , o+1);

}

else

Console.Write("{0}" , (char)strings[o]);

}

*/

/*

Console.WriteLine("Module Table:{0}" , ModuleStruct.Length);

Console.WriteLine("Name={0} {1}", GetString(ModuleStruct[1].Name) , ModuleStruct[1].Name.ToString("X"));

Console.WriteLine("Generation={0} Mvid={1} EncId={2} EncBaseId={3}" , ModuleStruct[1].Generation , ModuleStruct[1].Mvid , ModuleStruct[1].EncId , ModuleStruct[1].EncBaseId);

*/

/*

Console.WriteLine("TypeRef Table:{0}" , TypeRefStruct.Length );

for ( int o = 1 ; o < TypeRefStruct.Length ; o++)

{

Console.WriteLine("Type {0}", o );

Console.WriteLine("Resolotion Scope={0} {1}" , GetResolutionScopeTable(TypeRefStruct[o].resolutionscope), GetResolutionScopeValue(TypeRefStruct[o].resolutionscope));

Console.WriteLine("NameSpace={0} {1}" , GetString(TypeRefStruct[o].nspace) , TypeRefStruct[o].nspace.ToString("X"));

Console.WriteLine("Name={0} {1}" , GetString(TypeRefStruct[o].name), TypeRefStruct[o].name.ToString("X"));

}

*/

/*

Console.WriteLine("TypeDef Table:{0}" , TypeDefStruct.Length );

for ( int o = 1 ; o < TypeDefStruct.Length ; o++)

{

Console.WriteLine("Type {0} ", o)  ;

Console.WriteLine("Name={0} {1}" , GetString(TypeDefStruct[o].name), TypeDefStruct[o].name.ToString("X"));

Console.WriteLine("NameSpace={0} {1}" , GetString(TypeDefStruct[o].nspace) , TypeDefStruct[o].nspace.ToString("X"));

Console.WriteLine("Field[{0}]", TypeDefStruct[o].findex);

Console.WriteLine("Method[{0}]", TypeDefStruct[o].mindex);

}

*/

/*

Console.WriteLine("CustomAttributeTable:{0}" , CustomAttributeStruct.Length );

for ( int o = 1 ; o < CustomAttributeStruct.Length ; o++)

{

string tablename= GetHasCustomAttributeTable(CustomAttributeStruct[o].parent) ;

int index = GetHasCustomAttributeValue(CustomAttributeStruct[o].parent);

string methoddefref = GetCustomAttributeTypeTable(CustomAttributeStruct[o].type);

int methoddefrefindex = GetCustomAttributeTypevalue(CustomAttributeStruct[o].type);

Console.WriteLine("Row={0} Parent tablename={1} index={2} methoddefref={3} methoddefrefindex={4}" , o.ToString("X") , tablename , index , methoddefref , methoddefrefindex);

}

*/

/*

Console.WriteLine("AssemblyRefTable:{0}" , AssemblyRefStruct.Length );

for ( int o = 1 ; o < AssemblyRefStruct.Length ; o++)

{

}

*/

}

bool IsMakeArray(byte [] stringarray)

{

int countascii = 0;

int index = 0;

bool makearray = false;

while ( index < stringarray.Length - 1 )

{

if ( stringarray[index] >= 129 )

countascii++;

if ( stringarray[index] <= 31 && !( stringarray[index] == 0x0d || stringarray[index] == 0x0a || stringarray[index] == 0x09 ))

countascii++;

if ( stringarray[index+1] != 0 )

countascii++;

index = index + 2;

}

if ( countascii >= 1)

makearray = true;

return makearray;

}

public void GetFieldConstantValueAsString(int tablerow , int value , int len)

{

string returnstring  = " = ";

Console.Write(returnstring);

int howmanybytes=0,uncompressedbyte , count;

howmanybytes = CorSigUncompressData(blob , value , out uncompressedbyte);

count = uncompressedbyte;

value = value + howmanybytes;

byte [] stringarray = new byte[count];

Array.Copy(blob , value , stringarray , 0 , count);

bool makearray = IsMakeArray(stringarray);

if ( makearray && count != 0)

{

Console.Write("bytearray (");

DisplayFormattedColumns(value-howmanybytes, len+14 , false , false);

}

else

{

string str = "";

str = GetNameU(value - howmanybytes, true , tablerow);

returnstring = "\"";

returnstring = returnstring + DisplayStringMethod(str,spacesforrest+ spacesfortry + spacesfornested , tablerow , true);

returnstring = returnstring + "\"";

Console.WriteLine(returnstring);

}

return ;

}

public string DisplayStringMethod(string str,int spaces , int tablerow , bool field)

{

bool notfirstline = false;

int len = str.Length ;

int countofchars = 0;

int totalcount = 0;

int bytecount = 49;

string returnstring = "";

int secondline = 101;

if ( field )

{

string s = GetFieldAttributes(tablerow);

secondline = s.Length + fieldparamarray[tablerow].Length + NameReserved(GetString(FieldStruct[tablerow].name)).Length + 74;

}

for ( int ii = 0 ; ii < len ; ii++)

{

if ( str[ii] == '\t')

returnstring  = returnstring  + "\\t" ;

else if ( str[ii] == '"')

returnstring  = returnstring  +  "\\\"" ;

else if ( str[ii] == '\\')

returnstring  = returnstring  + "\\\\";

else if ( str[ii] == 13)

returnstring  = returnstring  + "\\r";

else if ( str[ii] == 10)

returnstring  = returnstring  + "\\n";

else if ( str[ii] == '?')

returnstring  = returnstring  + "\\?";

else

returnstring  = returnstring  + str[ii];

if ( str.Length >= 50 &&  str[49] == '\\')

bytecount = 48;

if ( countofchars == bytecount && !notfirstline && !( len == 50 ||  len == 51 ||  len == 52) )

{

returnstring  = returnstring  + "\"\r\n" + CreateSpaces(spaces) + "+ \"" ;

notfirstline = true;

countofchars = 0;

}

else if ( notfirstline && (countofchars % secondline) == 0  )

{

int charsleft = len - totalcount ;

if ( charsleft >= 4)

returnstring  = returnstring  + "\"\r\n" + CreateSpaces(spaces) + "+ \"" ;

countofchars = 0;

}

totalcount++;

countofchars++;

}

return returnstring;

}

public string GetNameU(int starting , bool blobtable , int tablerow)

{

int howmanybytes , uncompressedbyte;

if ( blobtable )

howmanybytes = CorSigUncompressData(blob  , starting , out uncompressedbyte);

else

howmanybytes = CorSigUncompressData(us  , starting , out uncompressedbyte);

int len = uncompressedbyte;

System.Text.Encoding e = System.Text.Encoding.Unicode;

string  returnstring ;

if ( blobtable )

returnstring = e.GetString(blob, starting + howmanybytes  , len);

else

returnstring = e.GetString(us, starting + howmanybytes  , len);

return returnstring;

}

 

public void DisplayR8(double token , byte [] codearray , int codeindex)

{

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

string doubles = token.ToString();

int pos = doubles.IndexOf("E-");

int d2 = 0;

if ( pos != -1)

{

string d1 = doubles.Substring(pos+2);

d2 = Convert.ToInt32(d1);

}

//Console.WriteLine(".......{0} {1}" , doubles , token);

if ( doubles.IndexOf("Infinity") != -1 || doubles.IndexOf("NaN") != -1 || d2 >= 308)

Console.Write("({0} {1} {2} {3} {4} {5} {6} {7})",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

else if ( token == 0 && b8 == 0x80)

Console.Write("-0.0" );

else if ( token == 0 && b8 == 0x00)

Console.Write("0.0" );

else

{

sss s1 = new sss();

string ss = s1.ReturnStringForR8(token , 0);

Console.Write(ss);

}

}

public void GetFieldConstantValue (int constantrow , int len )

{

int ii;

if ( ConstantsStruct == null )

{

Console.WriteLine();

return ;

}

for ( ii = 1 ; ii < ConstantsStruct.Length ; ii++)

{

int tabletype = ConstantsStruct[ii].parent & 0x03;

if ( tabletype == 0)

{

int constantrowcoded = ConstantsStruct[ii].parent >> 2;

if ( constantrowcoded == constantrow)

break;

}

}

if ( ii != ConstantsStruct.Length )

{

if ( ConstantsStruct[ii].dtype == 14)

GetFieldConstantValueAsString(constantrow , ConstantsStruct[ii].value , len);

else

{

string ss = DisplayFromConstantsTable(constantrow,0 ,"FieldDef");

Console.Write(ss);

}

}

else

Console.WriteLine();

}

public string DisplayFromConstantsTable(int start , int end ,string tablename )

{

string returnstring = "";

if ( ConstantsStruct == null)

return "";

for ( int ii = 1 ; ii < ConstantsStruct.Length ; ii++)

{

string consttablename = GetHasConstTable(ConstantsStruct[ii].parent);

int constindex = GetHasConstValue(ConstantsStruct[ii].parent);

if ( consttablename == tablename )

{

if ( start == constindex )

{

if ( consttablename == "Property" || consttablename == "FieldDef")

returnstring = " = ";

else

returnstring = "  = ";

int value = ConstantsStruct[ii].value;

if ( ConstantsStruct[ii].dtype == 2 )

{

bool val = BitConverter.ToBoolean(blob , ConstantsStruct[ii].value+1);

if ( val )

returnstring = returnstring +  GetType(ConstantsStruct[ii].dtype) + "(true)" + "\r\n";

else

returnstring = returnstring +  GetType(ConstantsStruct[ii].dtype) + "(false)"+ "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x03 )

{

returnstring = returnstring + "char(0x" ;

short val = BitConverter.ToInt16(blob , value+1);

returnstring = returnstring + val.ToString("X4");

returnstring = returnstring + ")\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x04  || ConstantsStruct[ii].dtype == 0x05)

{

int val = blob[ConstantsStruct[ii].value+1];

returnstring = returnstring +  GetType(0x04) + "(0x" + val.ToString("X2") + ")" + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x06 || ConstantsStruct[ii].dtype == 0x07  )

{

short val = BitConverter.ToInt16(blob , ConstantsStruct[ii].value+1);

//if ( val == -1)

//returnstring = returnstring +  GetType(0x06) + "(0xFFFF)" + "\r\n";

//else

returnstring = returnstring +  GetType(0x06) + "(0x" + val.ToString("X4") + ")" + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x08 || ConstantsStruct[ii].dtype == 0x09 )

{

int val = BitConverter.ToInt32(blob , ConstantsStruct[ii].value+1);

returnstring = returnstring +  GetType(0x08) + "(0x" + val.ToString("X8") + ")" + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x0a || ConstantsStruct[ii].dtype == 0x0b )

{

long val = BitConverter.ToInt64(blob , ConstantsStruct[ii].value+1);

returnstring = returnstring +  GetType(0x0a) + "(0x" + val.ToString("X") + ")" + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 12 )

{

returnstring = returnstring + "float32(" ;

Single singlevalue = BitConverter.ToSingle(blob, value+1);

int val = BitConverter.ToInt32(blob , value+1);

string s = singlevalue.ToString();

int decimalpoint = s.IndexOf(".");

if ( singlevalue == 1.5e+009)

returnstring = returnstring + "1.5e+009" ;

else if ( decimalpoint == -1  &&  !(s.IndexOf("Infinity") != -1 || s.IndexOf("NaN") != -1))

returnstring = returnstring + s + "." ;

else

returnstring = returnstring + "0x" + val.ToString("X8");

returnstring = returnstring + ")\r\n";

//Console.WriteLine(returnstring);

}

if ( ConstantsStruct[ii].dtype == 13)

{

returnstring = returnstring + "float64(" ;

Double val = BitConverter.ToDouble(blob , value+1);

//int dummy = BitConverter.ToInt32(blob , value+1);

sss s1 = new sss();

string ss = s1.ReturnStringForR8(val , 1);

returnstring = returnstring + ss + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0xe )

{

int len = blob[ConstantsStruct[ii].value] ;

if ( len >= 1)

{

returnstring = returnstring + "\"";

for ( int jj = 1 ; jj < len ; jj++)

{

if ( blob[ConstantsStruct[ii].value+jj] != 0)

returnstring = returnstring + (char)blob[ConstantsStruct[ii].value+jj];

}

returnstring = returnstring + "\"\r\n" ;

}

else

returnstring = returnstring +  "\"\"" + "\r\n";

}

if ( ConstantsStruct[ii].dtype == 0x12 )

{

returnstring = returnstring +  "nullref" + "\r\n";

}

}

}

}

return returnstring;

}

public int DecodeILInstrcution2 (OpCode opcode , int codeindex , byte [] codearray , int methodindex , string strings )

{

int sizeofinstructiondata = 0;

if ( opcode.OperandType == OperandType.ShortInlineR)

{

Console.Write(strings);

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

//int int32value = BitConverter.ToInt32(codearray, codeindex+1);

Single singlevalue = BitConverter.ToSingle(codearray, codeindex+1);

string s = singlevalue.ToString();

Console.Write("{0}{1}{2}{3}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(8));

Console.Write(" */ {0} {1} ", opcode.Name , CreateSpaces(3) );

if ( singlevalue == 0.015625)

Console.Write("1.5625e-002");

else if ( singlevalue == 1.5e+009)

Console.Write("1.5e+009");

else if ( singlevalue == 1.5e+008)

Console.Write("1.5e+008");

else if ( singlevalue == 0 && b4 == 0x80)

Console.Write("-0.0" );

else if ( singlevalue == 0)

Console.Write("0.0" );

else if ( s.EndsWith(".5") || s.EndsWith(".25") || s.EndsWith(".75") || s.EndsWith("0625") || s.EndsWith("125")|| s.EndsWith(".375") )

Console.Write(s);

else

{

//Console.WriteLine(".......A");

sss s4 = new sss();

string ss = s4.ReturnStringForR4(singlevalue );

if ( ss == "")

Console.Write("({0} {1} {2} {3})" , b1.ToString("X2"), b2.ToString("X2"), b3.ToString("X2"), b4.ToString("X2"));

else

Console.Write(ss);

}

sizeofinstructiondata = 5;

}

if ( opcode.OperandType == OperandType.InlineR)

{

Console.Write(strings);

double token = BitConverter.ToDouble( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

Console.Write("{0}{1}{2}{3}{4}{5}{6}{7}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

Console.Write(" */ {0} {1} ", opcode.Name , CreateSpaces(3));

DisplayR8(token,codearray , codeindex);

sizeofinstructiondata = 9;

}

if ( opcode.OperandType == OperandType.InlineString)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

token = token & 0x00ffffff;

int howmanybytes, uncompressedbyte5;

howmanybytes= CorSigUncompressData(us  , token , out uncompressedbyte5);

int count = uncompressedbyte5;

//int count = uncompressedbyte5 - 1;

byte [] stringarray = new byte[count];

int startingpt = token + howmanybytes;

Array.Copy(us , startingpt, stringarray , 0 , count);

bool makearray = IsMakeArray(stringarray);

if ( makearray && count != 0)

{

Console.Write("(70){0}       */ {1}      " , token.ToString("X6") , opcode.Name);

Console.Write("bytearray (");

DisplayFormattedColumns(token, 62 + (spacesforrest+2+ spacesfortry + spacesfornested) , false , true);

}

else

{

string str = GetNameU(token , false , 0);

Console.Write("(70){0}       */ {1}      " , token.ToString("X6") , opcode.Name);

Console.Write("\"");

string returnstring;

returnstring = DisplayStringMethod(str,spacesforrest+2+ spacesfortry + spacesfornested , 0 , false);

Console.Write(returnstring);

Console.Write("\" /* 70{0} */" , token.ToString("X6"));

}

sizeofinstructiondata = 5;

}

if ( codearray.Length - 1 == codeindex && opcode.OperandType == OperandType.InlineMethod)

{

Console.Write(strings);

Console.Write("(00)02301B       */ call       0x2301b ");

return 1;

}

if ( opcode.OperandType == OperandType.InlineNone)

{

Console.Write(strings);

Console.Write("{0}*/ {1}",CreateSpaces(17) ,  opcode.Name);

if ( opcode.Name == "ret" && codeindex != (codearray.Length -1) )

Console.WriteLine();

if ( opcode.Name == "throw" && codeindex != (codearray.Length -1) )

Console.WriteLine();

sizeofinstructiondata=1;

}

if ( opcode.OperandType == OperandType.InlineI)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(8));

Console.Write(" */ {0} {1} 0x{2}", opcode.Name , CreateSpaces(3) , token.ToString("x"));

sizeofinstructiondata = 5;

}

if ( opcode.OperandType == OperandType.InlineI8)

{

Console.Write(strings);

long token = BitConverter.ToInt64( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

byte b5 = codearray[codeindex+5];

byte b6 = codearray[codeindex+6];

byte b7 = codearray[codeindex+7];

byte b8 = codearray[codeindex+8];

Console.Write("{0}{1}{2}{3}{4}{5}{6}{7}",b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"),b5.ToString("X2"),b6.ToString("X2"),b7.ToString("X2"),b8.ToString("X2") );

Console.Write(" */ {0} {1} 0x{2}", opcode.Name , CreateSpaces(3) , token.ToString("x"));

sizeofinstructiondata = 9;

}

if ( opcode.OperandType == OperandType.ShortInlineI)

{

Console.Write(strings);

int token = codearray[codeindex+1];

Console.Write("{0}",token.ToString("X2"));

Console.Write(CreateSpaces(14));

if ( token >= 128)

token =  token - 256;

if ( opcode.Name == "unaligned." )

Console.Write(" */ {0} {1}", opcode.Name , token.ToString());

else

Console.Write(" */ {0}   {1}", opcode.Name ,  token.ToString());

sizeofinstructiondata = 2;

}

if ( opcode.OperandType == OperandType.InlineBrTarget)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1);

string returnstring = "";

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(9) + "*/ ");

token = token + codeindex + 5;

int len = opcode.Name.Length;

returnstring = opcode.Name + " " +  CreateSpaces(9 - len) + " IL_" + token.ToString("x4");

Console.Write(returnstring);

if ( ! (codearray.Length == codeindex + 5 ))

Console.WriteLine();

sizeofinstructiondata = 5;

}

if ( opcode.OperandType == OperandType.ShortInlineBrTarget)

{

Console.Write(strings);

int token = codearray[codeindex + 1];

string returnstring = "";

Console.Write("{0}" , token.ToString("X2"));

Console.Write(CreateSpaces(15) + "*/ ");

if ( token >= 128)

{

token = 0xff - token ;

token = codeindex + 1 - token;

}

else

token = token + codeindex + 2;

int len = opcode.Name.Length;

returnstring = opcode.Name + " " +  CreateSpaces(9 - len) + " IL_" + token.ToString("x4");

Console.Write(returnstring);

if ( ! (codearray.Length == codeindex + 2 ))

Console.WriteLine();

sizeofinstructiondata = 2;

}

if ( opcode.OperandType == OperandType.InlineSwitch)

{

Console.Write(strings);

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

byte b3 = codearray[codeindex+3];

byte b4 = codearray[codeindex+4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

Console.Write(CreateSpaces(9 ));

Console.Write("*/ switch     ( ");

if ( token == 0)

Console.Write(")");

else

for ( int ii = 1 ; ii <= token ; ii++)

{

Console.Write("\r\n" + CreateSpaces(spacesforrest+2 + spacesfortry + spacesfornested));

Console.Write(CreateSpaces(10 ) + "/*      | ");

int index = BitConverter.ToInt32( codearray , codeindex + 1 + ii*4);

b1 = codearray[codeindex+1 + ii*4];

b2 = codearray[codeindex+2 + ii*4];

b3 = codearray[codeindex+3 + ii*4];

b4 = codearray[codeindex+4 + ii*4];

Console.Write("{0}{1}{2}{3}" , b1.ToString("X2"),b2.ToString("X2"),b3.ToString("X2"),b4.ToString("X2"));

int tot = codeindex+index+1 + token*4 + 4;

Console.Write(CreateSpaces(9) + "*/" + CreateSpaces(13) + "IL_{0}" , tot.ToString("x4"));

if ( ii != token)

Console.Write(",");

else

Console.Write(")");

}

sizeofinstructiondata = 5 + token*4;

}

if ( opcode.OperandType == OperandType.ShortInlineVar)

{

Console.Write(strings);

int token = codearray[codeindex+1];

Console.Write("{0}" , token.ToString("X2"));

Console.Write(CreateSpaces(15) + "*/ {0}" , opcode.Name);

int len = opcode.Name.Length;

if (opcode.Name == "ldarg.s" || opcode.Name == "ldarga.s" || opcode.Name == "starg.s")

{

string methodattributeflags = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

string sname = "";

if ( token > methoddefparamcount[methodindex] && methodattributeflags.IndexOf("static") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token > methoddefparamcount[methodindex]+1 && methodattributeflags.IndexOf("instance") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token == 0 && methodattributeflags.IndexOf("instance") != -1 )

sname = "0";

else

{

if ( methodattributeflags.IndexOf("static") != -1)

token++;

sname = GetParamNameForMethod( methodindex , 0 , token);

}

Console.Write("{0}{1}" , CreateSpaces(11 - len) , sname);

}

else

Console.Write("{0}V_{1}" , CreateSpaces(11 - len) , token);

sizeofinstructiondata = 2;

}

if ( opcode.OperandType == OperandType.InlineVar)

{

Console.Write(strings);

ushort token = (ushort)BitConverter.ToInt16(codearray , codeindex + 1);

byte b1 = codearray[codeindex+1];

byte b2 = codearray[codeindex+2];

Console.Write("{0}{1}" , b1.ToString("X2"),b2.ToString("X2"));

Console.Write(CreateSpaces(13) + "*/ {0}" , opcode.Name);

int len = opcode.Name.Length;

if (opcode.Name == "ldarg" || opcode.Name == "ldarga" || opcode.Name == "starg")

{

string methodattributeflags = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

string sname = "";

if ( token > methoddefparamcount[methodindex] && methodattributeflags.IndexOf("static") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token > methoddefparamcount[methodindex]+1 && methodattributeflags.IndexOf("instance") != -1)

sname = token.ToString() + " // ERROR: invalid arg index (>="+ (methoddefparamcount[methodindex]+1).ToString() + ")";

else if ( token == 0 && methodattributeflags.IndexOf("instance") != -1 )

sname = "0";

else

{

if ( methodattributeflags.IndexOf("static") != -1)

token++;

sname = GetParamNameForMethod( methodindex , 0 , token);

}

Console.Write("{0}{1}" , CreateSpaces(11 - len) , sname);

}

else

Console.Write("{0}V_{1}" , CreateSpaces(11 - len) , token);

sizeofinstructiondata = 3;

}

if ( opcode.OperandType == OperandType.InlineField || opcode.OperandType == OperandType.InlineMethod || opcode.OperandType == OperandType.InlineType || opcode.OperandType == OperandType.InlineTok || opcode.OperandType == OperandType.InlineSig)

{

int token = BitConverter.ToInt32( codearray , codeindex + 1 );

int seriouserror;

DecodeTokenIL(token , opcode , methodindex , strings , out seriouserror ) ;

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

if ( table == 0x0a)

{

bool b = HasCustomAttribute("MemberRef" , token );

if ( b)

{

Console.WriteLine();

DisplayCustomAttribute("MemberRef" , token, 2 + spacesforrest + spacesfornested);

}

}

if ( seriouserror == 1)

sizeofinstructiondata = codearray.Length + 1;

else

sizeofinstructiondata = 5;

}

 

return sizeofinstructiondata;

}

public void DisplayCustomAttribute (string tname , int tabindex , int noofspaces)

{

if (CustomAttributeStruct == null)

return;

for ( int ii = 1 ; ii < CustomAttributeStruct.Length ; ii++)

{

string parentcodedtablename= GetHasCustomAttributeTable(CustomAttributeStruct[ii].parent) ;

int parentcodedindex= GetHasCustomAttributeValue(CustomAttributeStruct[ii].parent);

string typecodetable = GetCustomAttributeTypeTable(CustomAttributeStruct[ii].type) ;

int typecodedindex  = GetCustomAttributeTypevalue(CustomAttributeStruct[ii].type);

string initialspaces;

initialspaces = CreateSpaces(noofspaces);

int tableindexcode = 0;

int tablenumber = 0;

string returnstring = "";

bool custombug = false;

int typeindex ;

string typename = "";

string returnvaluestring = "";

string paramstring  = "";

string dummy = "";

string methodname = "";

string onespace="";

if ( (tname == parentcodedtablename && tabindex == parentcodedindex) || (parentcodedtablename == "TypeRef" && tabindex == 0) )

{

if ( typecodetable == "MethodRef" )

{

tableindexcode = 0x0A;

typeindex= MemberRefStruct[typecodedindex].clas >> 3;

typename = typerefnames[typeindex] ;

returnvaluestring  = methodrefreturnarray[typecodedindex];

paramstring = methodrefparamarray1[typecodedindex];

tablenumber = 1;

methodname = NameReserved(GetString(MemberRefStruct[typecodedindex].name));

onespace = " ";

}

else

{

tableindexcode = 0x06;

typeindex = GetTypeForMethod(typecodedindex);

typename = typedefnames[typeindex] ;

returnvaluestring = methoddefreturnarray[typecodedindex];

paramstring  = methoddefparamarray1[typecodedindex] ;

tablenumber = 02;

methodname = NameReserved(GetString(MethodStruct[typecodedindex].name));

}

if (typename.IndexOf("System.Diagnostics.DebuggableAttribute") != -1)

custombug = true;

if ( custombug )

{

Console.Write(CreateSpaces(noofspaces));

Console.WriteLine("// --- The following custom attribute is added automatically, do not uncomment -------");

returnstring = returnstring + CreateSpaces(noofspaces) + "//";

if ( initialspaces == "")

returnstring = returnstring + "  ";

}

if ( parentcodedtablename == "TypeRef")

{

returnstring = returnstring + initialspaces + ".custom /*0C" + ii.ToString("X6") +"*/ (" + typerefnames[parentcodedindex];

returnstring = returnstring + "/*" + tablenumber.ToString("X2") + parentcodedindex.ToString("X6") + "*/ ) ";

}

else

returnstring = returnstring + initialspaces + ".custom /*0C" + ii.ToString("X6") + ":" + tableindexcode.ToString("X2") + typecodedindex.ToString("X6") + "*/ ";

returnstring = returnstring + "instance " + returnvaluestring + onespace + typename ;

returnstring = returnstring + "::" +  methodname;

returnstring = returnstring + "(";

if ( noofspaces == 0)

dummy   = ParamOnMultipleLines(paramstring , returnstring.Length + 2);

else if ( paramstring  != null)

dummy   = ParamOnMultipleLines(paramstring , returnstring.Length);

if ( custombug )

{

int ind1 = dummy.IndexOf("\r\n");

dummy= dummy.Insert(ind1+2, CreateSpaces(noofspaces) + "//");

dummy= dummy.Remove(ind1+10, 4);

}

returnstring = returnstring + dummy ;

returnstring = returnstring + ")";

returnstring = returnstring + " /* " + tableindexcode.ToString("X2") + typecodedindex.ToString("X6") + " */";

Console.Write(returnstring);

///////

int index = CustomAttributeStruct[ii].value;

int howmanybytes,uncompressedbyte ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

if ( uncompressedbyte == 0)

{

Console.WriteLine();

continue;

}

index = index + howmanybytes;

byte [] blobarray = new byte[uncompressedbyte];

Array.Copy(blob , index , blobarray , 0 , uncompressedbyte);

bool displayoneline = true;

string displaystring = "";

for ( int  jj = 0 ; jj < uncompressedbyte ; jj++)

{

if ( blobarray[jj] < 0x20)

displayoneline = false;

if ( blobarray[jj] >= 0x7f)

displayoneline = false;

}

if ( displayoneline)

{

displaystring = " = \"";

for ( int  jj = 0 ; jj < uncompressedbyte ; jj++)

{

displaystring = displaystring + (char)blobarray[jj];

}

displaystring = displaystring + "\"";

if ( tname == "MemberRef")

Console.Write(displaystring);

else

Console.WriteLine(displaystring);

}

else

{

int startoffunctionclosebracket = returnstring.LastIndexOf(")");

int lastenter = returnstring.LastIndexOf("\r\n");

if ( lastenter == -1)

lastenter = -2;

int diff2 = startoffunctionclosebracket - lastenter + 19;

Console.Write(" = ( ");

DisplayFormattedColumns(CustomAttributeStruct[ii].value,diff2 , false , false);

}

}

}

}

public void abc(string [] args)

{

ReadPEStructures(args);

DisplayPEStructures();

ReadandDisplayImportAdressTable();

ReadandDisplayCLRHeader();

ReadStreamsData();

FillTableSizes();

ReadTablesIntoStructures();

DisplayTablesForDebugging();

ReadandDisplayVTableFixup();

ReadandDisplayExportAddressTableJumps();

FillArray();

FillOpCodeArray();

CreateSignatures();

DisplayModuleRefs();

DisplayAssembleyRefs();

DisplayAssembley();

DisplayFileTable();

DisplayClassExtern();

DisplayResources();

DisplayModuleAndMore();

DispalyVtFixup();

DisplayTypeDefs();

DisplayTypeDefsAndMethods();

}

public void DisplayFormattedColumns( int index , int startingspaces , bool putonespace , bool opcode)

{

int howmanybytes,uncompressedbyte ;

if ( opcode )

{

howmanybytes = CorSigUncompressData(us, index , out uncompressedbyte);

uncompressedbyte = uncompressedbyte - 1;

}

else

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

int token = index;

index = index + howmanybytes;

byte [] blobarray = new byte[uncompressedbyte];

if ( opcode )

Array.Copy(us, index , blobarray , 0 , uncompressedbyte);

else

Array.Copy(blob , index , blobarray , 0 , uncompressedbyte);

int maincounter = 0;

while ( maincounter < uncompressedbyte )

{

string firststring = "";

string secondstring = "";

int counterforascii = 0;

int ii ;

bool noascii = false;

for ( counterforascii = 0 ; counterforascii < 16 ; counterforascii++)

{

if ( maincounter == uncompressedbyte )

break;

if ( blobarray[maincounter] >= 0x20 && blobarray[maincounter] <= 0x7e)

noascii = true;

maincounter++;

}

maincounter -= counterforascii;

for ( ii = 0 ; ii < 16 ; ii++)

{

if ( maincounter == uncompressedbyte )

break;

firststring = firststring + blobarray[maincounter].ToString("X2") + " ";

if ( blobarray[maincounter] >= 0x20 && blobarray[maincounter] <= 0x7e)

secondstring = secondstring + (char)blobarray[maincounter];

else

secondstring = secondstring + ".";

maincounter++;

}

if ( maincounter == uncompressedbyte )

{

int leftovers = maincounter% 16;

if ( leftovers != 0)

{

leftovers = 15 - leftovers;

firststring = firststring + ")" ;

int space = leftovers*3 + 3;

if ( noascii )

firststring = firststring + CreateSpaces(space);

else

firststring = firststring + " ";

}

else

{

firststring = firststring + ")";

if ( putonespace && uncompressedbyte <= 16)

firststring = firststring + " ";

firststring = firststring + CreateSpaces(0);

}

}

if ( maincounter == uncompressedbyte )

{

if ( noascii )

firststring = firststring + " // " + secondstring;

if ( uncompressedbyte == 16 && !noascii && opcode)

firststring = firststring + "  /* 70" + token.ToString("X6") + " */";

else if ( opcode )

firststring = firststring + " /* 70" + token.ToString("X6") + " */";

}

else

{

if ( noascii )

firststring = firststring + "  // " + secondstring;

}

if ( maincounter == uncompressedbyte && opcode)

Console.Write(firststring);

else

Console.WriteLine(firststring);

if ( maincounter != uncompressedbyte )

Console.Write(CreateSpaces(startingspaces));

}

}

public string DecodeMemberRefToken (int token , int methodindex , OpCode opcode )

{

string returnstring = "";

//Console.WriteLine(".......{0}" , token.ToString("X"));

if ( token >= MemberRefStruct.Length )

return " $MR$" + token.ToString("X2") + "() /* 0A0000" + token.ToString("X2") + " */";

int row = MemberRefStruct[token].clas;

string codedindextable = GetMemberRefParentCodedIndexTable(row);

int codedindexrow = row >> 3;

string initialstring = "";

//Console.WriteLine(".......{0}" , codedindextable);

if ( codedindextable == "ModuleRef")

{

initialstring = methodreftypearray[token] + methodrefreturnarray[token] + " ";

string name = NameReserved(GetString(ModuleRefStruct[codedindexrow].name));

initialstring = initialstring + "[.module " + name + "/* 1A" + codedindexrow.ToString("X6") + " */]" ;

}

if ( codedindextable == "TypeSpec") //arrays.exe

{

string returnarray = methodrefreturnarray[token];

string typeplusreturn  = methodreftypearray[token] + returnarray;

string types = CreateSignatureForTypeSpec(codedindexrow);

types = types.Replace("^",",");

initialstring = typeplusreturn  + " " + types ;

}

else if ( codedindextable == "MethodDef")

{

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

int typeindex = GetTypeForMethod(codedindexrow);

initialstring = initialstring + typedefnames[typeindex];

}

else if ( codedindextable == "TypeRef")

{

if ( opcode.Name == "ldtoken")

{

int typeindex1 = 0;

string typename = NameReserved(GetString(TypeRefStruct[codedindexrow].name));

string typenamespace = NameReserved(GetString(TypeRefStruct[codedindexrow].nspace));

for ( int typecnt = 1 ; typecnt < TypeDefStruct.Length ; typecnt++)

{

if ( typename == NameReserved(GetString(TypeDefStruct[typecnt].name)) && typenamespace == NameReserved(GetString(TypeDefStruct[typecnt].nspace)))

{

typeindex1 = typecnt;

//Console.WriteLine("...{0}" , typename , );

break;

}

}

int start , startofnext;

start =  TypeDefStruct[typeindex1].findex ;

if ( typeindex1 == (TypeDefStruct.Length - 1) )

startofnext= FieldStruct.Length;

else

startofnext = TypeDefStruct[typeindex1+1].findex ;

bool found = false;

for ( int fieldindex = start ; fieldindex < startofnext ; fieldindex++)

{

string name = NameReserved(GetString(MemberRefStruct[token].name));

if ( name == NameReserved(GetString(FieldStruct[fieldindex].name)))

{

found = true;

break;

}

}

if ( found )

initialstring = "field ";

else

initialstring = "method ";

}

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

initialstring = initialstring + typerefnames[codedindexrow];

//Console.WriteLine("......{0} {1}" , codedindexrow , typerefnames[codedindexrow] );

}

else if ( codedindextable == "TypeDef")

{

if ( opcode.Name == "ldtoken")

initialstring = "field ";

initialstring = initialstring + methodreftypearray[token] + methodrefreturnarray[token] + " ";

initialstring = initialstring + typedefnames[codedindexrow];

}

string methodparmarraystring = methodrefparamarray1[token];

string nameplusparams = "";

if ( methodparmarraystring != null)

{

nameplusparams =  NameReserved(GetString(MemberRefStruct[token].name))  + "(";

int len = 51 + spacesforrest+2+ spacesfortry + spacesfornested + nameplusparams.Length + initialstring.Length + 2;

nameplusparams = nameplusparams + ParamOnMultipleLines(methodparmarraystring,len);

nameplusparams = nameplusparams + ")";

}

else

nameplusparams =  NameReserved(GetString(MemberRefStruct[token].name))  ;

returnstring = initialstring + "::" +  nameplusparams + " /* 0A" + token.ToString("X6") + " */";

return returnstring;

}

public string DecodeMemberDefToken (int token , OpCode opcode)

{

string returnstring = "";

if ( token >= MethodStruct.Length)

return returnstring;

string name = NameReserved(GetString(MethodStruct[token].name));

string methodattributes = GetMethodAttribute(MethodStruct[token].flags , token );

if ( methodattributes.IndexOf("privatescope ") != -1)

name = name + "$PST06" + token.ToString("X6");

int typeindex = GetTypeForMethod(token);

if ( opcode.Name == "ldtoken")

returnstring = "method ";

returnstring = returnstring + methoddeftypearray[token] + methoddefreturnarray[token] + typedefnames[typeindex] ;

returnstring = returnstring + "::" + name + "(" ;

int len = returnstring.Length + 53 + spacesforrest + spacesfortry + spacesfornested;

string sfinal = methoddefparamarray1[token];

returnstring = returnstring + ParamOnMultipleLines(sfinal , len )  + ")";

returnstring = returnstring + " " + "/* 06" + token.ToString("X6") + " */";

return returnstring;

}

public void DecodeTokenIL (int token , OpCode opcode , int methodindex , string strings , out int seriouserror )

{

seriouserror = 0;

int originaltoken = token;

int table = (int)(token & 0xff000000);

table = table >> 24;

token = token & 0x00ffffff;

//if ( opcode.Name == "ldtoken")

//Console.WriteLine("........");

if ( table == 4 && token > FieldStruct.Length )

{

Console.Write("     ********* ERROR DISASSEMBLING THE METHOD IL CODE ***********");

seriouserror = 1;

return ;

}

if ( table == 1 && token > TypeRefStruct.Length )

{

Console.Write("     ********* ERROR DISASSEMBLING THE METHOD IL CODE ***********");

seriouserror = 1;

return ;

}

Console.Write(strings);

if ( table == 0)

{

Console.Write("({0}){1}       */ {2}{3}0x{4} " , table.ToString("X2") ,token.ToString("X6"), opcode.Name, CreateSpaces(11-opcode.Name.Length) , token.ToString("X2") );

}

if ( table >= 60 || table < 0)

{

byte dummybyte = (byte) table;

string returnstring =  "("  + dummybyte.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

Console.Write(returnstring);

int len = 31 - returnstring.Length;

Console.Write(CreateSpaces(len));

Console.Write("<unknown token type 0x" + dummybyte.ToString("x2") + ">");

}

if (table == 0x01)

{

string returnstring  = "(01)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + typerefnames[token];

Console.Write(returnstring);

}

if ( table == 0x02)

{

string returnstring = "(02)" + token.ToString("X6") + "       */ " + opcode.Name;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + typedefnames[token];

Console.Write(returnstring);

}

if (table == 0x06) //Method

{

string returnstring = "(06)" + token.ToString("X6") + "       */ " + opcode.Name;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberDefToken(token , opcode);

Console.Write(returnstring);

}

if ( table == 0x04)

{

string returnstring =  "("  + table.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

Console.Write(returnstring);

int typeindex = GetTypeForField(token);

if ( opcode.Name == "ldtoken" )

Console.Write("    field ");

else

{

int len = opcode.Name.Length;

Console.Write(CreateSpaces(11-len));

}

Console.Write(fieldparamarray[token]);

string finalstring = typedefnames[typeindex];

Console.Write(" {0}::" , finalstring , typeindex.ToString("X6"));

string name = NameReserved(GetString(FieldStruct[token].name));

if (fieldflagsarray[token].IndexOf("privatescope ") != -1)

name = name + "$PST04" + token.ToString("X6");

name = name + " /* 04" + token.ToString("X6") + " */";

Console.Write(name);

}

if (table == 0x0a) //MemberRef

{

string returnstring = "(0A)" + token.ToString("X6") + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

returnstring = returnstring + CreateSpaces(11-len) + DecodeMemberRefToken(token , methodindex , opcode );

Console.Write(returnstring);

}

if ( table == 0x11) //StandAlonesig

{

int b1 = token & 0xff;

int b2 = (token & 0xff00) >> 8;

int b3 = (token & 0xff0000) >> 16;

string returnstring =  b1.ToString("X2") + b2.ToString("X2") + b3.ToString("X2") + table.ToString("X2");

returnstring = returnstring + "         */ " + opcode.Name + "      ";

string dummy = CreateSignatureForCalli(token);

int len = opcode.Name.Length;

if ( dummy == "error")

returnstring = "(" + table.ToString("X2") + ")" + token.ToString("X6") + "       */ " + opcode.Name + CreateSpaces(11-len) + "<unknown token type 0x" + table.ToString("X2")+">" ;

else

returnstring = returnstring + dummy + " /*" + originaltoken.ToString("X8") + "*/";

Console.Write(returnstring);

}

if ( table == 0x1b) // Typespec

{

string returnstring =  "("  + table.ToString("X2") + ")" + token.ToString("X6");

returnstring = returnstring + "       */ " + opcode.Name ;

int len = opcode.Name.Length;

string types =  CreateSignatureForTypeSpec(token);

types = types.Replace("^",",");

returnstring = returnstring + CreateSpaces(11-len) + types ;

Console.Write(returnstring);

}

}

public string CreateSignatureForCalli(int row)

{

int aa = -1;

int howmanybytes,uncompressedbyte , count;

if ( row >= StandAloneSigStruct.Length)

return "error";

int index = StandAloneSigStruct[row].index ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blobarray = new byte[count];

Array.Copy(blob , index + howmanybytes , blobarray , 0 , count);

if ( row == aa)

{

for ( int i = 0 ; i < count ; i++)

Console.Write("{0} " , blobarray[i].ToString("X"));

Console.WriteLine();

}

string types = DecodeFirstByteofMethodSignature ( blobarray[0] , row);

index = 1;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

count = uncompressedbyte;

index = index + howmanybytes ;

string returnstring =types;

int dummyint1;

returnstring = returnstring + GetElementType( index , blobarray , out dummyint1 , 0 , "");

index = index + dummyint1;

returnstring = returnstring + "(";

for ( int l = 1 ; l <= count ; l++)

{

if ( blobarray[index] == 0x41 )

{

returnstring = returnstring + "...,";

index = index + 1;

}

string dummy = GetElementType(index , blobarray , out howmanybytes ,0 , "");

returnstring = returnstring + dummy ;

if ( l != count )

returnstring = returnstring + ",";

index = index + howmanybytes;

}

if ( index < blobarray.Length && blobarray[index] == 0x41)

returnstring = returnstring +  ",..." ;

returnstring = returnstring + ")";

return returnstring;

}

public string CreateSignatureForTypeSpec(int row)

{

string returnstring = "";

int howmanybytes,uncompressedbyte , count;

int index = TypeSpecStruct[row].signature ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blobarray = new byte[count];

Array.Copy(blob , index + howmanybytes , blobarray , 0 , count);

/*

Console.WriteLine(".........{0} {1} {2} {3}" , count , blob[index] ,blob[index+1], blob[index+2] );

for ( int i = 0 ; i < count ; i++)

Console.Write("{0} " , blobarray[i]);

Console.WriteLine();

*/

returnstring = GetElementType( 0 , blobarray , out howmanybytes ,0 , "");

return returnstring;

}

public string GetParamNameForMethod(int row , int count , int l)

{

string returnstring = "";

string mattributes = GetMethodAttribute(MethodStruct[row].flags , row);

if ( ParamStruct == null)

{

//isnan.exe

if ( mattributes.IndexOf("static") != -1)

l--;

return  "A_" + l.ToString();

}

int start , startofnext=0 , paramcount;

start =  MethodStruct[row].param ;

if ( row  == (MethodStruct.Length -1) )

startofnext= ParamStruct.Length;

else

startofnext = MethodStruct[row+1].param;

paramcount =   startofnext - start;

int ind;

bool paramfound = false;

for ( ind = start ; ind < startofnext ; ind++)

{

if ( ParamStruct[ind].sequence == l)

{

paramfound = true;

break;

}

}

//if ( ind < paramnames.Length && && paramfound)

if ( paramfound && paramnames[ind] != "" )

{

returnstring = NameReserved(paramnames[ind]);

}

else

{

//Interop.orders.dll

if ( mattributes.IndexOf("static") != -1)

l--;

returnstring = "A_" + l.ToString();

}

return returnstring;

}

public void FillOpCodeArray()

{

OpCodesArray = new OpCode[256];

OpCodesArray1 = new OpCode[32];

FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

//Console.WriteLine("Name              Value OperandType          Flow         OpCode     Size");

foreach (FieldInfo f in fields)

{

OpCode o = (OpCode) f.GetValue(null);

//if ( o.OperandType  == OperandType.InlineField)

//Console.WriteLine("{0,-17} {1,5} {2,-20} {3,-12} {4,-10} {5}" , o.Name, o.Value.ToString("X") , o.OperandType , o.FlowControl , o.OpCodeType , o.Size);

if ( o.Value <= 255 && o.Value >= 0)

OpCodesArray[(short)o.Value] = o;

OpCodesArray1[(ushort) 0x00] = OpCodes.Arglist;

OpCodesArray1[(ushort) 0x01] = OpCodes.Ceq;

OpCodesArray1[(ushort) 0x02] = OpCodes.Cgt;

OpCodesArray1[(ushort) 0x03] = OpCodes.Cgt_Un;

OpCodesArray1[(ushort) 0x04] = OpCodes.Clt;

OpCodesArray1[(ushort) 0x05] = OpCodes.Clt_Un;

OpCodesArray1[(ushort) 0x06] = OpCodes.Ldftn;

OpCodesArray1[(ushort) 0x07] = OpCodes.Ldvirtftn;

OpCodesArray1[(ushort) 0x09] = OpCodes.Ldarg;

OpCodesArray1[(ushort) 0x0A] = OpCodes.Ldarga;

OpCodesArray1[(ushort) 0x0B] = OpCodes.Starg;

OpCodesArray1[(ushort) 0x0C] = OpCodes.Ldloc;

OpCodesArray1[(ushort) 0x0D] = OpCodes.Ldloca;

OpCodesArray1[(ushort) 0x0E] = OpCodes.Stloc;

OpCodesArray1[(ushort) 0x0F] = OpCodes.Localloc;

OpCodesArray1[(ushort) 0x11] = OpCodes.Endfilter;

OpCodesArray1[(ushort) 0x12] = OpCodes.Unaligned;

OpCodesArray1[(ushort) 0x13] = OpCodes.Volatile;

OpCodesArray1[(ushort) 0x14] = OpCodes.Tailcall;

OpCodesArray1[(ushort) 0x15] = OpCodes.Initobj;

OpCodesArray1[(ushort) 0x17] = OpCodes.Cpblk;

OpCodesArray1[(ushort) 0x18] = OpCodes.Initblk;

OpCodesArray1[(ushort) 0x1A] = OpCodes.Rethrow;

OpCodesArray1[(ushort) 0x1C] = OpCodes.Sizeof;

OpCodesArray1[(ushort) 0x1D] = OpCodes.Refanytype;

}

 

 

}

public void DisplayAllMethods (int typeindex)

{

if ( TypeDefStruct == null)

return;

if ( MethodStruct == null)

return;

int start , startofnext=0;

start =  TypeDefStruct[typeindex].mindex ;

if ( typeindex == (TypeDefStruct.Length -1) )

{

startofnext= MethodStruct.Length;

}

else

startofnext = TypeDefStruct[typeindex+1].mindex ;

for ( int methodindex = start ; methodindex < startofnext ; methodindex++)

{

string methodstring = CreateSpaces(spacesforrest);

if ( IsTypeNested(typeindex))

methodstring = methodstring + CreateSpaces(spacesfornested);

methodstring = methodstring  + ".method ";

methodstring = methodstring + "/*06" + methodindex.ToString("X6") + "*/ " ;

string methodattribute = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

int pos1 = methodattribute.IndexOf("instance");

if ( pos1 != -1)

methodattribute = methodattribute.Remove(pos1, 9);

string enterformethodattrbute = "";

string enterforreturnvalue = "";

string enterformarshal = "";

string paramattrstring = "";

string parammarshalstring = "";

paramattrstring = GetParamAttrforMethodCalling(methodindex);

parammarshalstring = GetParamAttrforMethodMarshal(methodindex , 0 );

string nspace= "";

nspace= NameReserved(GetString(TypeDefStruct[typeindex].nspace));

int parenttype = GetParentForNestedType(typeindex);

if ( parenttype  != 0)

nspace = NameReserved(GetString(TypeDefStruct[parenttype].nspace));

bool cat2return = false;

bool cat3returnvaluemarshal = false;

bool cat4 = false;

int howmany = HowManyMethodAttributes(methodattribute);

if ( parammarshalstring == "" )

{

if ( methodattribute == "public static " && !(IsTypeNested(typeindex) && nspace != "" ) )

cat2return = true;

if ( methodattribute == "private static " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "family static " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "assembly static " && !IsTypeNested(typeindex) && nspace == "" )

cat2return = true;

if ( methodattribute == "public virtual " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "private virtual " && !IsTypeNested(typeindex) && nspace == "")

cat2return = true;

if ( methodattribute == "family virtual " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "public newslot " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "private newslot " && !IsTypeNested(typeindex) && nspace == "")

cat2return = true;

if ( methodattribute == "family newslot " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "public final "  )

cat2return = true;

if ( methodattribute == "private final " && !(IsTypeNested(typeindex) && nspace != "") )

cat2return = true;

if ( methodattribute == "family final " )

cat2return = true;

if ( methodattribute == "public abstract " && !IsTypeNested(typeindex) && nspace == "") 

cat2return = true;

if ( methodattribute == "private abstract " && !IsTypeNested(typeindex) && nspace == "")

cat2return = true;

if ( methodattribute == "family abstract " && !IsTypeNested(typeindex) && nspace == "") 

cat2return = true;

if ( methodattribute == "public hidebysig " && !IsTypeNested(typeindex) && nspace == "" )

cat2return = true;

if ( methodattribute == "family hidebysig " && !IsTypeNested(typeindex) && nspace == "" )

cat2return = true;

if ( methodattribute.IndexOf("pinvokeimpl") == -1)

{

if ( howmany == 0 && methoddeftypearray[methodindex].IndexOf("instance ") != -1 )

cat2return = true;

}

}

int aa = 0x00;

if ( parammarshalstring != ""  )

{

if ( methodattribute == "public hidebysig " && nspace == "" && !IsTypeNested(typeindex))

cat3returnvaluemarshal = true;

if ( methodattribute == "family hidebysig " && nspace == "" && !IsTypeNested(typeindex))

cat3returnvaluemarshal = true;

if ( methodattribute == "public virtual " && nspace != "" && !IsTypeNested(typeindex))

cat3returnvaluemarshal = true;

if ( methodattribute == "public virtual " && nspace == "" && !IsTypeNested(typeindex))

cat3returnvaluemarshal = true;

if ( methodattribute == "public virtual " && nspace == "" && IsTypeNested(typeindex))

cat3returnvaluemarshal = true;

if ( methodattribute == "public static " && ! (IsTypeNested(typeindex) && nspace != ""))

cat3returnvaluemarshal = true;

if ( methodattribute == "private static " && ! (IsTypeNested(typeindex) && nspace != ""))

cat3returnvaluemarshal = true;

if ( methodattribute == "family static " && ! (IsTypeNested(typeindex) && nspace != ""))

cat3returnvaluemarshal = true;

 

if ( methodattribute == "assembly static " && !IsTypeNested(typeindex) && nspace == "")

cat3returnvaluemarshal = true;

if ( howmany == 0 && methoddeftypearray[methodindex] == "instance " )

cat3returnvaluemarshal = true;

}

if (parammarshalstring != "" && methodattribute.IndexOf("pinvokeimpl") == -1)

{

if ( methodattribute == "public virtual " && nspace != "" && IsTypeNested(typeindex))

cat4 = true;

if ( howmany == 0 && IsTypeNested(typeindex) && nspace != "" && methoddeftypearray[methodindex] == "" )

{

bool problem1 = true;

if ( methodindex == aa)

Console.WriteLine("....{0} {1}.." , methoddefreturnarray[methodindex].Length , methoddefreturnarray[methodindex]);

if ( methodattribute == "assembly static " || methodattribute == "public static " || methodattribute == "private static " ||  methodattribute == "family static " )

{

if ( paramattrstring == "" )

problem1 = false;

}

if ( problem1)

cat4 = true;

}

if ( methodattribute.IndexOf("hidebysig") != -1)

{

if ( methodattribute.IndexOf("public") != -1 || methodattribute.IndexOf("family") != -1)

{

if ( IsTypeNested(typeindex) || nspace != "" )

cat4 = true;

}

else

cat4 = true;

}

if ( howmany >= 2  )

cat4 = true;

}

if ( cat2return )

{

enterformethodattrbute = "";

enterforreturnvalue = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

enterformarshal = "";

}

else if ( cat3returnvaluemarshal)

{

enterformethodattrbute = "";

enterforreturnvalue = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

enterformarshal = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

}

else if ( cat4)

{

enterformethodattrbute = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

enterforreturnvalue = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

enterformarshal = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

}

else

{

enterformethodattrbute = "\r\n" + CreateSpaces(spacesforrest + 8 + spacesfornested);

enterforreturnvalue = " ";

if (parammarshalstring != "")

enterformarshal = " ";

}

methodstring = methodstring + methodattribute + enterformethodattrbute;

methodstring = methodstring + methoddeftypearray[methodindex] + paramattrstring ;

methodstring = methodstring + methoddefreturnarray[methodindex] + enterforreturnvalue;

methodstring = methodstring +  parammarshalstring + enterformarshal ;

if ( methodstring.Length - methodstring.LastIndexOf("\r\n") >= 44 )

{

methodstring = methodstring.Remove(methodstring.Length-1,1);

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 8+ spacesfornested);

}

methodstring = methodstring + NameReserved(GetString(MethodStruct[methodindex].name)) ;

if ( methodattribute.IndexOf("privatescope") != -1)

methodstring = methodstring + "$PST06" + methodindex.ToString("X6");

methodstring = methodstring + "(";

int len = 0;

if ( methoddefparamarray[methodindex] != null)

{

int indexofenter = methodstring.LastIndexOf("\r\n");

int lengthofstring = methodstring.Length ;

len = lengthofstring - indexofenter - 2;

methodstring = methodstring + ParamOnMultipleLines(methoddefparamarray[methodindex] , len );

}

methodstring = methodstring  +  ")";

string implflags = GetMethodAttribute1(MethodStruct[methodindex].impflags);

methodstring = methodstring + " " + implflags ;

string methodsignature = GetMethodSignatureBytes(methodindex);

methodstring = methodstring + methodsignature;

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest+ spacesfornested) + "{" ;

int tablerow = entrypointtoken & 0x00ffffff;

if ( tablerow == methodindex )

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + ".entrypoint";

Console.WriteLine(methodstring);

DisplayCustomAttribute("MethodDef" , methodindex , 2 + spacesforrest + spacesfornested);

DisplayParamsForMethod(methodindex);

DisplayAllSecurity( 1 , methodindex );

DisplayOverrideMethod(methodindex); // interfaces.exe

if (implflags.IndexOf("cil managed") == -1 || MethodStruct[methodindex].rva == 0)

{

bool problem1 = true;

if ( methodattribute.IndexOf("pinvokeimpl") != -1 )

{

if ( methodattribute.IndexOf("pinvokeimpl(/* No map */)") != -1)

{

Console.WriteLine("  // Embedded native code");

Console.WriteLine("  //  Disassembly of native methods is not supported.");

Console.WriteLine("  //  Managed TargetRVA = 0x{0}" , MethodStruct[methodindex].rva.ToString("x4"));

Console.WriteLine(CreateSpaces(spacesforrest+ spacesfornested) + "} // end of global method " +  NameReserved(GetString(MethodStruct[methodindex].name)));

}

else

{

methodstring = CreateSpaces(spacesforrest+ spacesfornested) + "}"  ;

Console.Write(methodstring);

}

methodstring = "";

problem1 = false;

}

else if (implflags.IndexOf("runtime managed") != -1)

{

methodstring = "";

}

else if (implflags.IndexOf("runtime unmanaged") != -1)

methodstring = "    //  Method provided by Runtime\r\n";

else if (implflags.IndexOf("native unmanaged") != -1)

methodstring = "    //  Unmanaged TargetRVA = 0x" + MethodStruct[methodindex].rva.ToString("x4") + "\r\n";

else if ( implflags.IndexOf("native") != -1)

{

methodstring = "    //  Disassembly of native methods is not supported.";

methodstring = methodstring + "\r\n    //  Managed TargetRVA = 0x" +  MethodStruct[methodindex].rva.ToString("x4") + "\r\n";

}

else if ( MethodStruct[methodindex].rva == 0 && implflags.IndexOf("unmanaged") == -1 )

{

methodstring = CreateSpaces(spacesforrest+ spacesfornested + 2) + "// Method begins at RVA 0x0\r\n";

}

else if ( implflags.IndexOf("optil") != -1 )

{

methodstring = CreateSpaces(spacesforrest+ spacesfornested + 2) + "// Method begins at RVA 0x" +  MethodStruct[methodindex].rva.ToString("x4") + "\r\n";

methodstring = methodstring + CreateSpaces(spacesforrest+ spacesfornested + 2) + "// Code size       0 (0x0)\r\n";

}

else

{

methodstring = "";

}

if (problem1)

methodstring = methodstring + CreateSpaces(spacesforrest+ spacesfornested) + "} // end of method " + NameReserved(GetString(TypeDefStruct[typeindex].name)) + "::" + NameReserved(GetString(MethodStruct[methodindex].name)) + "\r\n";

Console.WriteLine(methodstring);

continue;

}

string vtentrystring = GetVtentryString(methodindex);

methodstring = vtentrystring;

methodstring = methodstring + CreateSpaces(spacesforrest + 2 + spacesfornested) +  "// Method begins at RVA 0x" + MethodStruct[methodindex].rva.ToString("x4");

Console.Write(methodstring);

long fileoffset = ConvertRVA(MethodStruct[methodindex].rva);

mfilestream.Seek(fileoffset , SeekOrigin.Begin);

DisplayFatFormat(NameReserved(GetString(TypeDefStruct[typeindex].name)) , NameReserved(GetString(MethodStruct[methodindex].name)) ,  methodindex  );

}

}

public void DisplayFatFormat ( string classname , string methodname , int methodindex )

{

DisplayInitialMethodHeader(methodindex);

DisplayMethodILCode(classname , methodname , methodindex );

}

public void DisplayInitialMethodHeader (int methodindex)

{

int tiny = mbinaryreader.ReadByte();

if ( (tiny & 0x03) == 0x03)

tinyformat = false;

else

tinyformat = true;

mfilestream.Seek(-1,SeekOrigin.Current);

string methodstring = "";

if ( !tinyformat )

{

long where = mfilestream.Position;

short first = mbinaryreader.ReadInt16();

first12 = (short)(first & 0x0fff);

short first4 = (short)(first & 0xf000);

first4 = (short) (first4 >> 12);

short stacksize = mbinaryreader.ReadInt16();

codesize = mbinaryreader.ReadInt32();

methodstring =  "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + "// Code size       " + codesize.ToString() + " (0x" + codesize.ToString("x") + ")\r\n";

if ( (first12&0x08) == 0x08 )

ReadExceptions(where , codesize , methodindex );

methodstring = methodstring + CreateSpaces(spacesforrest + 2+ spacesfornested) + ".maxstack  " + stacksize.ToString();

int standalonesig = mbinaryreader.ReadInt32();

int rowstandalonesig = standalonesig  & 0x00ffffff;

//Console.WriteLine(".......{0} " , rowstandalonesig);

if (StandAloneSigStruct != null && standalonesigarray == null)

standalonesigarray = new string[StandAloneSigStruct.Length];

 

if ( rowstandalonesig != 0 )

{

CreateSignatureForEachType(5 , StandAloneSigStruct[rowstandalonesig ].index , rowstandalonesig );

if ( standalonesigarray[rowstandalonesig ] != "")

{

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2+ spacesfornested) +  ".locals /*11" + rowstandalonesig.ToString("X6") + "*/ ";

if ((first12&0x10) == 0x10 )

methodstring = methodstring + "init (" ;

else

methodstring = methodstring + "(" ;

methodstring = methodstring + standalonesigarray[rowstandalonesig ];

methodstring = methodstring + ")";

}

}

}

else

{

mbinaryreader.ReadByte();

codesize = tiny >> 2;

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested ) +  "// Code size       " + codesize.ToString() + " (0x" + codesize.ToString("x") + ")";

if (codesize != 0)

methodstring = methodstring + "\r\n" + CreateSpaces(spacesforrest + 2+ spacesfornested) +  ".maxstack  8" ;

}

Console.WriteLine(methodstring);

}

 

public string DisplayParamsForMethod (int methodrow)

{

if ( ParamStruct == null)

return "";

string returnstring = "";

int start=0, end=0;

start = MethodStruct[methodrow].param;

if ( methodrow == (MethodStruct.Length - 1))

end = ParamStruct.Length  ;

else

end = MethodStruct[methodrow+1].param;

for ( int index = start ; index < end ; index++)

{

int seq = ParamStruct[index].sequence;

returnstring = CreateSpaces(spacesforrest+ spacesfornested+2) + ".param [" + seq.ToString() + "]" + "/*08" + index.ToString("X6") + "*/";

string str = DisplayFromConstantsTable(index ,0 ,"ParamDef");

if ( str != "")

Console.Write(returnstring + str );

bool b = HasCustomAttribute("ParamDef" , index);

if ( b && str == "")

Console.WriteLine(returnstring + " ");

DisplayCustomAttribute("ParamDef" , index , spacesforrest+ spacesfornested+2);

}

return "";

}

public int GetCustomAttributeTypevalue(int attributecodedtype)

{

return attributecodedtype >> 3;

}

public string GetCustomAttributeTypeTable( int attributecodedtype)

{

string returnstring = "";

int tag = attributecodedtype &  0x07;

if ( tag == 0)

returnstring = returnstring + "NotUsed";

if ( tag == 1)

returnstring = returnstring + "NotUsed";

if ( tag == 2)

returnstring = returnstring + "MethodDef";

if ( tag == 3)

returnstring = returnstring + "MethodRef";

if ( tag == 4)

returnstring = returnstring + "NotUsed";

return returnstring;

}

public int GetHasCustomAttributeValue( int attributecodedparent)

{

return attributecodedparent >> 5;

}

public string GetHasCustomAttributeTable ( int attributecodedparent)

{

string returnstring = "";

int tag = attributecodedparent & 0x1F;

if ( tag == 0)

returnstring = returnstring + "MethodDef";

if ( tag == 1)

returnstring = returnstring + "FieldDef";

if ( tag == 2)

returnstring = returnstring + "TypeRef";

if ( tag == 3)

returnstring = returnstring + "TypeDef";

if ( tag == 4)

returnstring = returnstring + "ParamDef";

if ( tag == 5)

returnstring = returnstring + "InterfaceImpl";

if ( tag == 6)

returnstring = returnstring + "MemberRef";

if ( tag == 7)

returnstring = returnstring + "Module";

if ( tag == 8)

returnstring = returnstring + "DeclSecurity";

if ( tag == 9)

returnstring = returnstring + "Property";

if ( tag == 10)

returnstring = returnstring + "Event";

if ( tag == 11)

returnstring = returnstring + "Signature";

if ( tag == 12)

returnstring = returnstring + "ModuleRef";

if ( tag == 13)

returnstring = returnstring + "TypeSpec";

if ( tag == 14)

returnstring = returnstring + "Assembly";

if ( tag == 15)

returnstring = returnstring + "AssemblyRef";

if ( tag == 16)

returnstring = returnstring + "File";

if ( tag == 17)

returnstring = returnstring + "ExportedType";

if ( tag == 18)

returnstring = returnstring + "ManifestResource";

return returnstring;

}

 

public void CreateSignatures ()

{

//StandAloneSig

//MethodTable

if (MethodStruct != null)

{

methoddefreturnarray = new string[MethodStruct.Length];

methoddefparamarray  = new string[MethodStruct.Length];

methoddefparamarray1  = new string[MethodStruct.Length];

methoddeftypearray  = new string[MethodStruct.Length];

methoddefparamcount = new int[MethodStruct.Length];

for ( int l = 1 ; l < MethodStruct.Length ; l++)

{

CreateSignatureForEachType(1 , MethodStruct[l].signature, l);

}

}

//MethodRefTable

if ( MemberRefStruct != null )

{

methodreftypearray = new string[MemberRefStruct.Length];

methodrefreturnarray = new string[MemberRefStruct.Length];

methodrefparamarray1  = new string[MemberRefStruct.Length];

for ( int l = 1 ; l < MemberRefStruct.Length ; l++)

{

CreateSignatureForEachType(2 , MemberRefStruct[l].sig, l);

}

}

//fieldtable

if ( FieldStruct != null )

{

fieldflagsarray = new string[FieldStruct.Length];

fieldparamarray  = new string[FieldStruct.Length];

for ( int l = 1 ; l < FieldStruct.Length ; l++)

{

CreateSignatureForEachType(6, FieldStruct[l].sig, l);

}

}

//propertytable

if ( PropertyStruct != null )

{

propertyparmarray = new string[PropertyStruct.Length];

propertyreturnarray = new string[PropertyStruct.Length];

propertytypearray  = new string[PropertyStruct.Length];

for ( int l = 1 ; l < PropertyStruct.Length ; l++)

{

CreateSignatureForEachType(7, PropertyStruct[l].type, l);

}

}

}

public void CreateSignatureForEachType (byte type , int index , int row)

{

int uncompressedbyte , count , howmanybytes;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

count = uncompressedbyte;

byte [] blob1 = new byte[count];

Array.Copy(blob , index + howmanybytes , blob1 , 0 , count);

if ( type == 7)

CreatePropertySignature(blob1 , row);

if ( type == 6)

CreateFieldSignature(blob1 , row);

if ( type == 5)

CreateLocalVarSignature(blob1 , row);

if ( type == 1)

CreateMethodDefSignature(blob1 , row);

if ( type == 2)

CreateMethodRefSignature(blob1 , row);

}

public void DisplayOneType (int typedefindex)

{

DisplayOneTypeDefStart(typedefindex);

DisplaySizeAndPack(typedefindex);

DisplayCustomAttribute("TypeDef" , typedefindex , 2 + spacefornamespace + spacesfornested);

DisplayAllSecurity( 0 , typedefindex);

DisplayNestedTypes(typedefindex);

DisplayOverride(typedefindex);

DisplayAllFields(typedefindex);

DisplayAllMethods(typedefindex);

DisplayAllEvents(typedefindex);

DisplayAllProperties(typedefindex);

DisplayOneTypeDefEnd(typedefindex );

}

public void DisplayAllFields (int typeindex)

{

if ( FieldStruct == null )

return;

int start , startofnext=0;

start =  TypeDefStruct[typeindex].findex ;

if ( typeindex == (TypeDefStruct.Length - 1) )

startofnext= FieldStruct.Length;

else

startofnext = TypeDefStruct[typeindex+1].findex ;

string returnstring = "";

for ( int fieldindex = start ; fieldindex < startofnext ; fieldindex++)

{

if ( NameReserved(GetString(FieldStruct[fieldindex].name)) == "_Deleted")

continue;

if ( typeindex == 1)

returnstring = "";

else

returnstring = CreateSpaces(spacesfornested + spacesforrest) ;

returnstring = returnstring + ".field /*04" + fieldindex.ToString("X6") + "*/" ;

returnstring = returnstring + " "  + fieldflagsarray[fieldindex]  +  fieldparamarray[fieldindex] +  " " + NameReserved(GetString(FieldStruct[fieldindex].name)) ;

if ( fieldindex < fieldflagsarray.Length && fieldflagsarray[fieldindex] != null && fieldflagsarray[fieldindex].IndexOf("privatescope") != -1 )

{

string ss = GetString(FieldStruct[fieldindex].name);

if ( ss.Length == 1 && (byte)ss[0] == 1)

{

returnstring = returnstring.Remove(returnstring.Length-1,1);

returnstring  = returnstring + "$PST04" + fieldindex.ToString("X6") + "'";

}

else

returnstring = returnstring + "$PST04" + fieldindex.ToString("X6");

}

string fieldrva = GetFieldRVA(fieldindex);

if ( fieldrva != "")

returnstring = returnstring + " at" + fieldrva;

int len = returnstring.Length;

Console.Write(returnstring);

GetFieldConstantValue(fieldindex , len );

DisplayCustomAttribute("FieldDef" , fieldindex , spacesfornested + spacesforrest);

}

}

/////

 

public void DisplayAllEvents(int typeindex)

{

int ii;

if ( EventMapStruct == null  )

return;

for ( ii = 1 ; ii < EventMapStruct.Length ; ii++)

{

if ( typeindex == (EventMapStruct[ii].index ) )

break;

}

if ( ii == EventMapStruct.Length)

return;

int start = EventMapStruct[ii].eindex;

int end;

if ( ii == EventMapStruct.Length -1 )

end = EventStruct.Length - 1;

else

end =  EventMapStruct[ii + 1].eindex -1;

for ( int eventrow = start ; eventrow <= end ; eventrow++)

{

Console.Write(CreateSpaces(spacesforrest + spacesfornested));

Console.Write(".event /*14{0}*/ {1}" , (eventrow).ToString("X6") , GetPropertyAttribute( EventStruct[eventrow].attr));

string name = NameReserved(GetString(EventStruct[eventrow].name)) ;

string codedtablename = GetTypeDefOrRefTable(EventStruct[eventrow].coded) ;

int codedindex = GetTypeDefOrRefValue(EventStruct[eventrow].coded);

string returnstring = "";

if ( codedtablename == "TypeRef")

returnstring = typerefnames[codedindex] + " /*01" + codedindex.ToString("X6") + "*/";

if ( codedtablename == "TypeDef")

returnstring = typedefnames[codedindex] + " /*02" + codedindex.ToString("X6") + "*/";

Console.Write(returnstring);

Console.Write(" " + name) ;

Console.WriteLine();

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.WriteLine("{");

DisplayCustomAttribute("Event" , eventrow , spacesfornested + spacesforrest+2);

for ( int kk = 1 ; kk < MethodSemanticsStruct.Length ; kk++)

{

string attributes = GetMethodSemanticsAttributes(MethodSemanticsStruct[kk].methodsemanticsattributes);

string table = GetHasSemanticsTable(MethodSemanticsStruct[kk].association);

int eventindex = GetHasSemanticsValue(MethodSemanticsStruct[kk].association);

int methodindex = MethodSemanticsStruct[kk].methodindex;

string methodattribute = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

if ( eventindex == eventrow && table == "Event" )

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfornested));

Console.Write("{0} {1}{2}",  attributes , methoddeftypearray[methodindex],  methoddefreturnarray[methodindex] );

string name1 = NameReserved(GetString(MethodStruct[methodindex].name));

 

Console.Write("{0}::{1}({2})" , typedefnames[typeindex], name1 , methoddefparamarray1[methodindex]);

Console.WriteLine(" /* 06{0} */" , (methodindex).ToString("X6"));

}

}

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("} ");

Console.WriteLine("// end of event {0}::{1}" , NameReserved(GetString(TypeDefStruct[typeindex].name)) , name);

}

}

 

public string GetPropertyAttributeDefault(int flags, int row)

{

string returnstring = "";

if ( (flags&0x1000) == 0x1000)

{

returnstring = DisplayFromConstantsTable( row , 0 ,"Property");

returnstring = returnstring.Remove(returnstring.Length-2,2);

}

return returnstring;

}

public void CreatePropertySignature (byte [] blobarray , int row)

{

int aa = -1;

if ( row == aa)

{

for ( int l = 0 ; l < blobarray.Length ; l++)

Console.Write("{0} " , blobarray[l].ToString("X"));

Console.WriteLine();

}

int howmanybytes , uncompressedbyte;

int index = 0;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + howmanybytes;

if ( (uncompressedbyte&0x20) == 0x20)

propertytypearray[row] = "instance ";

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + howmanybytes;

int count = uncompressedbyte;

string typestring = "";

string returnstring = "";

returnstring = GetElementType( index , blobarray , out howmanybytes , 0 , "") ;

propertyreturnarray[row] = returnstring;

index = index + howmanybytes;

returnstring = "";

for ( int l = 1 ; l <= count ; l++)

{

typestring = GetElementType( index , blobarray , out howmanybytes , 0 , "") ;

returnstring = returnstring + typestring;

index = index + howmanybytes;

if ( l != count)

returnstring = returnstring + ",";

}

propertyparmarray[row] = returnstring;

}

public string GetPropertyAttribute(int flags )

{

string returnstring = "";

if ( (flags&0x200) == 0x200 )

returnstring = returnstring + "specialname ";

if ( (flags&0x400) == 0x400 )

returnstring = returnstring + "rtspecialname ";

return returnstring ;

}

public void DisplayAllProperties (int typeindex)

{

int ii;

if ( PropertyMapStruct == null || PropertyStruct == null )

return;

for ( ii = 1 ; ii < PropertyMapStruct.Length ; ii++)

{

if ( typeindex == (PropertyMapStruct[ii].parent) )

break;

}

if ( ii == PropertyMapStruct.Length)

return;

int start = PropertyMapStruct[ii].propertylist;

int end;

if ( ii+1 == PropertyMapStruct.Length )

end = PropertyStruct.Length - 1;

else

end =  PropertyMapStruct[ii + 1].propertylist -1;

for ( int propertyrow = start ; propertyrow <= end ; propertyrow++)

{

string returnstring = CreateSpaces(spacesforrest + spacesfornested);

returnstring = returnstring + ".property /*17" + propertyrow.ToString("X6") + "*/ ";

string name = NameReserved(GetString(PropertyStruct[propertyrow].name)) ;

int flags = PropertyStruct[propertyrow].flags;

string propertyattribute = GetPropertyAttribute(flags );

returnstring = returnstring + propertyattribute + propertytypearray[propertyrow] + propertyreturnarray[propertyrow] ;

if ( returnstring.Length >= 41 )

returnstring = returnstring + "\r\n" + CreateSpaces(spacesforrest + spacesfornested)+ CreateSpaces(7);

returnstring = returnstring + " " + name + "(" ;

int len = returnstring.Length;

int len1 = returnstring.LastIndexOf("\r\n");

if ( len1 == -1)

len1 = -2;

string dummy = ParamOnMultipleLines(propertyparmarray[propertyrow], len-len1-2);

returnstring = returnstring + dummy + ")";

returnstring = returnstring + GetPropertyAttributeDefault(flags, propertyrow);

Console.WriteLine(returnstring);

Console.WriteLine(CreateSpaces(spacesforrest + spacesfornested) + "{");

DisplayCustomAttribute("Property" , propertyrow , 2 + spacesforrest + spacesfornested);

for ( int kk = 1 ; kk < MethodSemanticsStruct.Length ; kk++)

{

string attributes = GetMethodSemanticsAttributes(MethodSemanticsStruct[kk].methodsemanticsattributes);

string table = GetHasSemanticsTable(MethodSemanticsStruct[kk].association);

int propertyindex = GetHasSemanticsValue(MethodSemanticsStruct[kk].association);

int methodindex = MethodSemanticsStruct[kk].methodindex;

string methodattribute = GetMethodAttribute(MethodStruct[methodindex].flags , methodindex);

string paramstring = methoddefparamarray1[methodindex];

if ( propertyindex == propertyrow && table == "Property" )

{

string dummy1 = CreateSpaces(spacesforrest + 2 + spacesfornested);

dummy1 = dummy1 + attributes + " /*06" + methodindex.ToString("X6") + "*/ " + methoddeftypearray[methodindex] + methoddefreturnarray[methodindex];

 

string name1 = NameReserved(GetString(MethodStruct[methodindex].name)) + "(";

string dummy2 =  dummy1 +  typedefnames[typeindex] + "::" + name1;

int dummyint = dummy2.IndexOf("(");

string dummy3  =  ParamOnMultipleLines(paramstring , dummyint + 1)  ;

dummy3 = dummy3 + ")" + " /* 06" + (methodindex).ToString("X6") + " */";

Console.WriteLine(dummy2 + dummy3);

}

}

Console.Write(CreateSpaces(spacesforrest + spacesfornested));

Console.Write("} ");

Console.WriteLine("// end of property {0}::{1}" , NameReserved(GetString(TypeDefStruct[typeindex].name)) , name);

}

}

public string GetHasSemanticsTable(int asscoiationbyte)

{

string returnstring = "";

int tag = asscoiationbyte & 0x01;

if ( tag == 0 )

returnstring = returnstring + "Event";

if ( tag == 1 )

returnstring = returnstring + "Property";

return returnstring;

}

public string GetMethodSemanticsAttributes(short asscoiationbyte)

{

string returnstring = "";

if ( (asscoiationbyte & 0x01) == 0x01)

returnstring = returnstring + ".set";

if ( (asscoiationbyte & 0x02) == 0x02)

returnstring = returnstring + ".get";

if ( (asscoiationbyte & 0x04) == 0x04)

returnstring = returnstring + ".other";

if ( (asscoiationbyte & 0x08) == 0x08)

returnstring = returnstring + ".addon";

if ( (asscoiationbyte & 0x10) == 0x10)

returnstring = returnstring + ".removeon";

if ( (asscoiationbyte & 0x20) == 0x20)

returnstring = returnstring + ".fire";

return returnstring;

}

public void CreateMethodRefSignature (byte [] blobarray , int row)

{

//Console.WriteLine("CreateMethodRefSignature Name={0} row={1} b.Length={2}" , GetString(MemberRefStruct[row].name), row, blobarray.Length);

int aa = -1;

if ( row == aa)

{

Console.WriteLine("row number {0} {1}" , row , GetString(MemberRefStruct[row].name));

for ( int l = 0 ; l < blobarray.Length ; l++)

Console.Write("{0} " , blobarray[l].ToString("X"));

Console.WriteLine();

}

int howmanybytes,uncompressedbyte , index;

index = 0;

howmanybytes= CorSigUncompressData(blobarray , index , out uncompressedbyte);

if ( uncompressedbyte == 0x06 )

{

index = index + howmanybytes;

methodrefreturnarray[row] = GetElementType( index , blobarray , out howmanybytes , 0 , "");

return;

}

methodreftypearray[row] = DecodeFirstByteofMethodSignature(uncompressedbyte , row);;

index = index + howmanybytes;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

count = uncompressedbyte;

index = index + howmanybytes;

string typestring = GetElementType( index , blobarray , out howmanybytes, 0 , "");

methodrefreturnarray[row] = typestring;

index = index + howmanybytes;

string returnstring = "" ;

methodrefparamarray1[row] = "";

for ( int l = 1 ; l <= count ; l++)

{

string sentinel = "";

if ( blobarray[index] == 0x41)

{

sentinel = "..." + "," ;

index = index + 1;

}

typestring  = sentinel + GetElementType( index , blobarray , out howmanybytes , 0 , "") ;

index = index + howmanybytes;

returnstring = returnstring + typestring;

if ( l != count)

returnstring = returnstring  + "," ;

}

if ( index < blobarray.Length && blobarray[index] == 0x41)

returnstring = returnstring +  ",..." ;

methodrefparamarray1[row] = returnstring;

}

public void DisplayOverride (int typedefindex)

{

if ( MethodImpStruct == null  )

return;

for ( int ii = 1 ; ii < MethodImpStruct.Length ; ii++)

{

if ( typedefindex == MethodImpStruct[ii].classindex )

{

string codedeftablename = GetMethodDefTable(MethodImpStruct[ii].codeddef );

int codedefindex = GetMethodDefValue(MethodImpStruct[ii].codeddef );

string codebodytablename = GetMethodDefTable(MethodImpStruct[ii].codedbody);

int codebodyindex = GetMethodDefValue(MethodImpStruct[ii].codedbody );

//Console.WriteLine("...codedeftablename={0} codebodytablename={1} codedefindex={2} codebodyindex={3} ",codedeftablename ,codebodytablename,codedefindex,codebodyindex );

if ( codebodytablename== "MethodDef")

continue;

string finals = "";

if ( codedeftablename == "MethodDef" )

{

finals = CreateSpaces(spacesforrest + spacesfornested);

finals = finals + ".override " ;

int typedefmethodindex = GetTypeForMethod(codedefindex);

finals = finals + NameReserved(GetString(TypeDefStruct[typedefmethodindex ].name)) ;

finals = finals + "/* 02" + typedefmethodindex.ToString("X6") + " */::";

finals = finals + NameReserved(GetString(MethodStruct[codedefindex].name)) + " with";

}

else

{

finals = CreateSpaces(spacesforrest + spacesfornested);

finals = finals + ".override " ;

int typerefindex = GetTypeRefFromMethodRef(codedefindex);

finals = finals + typerefnames[typerefindex] + "::";

finals = finals + NameReserved(GetString(MemberRefStruct[codedefindex].name)) + " with";

}

int typerefindex1 = GetTypeRefFromMethodRef(codebodyindex);

finals = finals + " " + methodreftypearray[codebodyindex];

finals = finals + methodrefreturnarray[codebodyindex] + " " ;

finals = finals + DisplayTypeRefExtends(typerefindex1) + "::";

finals = finals + NameReserved(GetString(MemberRefStruct[codebodyindex].name)) + "(" ;

int len = finals.Length;

string paramstring = ParamOnMultipleLines(methodrefparamarray1[codebodyindex], len) ;

finals = finals + paramstring + ") /* 0A" + codebodyindex.ToString("X6") + " */";

Console.WriteLine(finals);

}

}

}

public void ReadandDisplayVTableFixup()

{

//Console.WriteLine("........{0}" , MethodStruct.Length  );

if ( MethodStruct == null)

return;

methodvtentryarray  = new int[MethodStruct.Length  + 1];

for ( int jj = 1 ; jj <= MethodStruct.Length ; jj++)

methodvtentryarray[jj] = 0;

if ( vtablerva != 0)

{

long save ;

long position = ConvertRVA(vtablerva) ;

if ( position == -1)

return;

mfilestream.Position = position;

Console.WriteLine("// VTableFixup Directory:");

int count1 = vtablesize/8;

vtfixuparray = new string[count1];

datavtfixuparray = new string[count1];

for ( int ii = 0 ; ii < count1 ; ii++)

{

vtfixuparray[ii] = ".vtfixup ";

datavtfixuparray[ii] = ".data ";

int fixuprva = mbinaryreader.ReadInt32();

Console.WriteLine("//   IMAGE_COR_VTABLEFIXUP[{0}]:" , ii);

Console.WriteLine("//       RVA:               {0}",fixuprva.ToString("x8"));

short count = mbinaryreader.ReadInt16();

Console.WriteLine("//       Count:             {0}", count.ToString("x4"));

short type = mbinaryreader.ReadInt16();

Console.WriteLine("//       Type:              {0}", type.ToString("x4"));

save = mfilestream.Position;

mfilestream.Position = ConvertRVA(fixuprva) ;

int i1 ;

long [] val = new long[count] ;

for ( i1 = 0 ; i1 < count ; i1++)

{

if ( (type&0x01)  == 0x01)

val[i1] = mbinaryreader.ReadInt32();

if ( (type&0x02)  == 0x02)

val[i1] = mbinaryreader.ReadInt64();

if ( (type&0x01)  == 0x01 )

Console.WriteLine("//         [{0}]            ({1})",i1.ToString("x4") , val[i1].ToString("X8"));

if ( (type&0x02)  == 0x02)

Console.WriteLine("//         [{0}]            (         {1})",i1.ToString("x4") , (val[i1]&0xffffffff).ToString("X"));

}

mfilestream.Position = save;

vtfixuparray[ii] = vtfixuparray[ii] + "[" + (i1).ToString("X") + "] ";

if ( (type&0x01)  == 0x01)

vtfixuparray[ii] = vtfixuparray[ii] + "int32 ";

if ( (type&0x02)  == 0x02)

vtfixuparray[ii] = vtfixuparray[ii] + "int64 ";

if ( (type&0x04)  == 0x04)

vtfixuparray[ii] = vtfixuparray[ii] + "fromunmanaged ";

vtfixuparray[ii] = vtfixuparray[ii] + "at D_" + fixuprva.ToString("X8");

vtfixuparray[ii] = vtfixuparray[ii] + " //";

for ( i1 = 0 ; i1 < count ; i1++)

{

if ( (type&0x01)  == 0x01)

vtfixuparray[ii] = vtfixuparray[ii]  + " " + val[i1].ToString("X8");

if ( (type&0x02)  == 0x02)

vtfixuparray[ii] = vtfixuparray[ii] + " " + val[i1].ToString("X16");

}

long index = 0;

if ( val != null)

index = val[0] & 0xffffff;

methodvtentryarray[ii+1] = (int)index; 

/*

datavtfixuparray[ii] = datavtfixuparray[ii] + "D_" + fixuprva.ToString("X8") + " = bytearray (\r\n" ;

string dummy = "";

datavtfixuparray[ii] = datavtfixuparray[ii] + CreateSpaces(17);

for ( int jj = 0 ; jj <= 3; jj++)

{

long value = (val[0] >> jj*8)&0xff;

dummy= dummy + value.ToString("X2") ;

if ( jj != 3)

dummy = dummy + " ";

}

datavtfixuparray[ii] = datavtfixuparray[ii] + dummy + ") ";

*/

}

Console.WriteLine();

}

 

}

public void DispalyVtFixup()

{

if (vtfixuparray == null)

return;

for ( int ii = 0 ; ii < vtfixuparray.Length ; ii++)

Console.WriteLine(vtfixuparray[ii]);

}

public string GetVtentryString (int methodrow)

{

string returnstring ="";

int kk = GetVtentryInteger(methodrow);

if ( kk >= 1)

returnstring = CreateSpaces(spacesforrest+2) + ".vtentry " + kk.ToString() + " : 1" + "\r\n" ;

return returnstring;

}

public int GetVtentryInteger (int methodrow)

{

int ii ;

for ( ii = 1 ; ii < methodvtentryarray.Length-1  ; ii++)

{

if ( methodvtentryarray[ii] == methodrow)

break;

}

if ( methodvtentryarray[ii] == 0)

return 0;

else

return ii;

}

 

public string GetArrayType (byte [] blobarray ,  int index , out int howmanybytes)

{

string returnstring ;

int total = 1;

int uncompressedbyte;

int rank;

int numsizes;

int howmanybytes1;

returnstring = GetElementType(index +1 , blobarray ,  out howmanybytes ,0 , "");

total = total + howmanybytes;

returnstring = returnstring + "[";

howmanybytes1 = CorSigUncompressData(blobarray , index + total, out uncompressedbyte);

total = total + howmanybytes1;

rank = uncompressedbyte;

howmanybytes1 = CorSigUncompressData(blobarray , index + total, out uncompressedbyte);

total = total + howmanybytes1;

numsizes = uncompressedbyte;

int [] sizearray = new int[numsizes];

for ( int l = 1 ; l <= numsizes ; l++)

{

howmanybytes1 = CorSigUncompressData(blobarray , index + total, out uncompressedbyte);

total = total + howmanybytes1;

sizearray[l-1] = uncompressedbyte;

}

howmanybytes1 = CorSigUncompressData(blobarray , index + total, out uncompressedbyte);

total = total + howmanybytes1;

int bounds = uncompressedbyte;

int [] boundsarray = new int[bounds];

//Console.WriteLine(".....rank={0} numsizes={1} bounds={2} " , rank, numsizes,bounds);

if ( rank != 0 && bounds == 0 && numsizes == 0)

{

for ( int i = 1 ; i < rank ; i++)

returnstring = returnstring + "^";

returnstring = returnstring + "]";

howmanybytes = howmanybytes + rank+1;

return returnstring;

}

int dots = 0;

for ( int l = 1 ; l <= bounds ; l++)

{

howmanybytes1 = CorSigUncompressData(blobarray , index + total, out uncompressedbyte);

total = total + howmanybytes1;

int ulSigned = uncompressedbyte & 0x1;

uncompressedbyte  = uncompressedbyte >> 1;

boundsarray[l-1] = uncompressedbyte ;

}

if ( numsizes == 0)

{

for ( int l = 0 ; l < bounds ; l++)

{

returnstring = returnstring + boundsarray[l] + "..." ;

if ( l != (bounds-1) )

returnstring = returnstring + "^";

}

}

else

{

for ( int l = 0 ; l < bounds ; l++)

{

if ( l < numsizes )

{

int upper = boundsarray[l] + sizearray[l] - 1 ;

if ( boundsarray[l] == 0 && sizearray[l] != 0 )

returnstring = returnstring + sizearray[l] ;

if (boundsarray[l] == 0 && sizearray[l] == 0)

returnstring = returnstring + "0" ;

else if (boundsarray[l] != 0 && sizearray[l] != 0)

returnstring = returnstring + boundsarray[l] + "..." + upper.ToString()  ;

else if (boundsarray[l] != 0 && sizearray[l] == 0)

returnstring = returnstring + boundsarray[l] + "..."  ;

}

else

{

dots++;

returnstring = returnstring + boundsarray[l] + "..."  ;

}

if ( l != bounds - 1 )

returnstring = returnstring + "^";

}

}

if ( numsizes != 0) // method a6

{

int leftover = rank - numsizes - dots ;

for ( int l = 1 ; l <= leftover ; l++)

returnstring = returnstring + "^";

}

returnstring = returnstring + "]";

howmanybytes = total-1;

return returnstring;

}

public string ParamOnMultipleLines (string paramstring , int spaces)

{

if ( paramstring == "")

return "";

if ( paramstring == null)

return "";

string returnstring = "";

if ( paramstring.IndexOf(",") == -1  )

{

paramstring = paramstring.Replace("^" , ",");

return paramstring;

}

char [] chararray = {','};

string [] stringarray = paramstring.Split(chararray);

returnstring = stringarray[0] + ",";

for ( int ii = 1 ; ii < stringarray.Length ; ii++)

{

returnstring = returnstring + "\r\n" + CreateSpaces(spaces) + stringarray[ii] ;

if ( ii != stringarray.Length -1 )

returnstring = returnstring  + ",";

}

returnstring = returnstring.Replace("^" , ",");

return returnstring;

}

public int HowManyMethodAttributes(string methodattribute)

{

int count = 0;

if ( methodattribute.IndexOf("hidebysig") != -1)

count++;

if ( methodattribute.IndexOf("newslot") != -1)

count++;

if ( methodattribute.IndexOf("specialname") != -1)

count++;

if ( methodattribute.IndexOf("rtspecialname") != -1)

count++;

if ( methodattribute.IndexOf("final") != -1)

count++;

if ( methodattribute.IndexOf("virtual") != -1)

count++;

if ( methodattribute.IndexOf("abstract") != -1)

count++;

return count;

}

public void CreateMethodDefSignature (byte [] blobarray , int row)

{

//Console.WriteLine("CreateMethodDefSignature Array Length={0} method row={1} name={2}" , blobarray.Length , row , GetString(MethodStruct[row].name));

int howmanybytes,uncompressedbyte , count , index;

index = 0;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

methoddeftypearray[row] = DecodeFirstByteofMethodSignature(uncompressedbyte , row);

index = index + howmanybytes;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

count = uncompressedbyte;

methoddefparamcount[row] = count;

index = index + howmanybytes;

string returntypestring = "";

returntypestring = GetElementType(index  , blobarray , out howmanybytes ,row , "Method") + " ";

returntypestring = returntypestring.Replace("^",",");

index = index + howmanybytes;

methoddefreturnarray[row] = returntypestring;

string returnstring1 = "" ;

string returnstring2 = "";

string typestring = "";

for ( int l = 1 ; l <= count ; l++)

{

typestring = GetElementType( index , blobarray , out howmanybytes , 0 , "") ;

index = index + howmanybytes;

returnstring2 = returnstring2 + typestring ;

if ( l != count)

returnstring2 = returnstring2 + ",";

int ind = GetParamRowNumber(row, l );

string paramcalling = GetParamAttrforParamCalling(ind);

string parammarshal = GetParamAttrforParamMarshal(ind , 1 ) ;

returnstring1 = returnstring1 + paramcalling ;

returnstring1 = returnstring1 + typestring + " " ;

returnstring1 = returnstring1 + parammarshal ;

returnstring1 = returnstring1 + GetParamNameForMethod( row , count , l);

if ( l != count)

returnstring1 = returnstring1 + "," ;

methoddefparamarray[row] = returnstring1;

methoddefparamarray1[row] = returnstring2;

}

}

int GetParamRowNumber( int row , int l )

{

if ( MethodStruct == null ||  ParamStruct == null)

return 0;

int start =  MethodStruct[row].param ;

int end = 0;

 

if ( row  == (MethodStruct.Length -1) )

end = ParamStruct.Length;

else

end = MethodStruct[row+1].param;

end--;

int i;

for ( i = start ; i <= end ; i++)

{

if ( ParamStruct[i].sequence == l)

return i;

}

return 0;

}

public string GetParamAttrforParamMarshal (int paramindex , int tabletype)

{

string returnstring = "";

if (ParamStruct == null  )

return "";

if (paramindex >= ParamStruct.Length )

return "";

int pattr = ParamStruct[paramindex].pattr;

returnstring = DecodeParamAttributes ( pattr , tabletype , paramindex , 0x2000);

return returnstring;

}

public string GetModOptOrModReq ( int index , byte [] blobarray , out int bytestaken)

{

string returnstring = "";

bytestaken = 0;

int whileindex = index;

if ( blobarray[index]  == 0x20 || blobarray[index]  == 0x1f)

{

while ( true )

{

int noofbytes;

string tokens = GetTokenType(blobarray , whileindex , out noofbytes) ;

if ( blobarray[whileindex]  == 0x20)

tokens = "modopt(" + tokens + ")";

if ( blobarray[whileindex]  == 0x1f)

tokens = "modreq(" + tokens + ")";

bytestaken = bytestaken + noofbytes + 1;

returnstring = tokens + " " + returnstring ;

whileindex = whileindex + noofbytes + 1;

if ( !(blobarray[whileindex]  == 0x20 || blobarray[whileindex]  == 0x1f)  )

break;

}

}

if ( returnstring != "")

returnstring = returnstring.Remove(returnstring.Length-1,1);

return returnstring;

}

public string GetElementType ( int index , byte [] blobarray , out int howmanybytes , int row , string name)

{

howmanybytes = 0;

string returnstring = "";

string modoptstring = "";

int bytestaken;

modoptstring = GetModOptOrModReq( index , blobarray , out bytestaken);

index = index + bytestaken;

byte type = blobarray[index];

if ( type >= 0x01 && type <= 0x0e )

{

returnstring = GetType(type);

howmanybytes = 1;

}

else if ( type == 0x0f)

{

returnstring = GetPointerToken(index, blobarray , out howmanybytes);

}

else if ( type == 0x10)

{

returnstring = GetByrefToken(index, blobarray , out howmanybytes);

}

else if ( type == 0x11 || type == 0x12 )

{

int howmanybytes2;

returnstring = GetTokenType( blobarray , index , out howmanybytes2);

howmanybytes = howmanybytes2 + 1;

}

else if ( type == 0x13  )

{

returnstring = "!" + blobarray[index+1].ToString();

howmanybytes = 2;

}

else if ( type == 0x14 )

{

int howmanybytes2;

returnstring = GetArrayType( blobarray , index , out howmanybytes2);

howmanybytes = howmanybytes2 + 1;

}

else if ( type == 0x15  || type == 0x17 || type == 0x1e || type == 0x21 )

{

returnstring = "/* UNKNOWN TYPE (0x" + type.ToString("X") + ")*/";

howmanybytes = 1;

}

else if ( type == 0x16)

{

returnstring = "typedref";

howmanybytes = 1;

}

else if ( type == 0x18)

{

returnstring = "native int";

howmanybytes = 1;

}

else if ( type == 0x19)

{

returnstring = "native unsigned int";

howmanybytes = 1;

}

else if ( type == 0x1a)

{

returnstring = "native float";

howmanybytes = 1;

}

else if ( type == 0x1c)

{

returnstring = "object";

howmanybytes = 1;

}

else if ( type == 0x1d)

{

returnstring = GetSzArray(index , blobarray , out howmanybytes);

}

else if ( type == 0x45 )

{

int howmanybytes2 ;

returnstring = GetElementType( index + 1 , blobarray , out howmanybytes2 , 0 , "") + " pinned";

howmanybytes = howmanybytes2 + 1;

}

else if ( type == 0x1b)

{

int howmanybytes2 ;

returnstring = GetPointerToFunctionSignature( index , blobarray , out howmanybytes2 , ref modoptstring , row , name) ;

modoptstring = "";

howmanybytes = howmanybytes2 ;

}

howmanybytes = howmanybytes + bytestaken;

if ( modoptstring != "")

returnstring = returnstring + " " + modoptstring;

return returnstring ;

}

public string GetPointerToFunctionSignature( int index , byte [] blobarray , out int howmanybytes , ref string modoptstring, int row , string name)

{

int uncompressedbyte;

index = index + 1;

int nobytes ;

int totalbytes = 1;

string returnstring = "";

nobytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

if ( row != 0 && name == "Method")

{

methoddeftypearray[row] = DecodeFirstByteofMethodSignature(uncompressedbyte , row);

methoddeftypearray[row] = "method " + methoddeftypearray[row];

}

else

returnstring =  "method " + DecodeFirstByteofMethodSignature(uncompressedbyte , row);

index = index + nobytes;

totalbytes = totalbytes + nobytes;

nobytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + nobytes;

totalbytes = totalbytes + nobytes;

int nooftypes = uncompressedbyte;

int bytestaken1;

string modoptstring1 = GetModOptOrModReq( index , blobarray , out bytestaken1);

index = index + bytestaken1;

totalbytes = totalbytes + bytestaken1;

returnstring = returnstring + GetElementType(index  , blobarray , out nobytes , 0 , "") ;

index = index + nobytes;

totalbytes = totalbytes + nobytes;

if ( modoptstring1 != "")

returnstring = returnstring + " " + modoptstring1 ;

returnstring = returnstring + " *(";

if ( nooftypes == 0)

returnstring = returnstring + ")";

else

for ( int i = 1; i <= nooftypes ; i++)

{

returnstring = returnstring + GetElementType(index  , blobarray , out nobytes ,0 , "");

if ( i != nooftypes)

returnstring = returnstring + ",";

else

returnstring = returnstring + ")";

index = index + nobytes;

totalbytes = totalbytes + nobytes;

}

if ( modoptstring != "")

returnstring = returnstring + " " + modoptstring;

howmanybytes = totalbytes;

return returnstring;

}

public string GetTableRefNameForFillArray( int tablerow , int typerow , string tablename)

{

string nameandnamespace = "";

if ( tablename == "AssemblyRef")

nameandnamespace = NameReserved(GetString(AssemblyRefStruct[tablerow].name)) ;

if ( tablename == "ModuleRef")

nameandnamespace = ".module " + NameReserved(GetString(ModuleRefStruct[tablerow].name)) ;

string stringnamespace = NameReserved(GetString(TypeRefStruct[typerow].nspace)) ;

string stringnested  = "";

if ( stringnamespace != "")

stringnamespace  = stringnamespace + ".";

if ( tablename == "AssemblyRef")

stringnested  = "[" + nameandnamespace  + "/* 23" + tablerow.ToString("X6") + " */]" + stringnamespace + NameReserved(GetString(TypeRefStruct[typerow].name));

if ( tablename == "ModuleRef")

stringnested  = "[" + nameandnamespace + "/* 1A" + tablerow.ToString("X6") + " */]" + stringnamespace + NameReserved(GetString(TypeRefStruct[typerow].name));

if ( tablename == "Module")

stringnested  = stringnested  + stringnamespace + NameReserved(GetString(TypeRefStruct[typerow].name));

stringnested  = stringnested  + "/* 01" + typerow.ToString("X6") + " *//" ;

return stringnested;

}

public string GetTypeRefForFillarray(int k)

{

string stringnamespace = NameReserved(GetString(TypeRefStruct[k].nspace)) ;

if ( stringnamespace != "")

stringnamespace= stringnamespace + ".";

string stringnested  = stringnamespace + NameReserved(GetString(TypeRefStruct[k].name)) ;

stringnested  = stringnested  + "/* 01" + k.ToString("X6") + " */" ;

return stringnested;

}

public void FillArray ()

{

int old = tableoffset;

bool tablehasrows = tablepresent(8);

int offs = tableoffset;

tableoffset = old;

if ( tablehasrows )

{

paramnames = new string[rows[8] + 1];

for ( int k = 1 ; k <= rows[8] ; k++)

{

short pattr = BitConverter.ToInt16 (metadata, offs);

offs += 2;

int sequence = BitConverter.ToInt16 (metadata, offs);

offs += 2;

int name = ReadStringIndex(metadata, offs);

offs += offsetstring;

string dummy = GetString(name);

paramnames[k] = NameReserved(dummy);

}

}

old = tableoffset;

tablehasrows  = tablepresent(1);

offs = tableoffset;

tableoffset = old;

if ( tablehasrows )

{

typerefnames = new string[rows[1]+1];

for ( int k = 1 ; k <= rows[1] ; k++)

{

short resolutionscope = BitConverter.ToInt16 (metadata , offs);

offs = offs + 2;

int name = ReadStringIndex(metadata , offs);

offs = offs + offsetstring;

int nspace = ReadStringIndex(metadata , offs);

offs = offs + offsetstring;

string stringname = NameReserved(GetString(name));

string stringtypefminusnested = GetString(nspace) ;

if ( stringtypefminusnested .Length != 0)

stringtypefminusnested = stringtypefminusnested + ".";

stringtypefminusnested = stringtypefminusnested + stringname;

string stringnested = "";

string resolutioncodedtable = GetResolutionScopeTable(resolutionscope );

int resolutionrow = GetResolutionScopeValue(resolutionscope );

if ( resolutioncodedtable == "Module")

{

stringtypefminusnested = stringtypefminusnested + "/* 01" + k.ToString("X6") + " */";

}

if ( resolutioncodedtable == "AssemblyRef")

{

stringnested  = "[" + NameReserved(GetString(AssemblyRefStruct[resolutionrow].name)) + "/* 23" + resolutionrow.ToString("X6") + " */]";

stringtypefminusnested = stringtypefminusnested + "/* 01" + k.ToString("X6") + " */";

}

if ( resolutioncodedtable == "ModuleRef")

{

stringnested  = "[.module " + NameReserved(GetString(ModuleRefStruct[resolutionrow].name)) + "/* 1A" + resolutionrow.ToString("x6") + " */]";

stringtypefminusnested = stringtypefminusnested + "/* 01" + k.ToString("X6") + " */";

}

if ( resolutioncodedtable == "TypeRef" )

{

string resolutioncodedtable1 = GetResolutionScopeTable(TypeRefStruct[resolutionrow].resolutionscope );

int resolutionrow1 = GetResolutionScopeValue(TypeRefStruct[resolutionrow].resolutionscope );

if ( resolutioncodedtable1 == "AssemblyRef" || resolutioncodedtable1 == "ModuleRef" || resolutioncodedtable1 == "Module")

{

stringnested = GetTableRefNameForFillArray(resolutionrow1 , resolutionrow , resolutioncodedtable1);

stringnested = stringnested + GetTypeRefForFillarray(k);

stringtypefminusnested = "";

}

else

{

string tablename = GetResolutionScopeTable(TypeRefStruct[k].resolutionscope );

int row  = GetResolutionScopeValue(TypeRefStruct[k].resolutionscope );

int cnt = 0;

while ( tablename == "TypeRef")

{

row  = GetResolutionScopeValue(TypeRefStruct[row].resolutionscope );

tablename = GetResolutionScopeTable(TypeRefStruct[row].resolutionscope );

cnt++;

}

int i = 0;

int [] typerows = new int[cnt];

string tablename1 = GetResolutionScopeTable(TypeRefStruct[k].resolutionscope );

int row1  = GetResolutionScopeValue(TypeRefStruct[k].resolutionscope );

while ( i < cnt )

{

row1  = GetResolutionScopeValue(TypeRefStruct[row1].resolutionscope );

tablename1 = GetResolutionScopeTable(TypeRefStruct[row1].resolutionscope );

typerows[i] = row1;

i++;

}

 

int assemblyrow = GetResolutionScopeValue(TypeRefStruct[row].resolutionscope );

int typerow = typerows[typerows.Length-1];

stringnested = GetTableRefNameForFillArray( assemblyrow , typerow , tablename);

 

i = 0;

string dummy = "";

while ( i < cnt-1 )

{

dummy  =  GetTypeRefForFillarray(typerows[i]) + "/" + dummy;

i++;

}

stringnested = stringnested + dummy;

stringnested = stringnested + GetTypeRefForFillarray(resolutionrow);

stringnested = stringnested + "/" + GetTypeRefForFillarray(k);

stringtypefminusnested = "";

}

}

typerefnames[k] = stringnested  + stringtypefminusnested ;

//Console.WriteLine(".......{0} {1} {2}" , resolutioncodedtable , typerefnames[k] , k);

}

}

old = tableoffset;

tablehasrows  = tablepresent(2);

offs = tableoffset;

tableoffset = old;

if ( tablehasrows )

{

typedefnames = new string[rows[2]+1];

for ( int k = 1 ; k <= rows[2] ; k++)

{

int name = TypeDefStruct[k].name;

offs += offsetstring;

int nspace = TypeDefStruct[k].nspace;

offs += offsetstring;

string nestedtypestring  = "";

nestedtypestring  = GetNestedTypeAsString(k);

string namestring  = GetString(name);

string namespacestring = NameReserved(GetString(nspace));

if ( namespacestring.Length != 0)

namespacestring = namespacestring + ".";

namestring  = NameReserved(namestring );

typedefnames[k] = nestedtypestring + namespacestring + namestring  + "/* 02" + k.ToString("X6") + " */";

}

}

}

public string DecodeToken (int token , int type)

{

byte tabletype = (byte)(token & 0x03);

int tableindex = token >> 2;

string returnstring = "";

//Console.WriteLine(".......tabletype={0} {1} {2}" , tabletype , tableindex , typerefnames.Length);

if ( tabletype == 0)

returnstring = typedefnames[tableindex];

if ( tabletype == 1 )

returnstring = typerefnames[tableindex] ;

return returnstring;

}

public string DecodeFirstByteofMethodSignature (int firstbyte , int methodrow)

{

string returnstring = "";

//Console.WriteLine(".....{0}" , firstbyte.ToString("X"));

if ( (firstbyte& 0x20 ) == 0x20 )

returnstring = "instance ";

if ( (firstbyte & 0x60 ) == 0x60 )

returnstring = "explicit instance ";

int firstbits = firstbyte & 0xf;

if ( firstbits  == 0x02 )

returnstring = returnstring + "unmanaged stdcall ";

else if ( firstbits  == 0x03 )

returnstring = returnstring + "unmanaged thiscall ";

else if ( firstbits  == 0x05 )

returnstring = returnstring + "vararg ";

else if ( firstbits  == 0x01 )

returnstring = returnstring + "unmanaged cdecl ";

else if ( firstbits  == 0x04 )

returnstring = returnstring + "unmanaged fastcall ";

return  returnstring;

}

public string DecodeParamAttributes(int pattr , int tabletype , int start , int bytemask)

{

string returnstring = "";

if ( (pattr & bytemask) == bytemask)

{

int ii ;

for ( ii = 1 ; ii <= FieldMarshalStruct.Length ; ii++)

{

int coded = FieldMarshalStruct[ii].coded;

int table = FieldMarshalStruct[ii].coded & 0x01;

coded = coded >> 1;

if ( coded == start && tabletype == table)

break;

}

int blobindex = FieldMarshalStruct[ii].index;

int length , howmanybytes;

howmanybytes = CorSigUncompressData(blob , blobindex, out length);

//Console.WriteLine("{0} {1} {2} {3}" ,blob[blobindex].ToString("X") , blob[blobindex+1].ToString("X"),blob[blobindex+2].ToString("X"),blob[blobindex+3].ToString("X") );

int blobvalue = blob[blobindex+howmanybytes];

string ss1 = GetMarshallType(blob[blobindex+howmanybytes] , howmanybytes , blobindex);

if ( ss1 == "[]" || ss1.IndexOf("[ + ") != -1 || ss1 == "" || ( ss1.Length >= 2 && ss1[0] == '[' && ss1[ss1.Length-1] == ']' ))

returnstring = " marshal(" + ss1;

else

returnstring = " marshal( " + ss1;

 

returnstring = returnstring + ")";

}

if ( returnstring != "")

returnstring = returnstring + " ";

return returnstring ;

}

public string GetMarshallType (byte marshalflags , int howmanybytes , int blobindex)

{

//Console.WriteLine("...{0} {1} {2} {3} {4}" ,blob[blobindex] , blob[blobindex+1].ToString("X"), blob[blobindex+2].ToString("X"), blob[blobindex+3].ToString("X") , blob[blobindex+4].ToString("X") );

//Console.WriteLine(".........{0}" , marshalflags.ToString("X"));

if ( blob[blobindex] == 0)

return "";

if ( marshalflags == 0x01)

return "void";

if ( marshalflags == 0x02)

return "bool";

if ( marshalflags == 0x03)

return "int8";

if ( marshalflags == 0x04)

return "unsigned int8";

if ( marshalflags == 0x05)

return "int16";

if ( marshalflags == 0x06)

return "unsigned int16";

if ( marshalflags == 0x07)

return "int32";

if ( marshalflags == 0x08)

return "unsigned int32";

if ( marshalflags == 0x09)

return "int64";

if ( marshalflags == 0x0a)

return "unsigned int64";

if ( marshalflags == 0x0b)

return "float32";

if ( marshalflags == 0x0c)

return "float64";

if ( marshalflags == 0x0D)

return "syschar";

if ( marshalflags == 0x0e)

return "variant";

if ( marshalflags == 0x0f)

return "currency";

if ( marshalflags == 0x10)

return "*";

if ( marshalflags == 0x11)

return "decimal";

if ( marshalflags == 0x12)

return "date";

if ( marshalflags == 0x13)

return "bstr";

if ( marshalflags == 0x14)

return "lpstr";

if ( marshalflags == 0x15)

return "lpwstr";

if ( marshalflags == 0x16)

return "lptstr";

if ( marshalflags == 0x17)

{

int uncompressedbyte;

CorSigUncompressData(blob , blobindex+howmanybytes+1 , out uncompressedbyte);

return "fixed sysstring [" + uncompressedbyte.ToString() + "]";

}

if ( marshalflags == 0x18)

return "objectref";

if ( marshalflags == 0x19)

return "iunknown";

if ( marshalflags == 0x1a)

return "idispatch";

if ( marshalflags == 0x1b)

return "struct";

if ( marshalflags == 0x1c)

return "interface";

if ( marshalflags == 0x1d)

{

string returnstring = "safearray";

if ( blob[blobindex] > 1)

{

string dummy = GetSafeArrayType(blob[blobindex+howmanybytes+1]);

if ( dummy != "")

returnstring = returnstring + " " + dummy;

}

int len = blob[blobindex] - 3;

if ( len > 0)

{

returnstring = returnstring + ", \""  ;

for ( int iii = 0 ; iii < len ; iii++)

returnstring = returnstring + (char)blob[blobindex+iii+howmanybytes+3] ;

returnstring = returnstring + "\""  ;

}

return returnstring;

}

if ( marshalflags == 0x1e)

{

int uncompressedbyte;

CorSigUncompressData(blob , blobindex+howmanybytes+1 , out uncompressedbyte);

return "fixed array [" + uncompressedbyte.ToString() + "]";

}

if ( marshalflags == 0x1f)

return "int";

if ( marshalflags == 0x20)

return "unsigned int";

if ( marshalflags == 0x21)

return "nested struct";

if ( marshalflags == 0x22)

return "byvalstr";

if ( marshalflags == 0x23)

return "ansi bstr";

if ( marshalflags == 0x24)

return "tbstr";

if ( marshalflags == 0x25)

return "variant bool";

if ( marshalflags == 0x26)

return "method";

if ( marshalflags == 0x27)

return "";

if ( marshalflags == 0x28)

return "as any";

if ( marshalflags == 0x29)

return "";

if ( marshalflags == 0x2a)

{

//Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" ,blob[blobindex].ToString("X") , blob[blobindex+1].ToString("X"),blob[blobindex+2].ToString("X"),blob[blobindex+3].ToString("X")  ,blob[blobindex+4].ToString("X"),blob[blobindex+5].ToString("X") ,blob[blobindex+6].ToString("X")  ,blob[blobindex+7].ToString("X")  );

/*

for ( int i = 0 ; i <= blob[blobindex] ; i++)

Console.Write("{0} " , blob[blobindex+i].ToString("X"));

Console.WriteLine();

*/

string returnstring = "";

string arrays = "[]";

string dummy1 = "";

if ( blob[blobindex] == 3)

{

dummy1 = " ";

arrays = "[ + " + blob[blobindex+2+howmanybytes].ToString() + "]";

}

if ( blob[blobindex] == 4)

{

dummy1 = "";

if ( blob[blobindex+2+howmanybytes] != 0)

arrays = "[" + blob[blobindex+3+howmanybytes].ToString() + " + " + blob[blobindex+2+howmanybytes].ToString() +  "]";

else

arrays = "[" + blob[blobindex+3+howmanybytes].ToString() + "]";

}

if ( blob[blobindex] >= 7)

{

int howmanytypes = blob[blobindex]/3;

returnstring = GetMarshallType(blob[blobindex+howmanybytes+howmanytypes] ,howmanybytes , blobindex);

if ( blob[blobindex+1+howmanybytes+howmanytypes] != 0)

arrays = "[" + blob[blobindex+2+howmanybytes+howmanytypes].ToString() + " + " + blob[blobindex+1+howmanybytes+howmanytypes].ToString() +  "]";

else

arrays = "[" + blob[blobindex+2+howmanybytes+howmanytypes].ToString() + "]";

returnstring = returnstring + arrays ;

for ( int i = 1 ; i < howmanytypes ; i++)

{

if ( blob[blobindex+howmanybytes+howmanytypes+i*2+2] == 0)

returnstring = returnstring + " " + GetMarshallType(blob[blobindex+howmanybytes+howmanytypes+i*2+1] ,howmanybytes , blobindex);

else

returnstring = returnstring + " " + GetMarshallType(blob[blobindex+howmanybytes+howmanytypes+i*2+2] ,howmanybytes , blobindex);

}

return returnstring;

}

if ( blob[blobindex+howmanybytes+1] == 0x50)

returnstring = arrays;

else

returnstring = dummy1 + GetMarshallType(blob[blobindex+howmanybytes+1] ,howmanybytes , blobindex) + arrays;

return returnstring;

}

if ( marshalflags == 0x2b)

return "lpstruct";

if ( marshalflags == 0x2c)

{

int len = 0;

int howmanybytes1 = 0;

howmanybytes1 = CorSigUncompressData(blob , blobindex + howmanybytes+3 , out len );

string returnstring = "custom (\"";

for ( int ii1 = 0 ; ii1 < len ; ii1++)

returnstring = returnstring +  (char)blob[blobindex+3+ii1+howmanybytes+howmanybytes1];

returnstring = returnstring + "\"" + "," ;

int len1 = len;

int bytes = 1;

if ( len1 >= 128)

bytes = 2;

howmanybytes1 = CorSigUncompressData(blob , blobindex + howmanybytes+3+len1+bytes , out len );

//Console.WriteLine("..............len={0} len1={1} {2}" , len , len1 , blob[blobindex]);

returnstring = returnstring + "\"" ;

for ( int ii1 = 1 ; ii1 <= len ; ii1++)

returnstring = returnstring +  (char)blob[blobindex+3+len1+ii1+howmanybytes+howmanybytes1];

returnstring = returnstring +  "\")";

return returnstring;

}

if ( marshalflags == 0x2d)

return "error";

return "Unknown";

}

public string GetSafeArrayType (byte safearraytype)

{

string returnstring = "";

//Console.WriteLine("......{0}" , safearraytype.ToString("X"));

if (safearraytype == 0)

returnstring = "";

if (safearraytype == 1)

returnstring = "null";

if (safearraytype == 2)

returnstring = "int16";

if (safearraytype == 3)

returnstring = "int32";

if (safearraytype == 4)

returnstring = "float32";

if (safearraytype == 5)

returnstring = "float34";

if (safearraytype == 6)

returnstring = "currency";

if (safearraytype == 7)

returnstring = "date";

if (safearraytype == 8)

returnstring = "bstr";

if (safearraytype == 9)

returnstring = "idispatch";

if (safearraytype == 0x0a)

returnstring = "error";

if (safearraytype == 0x0b)

returnstring = "bool";

if (safearraytype == 0x0c)

returnstring = "variant";

if (safearraytype == 0x0d)

returnstring = "iunknown";

if (safearraytype == 0x0e)

returnstring = "decimal";

if (safearraytype == 0x0f)

returnstring = "illegal";

if (safearraytype == 0x10)

returnstring = "int8";

if (safearraytype == 0x11)

returnstring = "unsigned int8";

if (safearraytype == 0x12)

returnstring = "unsigned int16";

if (safearraytype == 0x13)

returnstring = "unsigned int32";

if (safearraytype == 0x14)

returnstring = "int64";

if (safearraytype == 0x15)

returnstring = "unsigned int64";

if (safearraytype == 0x16)

returnstring = "int";

if (safearraytype == 0x17)

returnstring = "unsigned int";

if (safearraytype == 0x18)

returnstring = "void";

if (safearraytype == 0x19)

returnstring = "hresult";

if (safearraytype == 0x1a)

returnstring = "*";

if (safearraytype == 0x1b)

returnstring = "safearray";

if (safearraytype == 0x1c)

returnstring = "carray";

if (safearraytype == 0x1d)

returnstring = "userdefined";

if (safearraytype == 0x1e)

returnstring = "lpstr";

if (safearraytype == 0x1f)

returnstring = "lpwstr";

if (safearraytype == 0x20)

returnstring = "illegal";

if (safearraytype == 0x21)

returnstring = "illegal";

if (safearraytype == 0x22)

returnstring = "illegal";

if (safearraytype == 0x23)

returnstring = "illegal";

if (safearraytype == 0x24)

returnstring = "record";

if (safearraytype >= 0x25)

returnstring = "illegal";

return returnstring;

}

public string GetParamAttrforMethodMarshal (int methodindex , int seq )

{

string returnstring = "";

if (ParamStruct == null)

return returnstring;

int end;

int start = MethodStruct[methodindex].param;

if ( methodindex == (MethodStruct.Length - 1) )

end = ParamStruct.Length + 1;

else

end =  MethodStruct[methodindex+1].param;

if ( start == ParamStruct.Length)

return returnstring;

if ( start == end)

return returnstring;

if ( seq == 0 && ParamStruct[start].sequence != 0)

return "";

int pattr = ParamStruct[start].pattr;

returnstring = DecodeParamAttributes(pattr , 1 , start , 0x2000);

if ( returnstring != "" && returnstring[0] == 32)

returnstring = returnstring.Remove(0 , 1);

return returnstring;

}

public string GetMethodAttribute (int methodflags , int methodrow)

{

string returnstring = "";

methodaccessattribute="" ;

methodpinvokestring = "";

if ( (methodflags & 0x0006) == 0x0006)

returnstring = "public ";

else

if ( (methodflags & 0x0005) == 0x0005)

returnstring = "famorassem ";

else

if ( (methodflags & 0x0003) == 0x0003)

returnstring = "assembly ";

else

if ( (methodflags & 0x0004) == 0x0004)

returnstring = "family ";

else

if ( (methodflags & 0x0001) == 0x0001)

returnstring = "private ";

else if ( (methodflags & 0x0002) == 0x0002)

returnstring = "famandassem ";

else

returnstring = "privatescope ";

methodaccessattribute = returnstring;

if ( (methodflags & 0x0080) == 0x0080)

{

returnstring = returnstring + "hidebysig ";

}

if ( (methodflags & 0x0100) == 0x0100)

{

returnstring = returnstring + "newslot ";

}

if ( (methodflags & 0x0800) == 0x0800 || (methodflags & 0x0200) == 0x0200 )

{

returnstring = returnstring + "specialname ";

}

if ( (methodflags & 0x1000) == 0x1000)

{

returnstring = returnstring + "rtspecialname ";

}

if ( (methodflags & 0x0010) == 0x0010)

{

returnstring = returnstring + "static ";

}

else

{

returnstring = returnstring + "instance ";

}

if ( (methodflags & 0x0020) == 0x0020)

{

returnstring = returnstring + "final ";

}

if ( (methodflags & 0x0040) == 0x0040)

{

returnstring = returnstring + "virtual ";

}

if ( (methodflags & 0x0400) == 0x0400)

{

returnstring = returnstring + "abstract ";

}

if ( (methodflags & 0x2000) == 0x2000)

{

returnstring = returnstring + "pinvokeimpl(";

int ii;

if ( ImplMapStruct == null)

{

returnstring = returnstring + "/* No map */) ";

return returnstring;

}

else

{

for ( ii=1; ii < ImplMapStruct.Length ; ii++)

{

int index = ImplMapStruct[ii].cindex;

index = index >> 1;

if ( index == methodrow )

break;

}

if ( ii == ImplMapStruct.Length )

{

returnstring = returnstring + "/* No map */) ";

return returnstring;

}

string methodname = NameReserved(GetString(MethodStruct[methodrow].name));

string name = NameReserved(GetString(ImplMapStruct[ii].name));

int scope = ImplMapStruct[ii].scope;

string modulename = NameReserved(GetString(ModuleRefStruct[scope].name));

modulename = modulename.Replace("\\" , "\\\\");

returnstring = returnstring + "\"" + modulename + "\"" ;

if ( String.Compare(methodname , name) != 0)

returnstring = returnstring + " as \"" + name + "\"";

string pinvokeattribute1;

string pinvokeattribute = GetPinvokeAttributes(ImplMapStruct[ii].attr , out pinvokeattribute1);

returnstring = returnstring + pinvokeattribute1;

if (pinvokeattribute.IndexOf("stdcall") == -1)

returnstring = returnstring + " " + pinvokeattribute;

returnstring = returnstring + ") ";

int index1 = returnstring.IndexOf("pinvok") ;

methodpinvokestring  = returnstring.Remove(0, index1);

}

}

if ( (methodflags & 0x08) == 0x08)

{

returnstring = returnstring + "unmanagedexp ";

}

if ( (methodflags & 0xffff8000) == 0xffff8000)

{

returnstring = returnstring + "reqsecobj ";

}

return returnstring;

}

public string GetPinvokeAttributes (int attribute , out string returnattribute)

{

returnattribute = "";

if ( (attribute & 0x001) == 0x0001)

returnattribute = " nomangle";

if ( (attribute & 0x006) == 0x0006)

returnattribute = returnattribute+ " autochar";

else if ( (attribute & 0x002) == 0x0002)

returnattribute = returnattribute + " ansi";

else if ( (attribute & 0x004) == 0x0004)

returnattribute = returnattribute + " unicode";

if ( (attribute & 0x040) == 0x0040)

returnattribute = returnattribute + " lasterr";

string returnstring = "";

if ( (attribute & 0x0500) == 0x0500)

returnstring = returnstring+ "fastcall";

else if ( (attribute & 0x0300) == 0x0300)

returnstring= returnstring + "stdcall";

else if ( (attribute & 0x0100) == 0x0100)

returnstring = returnstring + "winapi";

else if ( (attribute & 0x0200) == 0x0200)

returnstring = returnstring + "cdecl";

else if ( (attribute & 0x0400) == 0x0400)

returnstring = returnstring + "thiscall";

return returnstring;

}

public void DisplaySizeAndPack (int typeindex)

{

if ( ClassLayoutStruct == null)

return;

for ( int ii = 1 ; ii < ClassLayoutStruct.Length ; ii++)

{

if ( ClassLayoutStruct[ii].parent == typeindex )

{

Console.Write(CreateSpaces(spacesfornested + spacesforrest));

Console.WriteLine(".pack {0}" , ClassLayoutStruct[ii].packingsize);

Console.Write(CreateSpaces(spacesfornested + spacesforrest));

Console.WriteLine(".size {0}" , ClassLayoutStruct[ii].classsize);

}

}

}

public void DisplayEnd()

{

string nspace = NameReserved(GetString(TypeDefStruct[TypeDefStruct.Length-1].nspace));

if ( ! placedend)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

placedend = true;

}

if ( nspace == "")

DisplayCustomAttribute("TypeRef" , 0 , 0);

DisplayData();

Console.WriteLine("//*********** DISASSEMBLY COMPLETE ***********************");

if ( datadirectoryrva[2] != 0)

Console.WriteLine("// WARNING: Created Win32 resource file a.res");

}

public void DisplayOneTypeDefEnd (int typeindex )

{

string dummy = "";

if ( IsTypeNested(typeindex) )

dummy = dummy + CreateSpaces(spacesfornested);

dummy = dummy + CreateSpaces(spacefornamespace);

dummy = dummy + "} // end of class ";

string classname = NameReserved(GetString(TypeDefStruct[typeindex].name));

dummy = dummy + classname ;

Console.WriteLine(dummy);

string namespacename = NameReserved(GetString(TypeDefStruct[typeindex].nspace));

Console.WriteLine();

if (  namespacename != "")

{

string nspace1 = NameReserved(GetString(TypeDefStruct[typeindex].nspace));

int ii;

for ( ii = typeindex + 1 ; ii < TypeDefStruct.Length - 1 ; ii++)

{

if ( IsTypeNested(ii) )

continue;

break;

}

string nspace2 = "";

if ( ii != TypeDefStruct.Length )

nspace2 = NameReserved(GetString(TypeDefStruct[ii].nspace));

if ( nspace1 != nspace2 )

{

if ( lasttypedisplayed == typeindex && notprototype  )

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

placedend = true;

DisplayCustomAttribute("TypeRef" , 0 , 2);

}

if (lasttypedisplayed == typeindex && notprototype  )

DisplayFinalCustomAttributes();

Console.Write("}");

Console.WriteLine(" // end of namespace {0}", namespacename);

spacefornamespace = 0;

spacesforrest = 2;

writenamespace = true;

Console.WriteLine();

}

else

writenamespace = false;

}

}

 

public int GetTypeForMethod (int methodrow)

{

int typedefindex = 0;

for ( typedefindex = 1 ; typedefindex < TypeDefStruct.Length - 1  ; typedefindex++)

{

int start = TypeDefStruct[typedefindex].mindex;

int end = TypeDefStruct[typedefindex+1].mindex -1 ;

if ( methodrow >= start && methodrow <= end)

return typedefindex;

}

return typedefindex;

}

public void DisplayTypeDefsAndMethods ()

{

notprototype = true;

if ( TypeDefStruct.Length != 2)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

}

Console.WriteLine();

Console.WriteLine("// =============== GLOBAL FIELDS AND METHODS ===================");

Console.WriteLine();

DisplayGlobalFields();

DisplayGlobalMethods();

if ( TypeDefStruct.Length != 2)

{

Console.WriteLine();

Console.WriteLine("// =============================================================");

Console.WriteLine();

Console.WriteLine();

Console.WriteLine("// =============== CLASS MEMBERS DECLARATION ===================");

Console.WriteLine("//   note that class flags, 'extends' and 'implements' clauses");

Console.WriteLine("//          are provided here for information only");

Console.WriteLine();

int kk = TypeDefStruct.Length ;

for ( int i = 2 ; i < kk ; i++)

{

if ( GetString(TypeDefStruct[i].name) == "_Deleted" && streamnames[0] == "#-")

continue;

if ( ! IsTypeNested(i) )

{

DisplayOneType(i);

}

}

}

DisplayEnd();

}

public void DisplayTypeDefs ()

{

if ( TypeDefStruct.Length != 2)

{

Console.WriteLine("//");

Console.WriteLine("// ============== CLASS STRUCTURE DECLARATION ==================");

Console.WriteLine("//");

writenamespace = true;

for ( int i = 2 ; i < TypeDefStruct.Length ; i++)

{

if ( GetString(TypeDefStruct[i].name) == "_Deleted"  && streamnames[0] == "#-")

{

continue;

}

if ( ! IsTypeNested(i) )

{

DisplayOneTypePrototype(i);

}

}

}

}

public bool IsTypeNested (int typeindex)

{

if (NestedClassStruct == null)

return false;

for ( int ii = 1 ;  ii< NestedClassStruct.Length ; ii++)

{

if ( NestedClassStruct[ii].nestedclass == typeindex)

return true;

}

return false;

}

public void DisplayOneTypePrototype (int typedefindex)

{

DisplayOneTypeDefStart(typedefindex);

DisplayNestedTypesPrototypes(typedefindex);

DisplayOneTypeDefEnd(typedefindex);

}

public void DisplayOneTypeDefStart (int typerow)

{

string namespacename = NameReserved(GetString(TypeDefStruct[typerow].nspace));

if (  namespacename != "")

{

if ( writenamespace )

{

Console.WriteLine(".namespace {0}" , namespacename );

Console.WriteLine("{"  );

spacefornamespace = 2;

spacesforrest = 4;

}

}

string typestring = "";

if ( IsTypeNested(typerow))

typestring = typestring + CreateSpaces(spacesfornested);

typestring = typestring + CreateSpaces(spacefornamespace);

typestring = typestring + ".class /*02" + typerow.ToString("X6") + "*/ ";

string attributeflags = GetTypeAttributeFlags(TypeDefStruct[typerow].flags , typerow);

Console.WriteLine("{0}{1}{2}" , typestring ,  attributeflags , NameReserved(GetString(TypeDefStruct[typerow].name)));

string tablename = GetTypeDefOrRefTable(TypeDefStruct[typerow].cindex);

int index = GetTypeDefOrRefValue(TypeDefStruct[typerow].cindex);

string typeextends = "";

if ( tablename == "TypeRef" )

{

typeextends = DisplayTypeRefExtends(index);

}

if ( tablename == "TypeDef" )

{

typeextends =  GetNestedTypeAsString(index) + DisplayTypeDefExtends(index);

}

if ( typeextends.Length != 0)

{

typestring = "";

if ( IsTypeNested(typerow))

typestring = typestring + CreateSpaces(spacesfornested);

typestring = typestring + CreateSpaces(spacefornamespace);

typestring = typestring + "       extends " + typeextends;

Console.WriteLine(typestring);

}

string interfacestring = DisplayAllInterfaces(typerow);

if ( interfacestring.Length != 0)

{

typestring = "";

if ( IsTypeNested(typerow))

typestring = typestring + CreateSpaces(spacesfornested);

typestring = typestring + CreateSpaces(spacefornamespace);

typestring = typestring + "       implements " + interfacestring;

Console.Write(typestring);

}

typestring = "";

if ( IsTypeNested(typerow))

typestring = typestring + CreateSpaces(spacesfornested);

typestring = typestring + CreateSpaces(spacefornamespace);

typestring = typestring + "{";

Console.WriteLine(typestring);

}

public string GetTypeAttributeFlags (int typeattributeflags , int typeindex)

{

string returnstring = "";

int visibiltymask = typeattributeflags & 0x07;

string visibiltymaskstring="";

if ( visibiltymask == 0)

visibiltymaskstring = "private ";

if ( visibiltymask == 1)

visibiltymaskstring = "public ";

if ( visibiltymask == 2)

visibiltymaskstring = "nested public ";

if ( visibiltymask == 3)

visibiltymaskstring = "nested private ";

if ( visibiltymask == 4)

visibiltymaskstring = "nested family ";

if ( visibiltymask == 5)

visibiltymaskstring = "nested assembly ";

if ( visibiltymask == 6)

visibiltymaskstring = "nested famandassem ";

if ( visibiltymask == 7)

visibiltymaskstring = "nested famorassem ";

int classlayoutmask = typeattributeflags & 0x18;

string classlayoutstring = "";

if ( classlayoutmask == 0)

classlayoutstring = "auto ";

if ( classlayoutmask == 0x08)

classlayoutstring = "sequential ";

if ( classlayoutmask == 0x10)

classlayoutstring = "explicit ";

string interfacestring = "";

if ( (typeattributeflags & 0x20) == 0x20)

interfacestring  = "interface ";

string abstractstring = "";

if ( (typeattributeflags & 0x80) == 0x80)

abstractstring  = "abstract ";

string sealedstring = "";

if ( (typeattributeflags & 0x100) == 0x100)

sealedstring  = "sealed ";

string specialnamestring = "";

if ( (typeattributeflags & 0x400) == 0x400)

specialnamestring  = "specialname ";

string importstring = "";

if ( (typeattributeflags & 0x1000) == 0x1000)

importstring  = "import ";

string serializablestring = "";

if ( (typeattributeflags & 0x2000) == 0x2000)

serializablestring = "serializable ";

int stringformatmask = typeattributeflags & 0x30000;

string stringformastring = "";

if ( stringformatmask == 0)

stringformastring = "ansi ";

if ( stringformatmask == 0x10000)

stringformastring = "unicode ";

if ( stringformatmask == 0x20000)

stringformastring = "autochar ";

string beforefieldinitstring = "";

if ( (typeattributeflags & 0x00100000) == 0x00100000)

beforefieldinitstring = "beforefieldinit ";

//string rtspecialnamestring = "";

//if ( (typeattributeflags & 0x800) == 0x800)

//rtspecialnamestring = "rtspecialname ";

if ( IsTypeNested(typeindex) )

returnstring = interfacestring + abstractstring + classlayoutstring + stringformastring +  serializablestring + sealedstring + importstring + visibiltymaskstring  + beforefieldinitstring;

else

returnstring = interfacestring + visibiltymaskstring + abstractstring + classlayoutstring + stringformastring + importstring + serializablestring + sealedstring + specialnamestring + beforefieldinitstring ;

return returnstring;

}

public string DisplayTypeDefExtends (int typedefindex)

{

if ( typedefindex == 0)

return "";

string name = NameReserved(GetString(TypeDefStruct[typedefindex].name));

string returnstring = NameReserved(GetString(TypeDefStruct[typedefindex].nspace));

if ( returnstring.Length != 0)

returnstring = returnstring + ".";

returnstring = returnstring + name  + "/* 02" + typedefindex.ToString("X6") + " */";

return returnstring;

}

public string GetNestedTypeAsString(int rowindex)

{

string netsedtypestring = "";

string namespaceandnameparent2 = "";

string namespaceandnameparent3= "";

if ( IsTypeNested(rowindex) )

{

int rowindexparent = GetParentForNestedType(rowindex);

if ( IsTypeNested(rowindexparent) )

{

int rowindexparentparent = GetParentForNestedType(rowindexparent);

if ( IsTypeNested(rowindexparentparent) )

{

int rowindexp3 = GetParentForNestedType(rowindexparentparent);

string nameparent3 = NameReserved(GetString(TypeDefStruct[rowindexp3].name));

namespaceandnameparent3= NameReserved(GetString(TypeDefStruct[rowindexp3].nspace));

if ( namespaceandnameparent3.Length != 0)

namespaceandnameparent3 = namespaceandnameparent3 + ".";

namespaceandnameparent3= namespaceandnameparent3 + nameparent3 + "/* 02" + rowindexp3.ToString("X6") + " *//";

}

string nameparent2 = NameReserved(GetString(TypeDefStruct[rowindexparentparent].name));

namespaceandnameparent2 = NameReserved(GetString(TypeDefStruct[rowindexparentparent].nspace));

if ( namespaceandnameparent2.Length != 0)

namespaceandnameparent2 = namespaceandnameparent2 + ".";

namespaceandnameparent2 = namespaceandnameparent3 + namespaceandnameparent2 + nameparent2 + "/* 02" + rowindexparentparent.ToString("X6") + " *//";

}

string nameparent1 = NameReserved(GetString(TypeDefStruct[rowindexparent].name));

netsedtypestring = NameReserved(GetString(TypeDefStruct[rowindexparent].nspace));

if ( netsedtypestring.Length != 0)

netsedtypestring = netsedtypestring + ".";

netsedtypestring = namespaceandnameparent2 + netsedtypestring + nameparent1 + "/* 02" + rowindexparent.ToString("X6") + " *//";

}

return netsedtypestring;

}

public int GetParentForNestedType (int typeindex)

{

int ii = 0;

if ( NestedClassStruct == null)

return 0;

for ( ii = 0 ; ii < NestedClassStruct.Length  ; ii++)

{

if ( typeindex == NestedClassStruct[ii].nestedclass )

{

//Console.WriteLine("............{0} {1}" , typeindex , NestedClassStruct[ii].nestedclass);

return NestedClassStruct[ii].enclosingclass;

}

}

return 0;

}

public string DisplayTypeRefExtends (int typerefindex)

{

string returnstring = "";

int resolutionscope = TypeRefStruct[typerefindex].resolutionscope;

string resolutionscopetable = GetResolutionScopeTable(resolutionscope);

int resolutionscopeindex = GetResolutionScopeValue(resolutionscope);

string dummy = "";

if ( resolutionscopetable == "Module")

{

}

if ( resolutionscopetable == "AssemblyRef")

{

returnstring = "[" + NameReserved(GetString(AssemblyRefStruct[resolutionscopeindex].name)) ;

returnstring = returnstring + "/* 23" + resolutionscopeindex.ToString("X6") + " */]";

}

if ( resolutionscopetable == "ModuleRef")

{

returnstring = "[.module " + NameReserved(GetString(ModuleRefStruct[resolutionscopeindex].name))  ;

returnstring = returnstring + "/* 1A" + resolutionscopeindex.ToString("X6") + " */]";

}

if ( resolutionscopetable == "TypeRef")

{

int resolutionscopeindex1 = GetResolutionScopeValue(TypeRefStruct[resolutionscopeindex].resolutionscope );

string resolutionscopetable1 = GetResolutionScopeTable(TypeRefStruct[resolutionscopeindex].resolutionscope );

if ( resolutionscopetable1 == "AssemblyRef")

{

dummy = "[" + NameReserved(GetString(AssemblyRefStruct[resolutionscopeindex1].name)) + "/* 23" + resolutionscopeindex1.ToString("X6") + " */]";

string nspace1 = NameReserved(GetString(TypeRefStruct[resolutionscopeindex].nspace));

if ( nspace1 != "")

nspace1 = nspace1 + ".";

dummy = dummy + nspace1 + NameReserved(GetString(TypeRefStruct[resolutionscopeindex].name)) + "/* 01" + resolutionscopeindex.ToString("X6") + " *//";

}

}

int namespaceindex = TypeRefStruct[typerefindex].nspace;

string nspace = NameReserved(GetString(namespaceindex));

returnstring = returnstring + nspace ;

if ( nspace.Length  != 0)

returnstring = returnstring + ".";

int nameindex = TypeRefStruct[typerefindex].name;

returnstring = dummy + returnstring + NameReserved(GetString(nameindex)) + "/* 01" + typerefindex.ToString("X6") + " */";

return returnstring;

}

public int GetResolutionScopeValue(int rvalue)

{

return rvalue >> 2;

}

public string GetResolutionScopeTable (int rvalue)

{

string returnstring = "";

int tag = rvalue & 0x03;

if ( tag == 0 )

returnstring = returnstring + "Module"  ;

if ( tag == 1 )

returnstring = returnstring + "ModuleRef"  ;

if ( tag == 2 )

returnstring = returnstring + "AssemblyRef"  ;

if ( tag == 3 )

returnstring = returnstring + "TypeRef"  ;

return returnstring;

}

public string DisplayAllInterfaces (int typeindex)

{

string returnstring = "";

if ( InterfaceImplStruct == null )

return "";

for ( int i = 1 ; i < InterfaceImplStruct.Length ; i++)

{

if ( typeindex == InterfaceImplStruct[i].classindex  )

{

string codedtablename = GetTypeDefOrRefTable(InterfaceImplStruct[i].interfaceindex);

int interfaceindex = GetTypeDefOrRefValue(InterfaceImplStruct[i].interfaceindex);

string interfacename = "";

if ( codedtablename == "TypeRef" )

interfacename  = DisplayTypeRefExtends(interfaceindex);

if ( codedtablename == "TypeDef" )

interfacename  = GetNestedTypeAsString(interfaceindex) + DisplayTypeDefExtends(interfaceindex);

returnstring = returnstring + interfacename;

bool nextclassindex ;

if ( i == (InterfaceImplStruct.Length - 1))

nextclassindex = false;

else if ( typeindex != InterfaceImplStruct[i+1].classindex  )

nextclassindex = false;

else

nextclassindex = true;

if ( nextclassindex )

returnstring = returnstring + ",\r\n                  " + CreateSpaces(spacefornamespace+spacesfornested);

else

returnstring = returnstring + "\r\n";

}

}

return returnstring;

}

 

public static void Main (string [] args)

{

try

{

zzz a = new zzz();

a.abc(args);

}

catch ( Exception e)

{

Console.WriteLine(e.ToString());

}

}

public void ReadPEStructures(string [] args)

{

filename = args[0];

mfilestream  = new FileStream(filename ,FileMode.Open);

mbinaryreader = new BinaryReader (mfilestream);

mfilestream.Seek(60, SeekOrigin.Begin);

int startofpeheader = mbinaryreader.ReadInt32();

mfilestream.Seek(startofpeheader, SeekOrigin.Begin);

byte sig1,sig2,sig3,sig4;

sig1 = mbinaryreader.ReadByte();

sig2 = mbinaryreader.ReadByte();

sig3 = mbinaryreader.ReadByte();

sig4 = mbinaryreader.ReadByte();

//First Structure

short machine = mbinaryreader.ReadInt16();

sections = mbinaryreader.ReadInt16();

int time = mbinaryreader.ReadInt32();

int pointer = mbinaryreader.ReadInt32();

int symbols = mbinaryreader.ReadInt32();

int headersize= mbinaryreader.ReadInt16();

int characteristics = mbinaryreader.ReadInt16();

sectionoffset = mfilestream.Position + headersize;

//Second Structure

int magic = mbinaryreader.ReadInt16();

int major = mbinaryreader.ReadByte();

int minor = mbinaryreader.ReadByte();

int sizeofcode = mbinaryreader.ReadInt32();

int sizeofdata = mbinaryreader.ReadInt32();

int sizeofudata = mbinaryreader.ReadInt32();

entrypoint = mbinaryreader.ReadInt32();

int baseofcode = mbinaryreader.ReadInt32();

int baseofdata = mbinaryreader.ReadInt32();

ImageBase = mbinaryreader.ReadInt32();

sectiona= mbinaryreader.ReadInt32();

filea = mbinaryreader.ReadInt32();

int majoros = mbinaryreader.ReadInt16();

int minoros = mbinaryreader.ReadInt16();

int majorimage = mbinaryreader.ReadInt16();

int minorimage = mbinaryreader.ReadInt16();

int majorsubsystem= mbinaryreader.ReadInt16();

int minorsubsystem = mbinaryreader.ReadInt16();

int verison = mbinaryreader.ReadInt32();

int imagesize = mbinaryreader.ReadInt32();

int sizeofheaders= mbinaryreader.ReadInt32();

int checksum = mbinaryreader.ReadInt32();

subsystem = mbinaryreader.ReadInt16();

int dllflags = mbinaryreader.ReadInt16();

stackreserve = mbinaryreader.ReadInt32();

stackcommit = mbinaryreader.ReadInt32();

int heapreserve = mbinaryreader.ReadInt32();

int heapcommit = mbinaryreader.ReadInt32();

int loader = mbinaryreader.ReadInt32();

datad = mbinaryreader.ReadInt32();

datadirectoryrva = new int[16];

datadirectorysize = new int[16];

for ( int i = 0 ; i <=15 ; i++)

{

datadirectoryrva[i] = mbinaryreader.ReadInt32();

datadirectorysize[i] = mbinaryreader.ReadInt32();

}

if ( datadirectorysize[14] == 0)

throw new System.Exception("Not a valid CLR file");

mfilestream.Position = sectionoffset ;

SVirtualAddress = new int[sections ];

SSizeOfRawData = new int[sections ];

SPointerToRawData = new int[sections ];

for ( int i = 0 ; i < sections ; i++)

{

mbinaryreader.ReadBytes(12);

SVirtualAddress[i] = mbinaryreader.ReadInt32();

SSizeOfRawData[i] = mbinaryreader.ReadInt32();

SPointerToRawData[i] = mbinaryreader.ReadInt32();

mbinaryreader.ReadBytes(16);

}

}

public void DisplayPEStructures()

{

Console.WriteLine();

Console.WriteLine("//  Microsoft (R) .NET Framework IL Disassembler.  Version 1.0.3328.4");

Console.WriteLine("//  Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.");

Console.WriteLine();

Console.WriteLine("// PE Header:");

Console.WriteLine("// Subsystem:                      {0}",subsystem.ToString("x8"));

Console.WriteLine("// Native entry point address:     {0}",entrypoint.ToString("x8"));

Console.WriteLine("// Image base:                     {0}",ImageBase.ToString("x8"));

Console.WriteLine("// Section alignment:              {0}",sectiona.ToString("x8"));

Console.WriteLine("// File alignment:                 {0}",filea.ToString("x8"));

Console.WriteLine("// Stack reserve size:             {0}",stackreserve.ToString("x8"));

Console.WriteLine("// Stack commit size:              {0}",stackcommit.ToString("x8"));

Console.WriteLine("// Directories:                    {0}",datad.ToString("x8"));

DisplayDataDirectory(datadirectoryrva[0] , datadirectorysize[0] , "Export Directory");

DisplayDataDirectory(datadirectoryrva[1] , datadirectorysize[1] , "Import Directory");

DisplayDataDirectory(datadirectoryrva[2] , datadirectorysize[2] , "Resource Directory");

DisplayDataDirectory(datadirectoryrva[3] , datadirectorysize[3] , "Exception Directory");

DisplayDataDirectory(datadirectoryrva[4] , datadirectorysize[4] , "Security Directory");

DisplayDataDirectory(datadirectoryrva[5] , datadirectorysize[5] , "Base Relocation Table");

DisplayDataDirectory(datadirectoryrva[6] , datadirectorysize[6] , "Debug Directory");

DisplayDataDirectory(datadirectoryrva[7] , datadirectorysize[7] , "Architecture Specific");

DisplayDataDirectory(datadirectoryrva[8] , datadirectorysize[8] , "Global Pointer");

DisplayDataDirectory(datadirectoryrva[9] , datadirectorysize[9] , "TLS Directory");

DisplayDataDirectory(datadirectoryrva[10] , datadirectorysize[10] , "Load Config Directory");

DisplayDataDirectory(datadirectoryrva[11] , datadirectorysize[11] , "Bound Import Directory");

DisplayDataDirectory(datadirectoryrva[12] , datadirectorysize[12] , "Import Address Table");

DisplayDataDirectory(datadirectoryrva[13] , datadirectorysize[13] , "Delay Load IAT");

DisplayDataDirectory(datadirectoryrva[14] , datadirectorysize[14] , "CLR Header");

Console.WriteLine();

}

public void DisplayDataDirectory(int rva, int size , string ss)

{

string sfinal =  "";

sfinal = String.Format("// {0:x}" , rva);

sfinal = sfinal.PadRight(12);

sfinal = sfinal + String.Format("[{0:x}" , size);

sfinal = sfinal.PadRight(21);

sfinal = sfinal + String.Format("] address [size] of {0}:" , ss);

if (ss == "CLR Header")

sfinal = sfinal.PadRight(67);

else

sfinal = sfinal.PadRight(68);

Console.WriteLine(sfinal);

}

public void ReadandDisplayImportAdressTable()

{

long stratofimports = ConvertRVA(datadirectoryrva[1]);

mfilestream.Position = stratofimports;

Console.WriteLine("// Import Address Table");

int outercount = 0;

while (true)

{

int rvaimportlookuptable = mbinaryreader.ReadInt32();

if ( rvaimportlookuptable == 0)

break;

int datetimestamp = mbinaryreader.ReadInt32();

int forwarderchain = mbinaryreader.ReadInt32();

int name = mbinaryreader.ReadInt32();

int rvaiat = mbinaryreader.ReadInt32();

mfilestream.Position = ConvertRVA(name);

Console.Write("//     ");

DisplayStringFromFile();

Console.WriteLine("//              {0} Import Address Table" , rvaiat.ToString("x8"));

Console.WriteLine("//              {0} Import Name Table" , name.ToString("x8"));

Console.WriteLine("//              {0}        time date stamp" , datetimestamp);

Console.WriteLine("//              {0}        Index of first forwarder reference" , forwarderchain);

Console.WriteLine("//");

 

long importtable = ConvertRVA(rvaimportlookuptable ) ;

mfilestream.Position = importtable;

int nexttable = mbinaryreader.ReadInt32();

if ( nexttable < 0 )

{

Console.WriteLine("// Failed to read import data.");

Console.WriteLine();

outercount++;

mfilestream.Position = stratofimports + outercount * 20;

continue;

}

 

int innercount = 0;

while ( true  )

{

long pos0 = ConvertRVA(rvaimportlookuptable ) + innercount * 4;

mfilestream.Position = pos0;

int pos1 = mbinaryreader.ReadInt32();

if ( pos1 == 0)

break;

long pos2 = ConvertRVA(pos1);

mfilestream.Position = pos2;

short hint = mbinaryreader.ReadInt16();

Console.Write("//                  ");

if ( hint.ToString("X").Length == 1)

Console.Write("  {0}" , hint.ToString("x"));

if ( hint.ToString("X").Length == 2)

Console.Write(" {0}" , hint.ToString("x"));

if ( hint.ToString("X").Length == 3)

Console.Write("{0}" , hint.ToString("x"));

Console.Write("  ");

DisplayStringFromFile();

innercount++;

}

Console.WriteLine();

outercount++;

mfilestream.Position = stratofimports + outercount * 20;

}

Console.WriteLine("// Delay Load Import Address Table");

if (datadirectoryrva[13] == 0)

Console.WriteLine("// No data.");

if (datadirectoryrva[13] != 0)

Console.WriteLine("........................// No data.");

}

public void DisplayStringFromFile()

{

while ( true )

{

byte filebyte = (byte )mfilestream.ReadByte();

if ( filebyte == 0)

break;

Console.Write("{0}" , (char)filebyte);

}

Console.WriteLine();

}

public void ReadandDisplayCLRHeader()

{

Console.WriteLine("// CLR Header:");

mfilestream.Position = ConvertRVA(datadirectoryrva[14]);

int size = mbinaryreader.ReadInt32();

int majorruntimeversion = mbinaryreader.ReadInt16();

int minorruntimeversion = mbinaryreader.ReadInt16();

metadatarva = mbinaryreader.ReadInt32();

int metadatasize = mbinaryreader.ReadInt32();

corflags = mbinaryreader.ReadInt32();

entrypointtoken = mbinaryreader.ReadInt32();

int resourcesrva = mbinaryreader.ReadInt32();

int resourcessize = mbinaryreader.ReadInt32();

int strongnamesigrva = mbinaryreader.ReadInt32();

int strongnamesigsize = mbinaryreader.ReadInt32();

int codemanagerrva = mbinaryreader.ReadInt32();

int codemanagersize = mbinaryreader.ReadInt32();

vtablerva = mbinaryreader.ReadInt32();

vtablesize = mbinaryreader.ReadInt32();

exportaddressrva = mbinaryreader.ReadInt32();

exportaddresssize = mbinaryreader.ReadInt32();

int managednativeheaderrva = mbinaryreader.ReadInt32();

int managednativeheadersize = mbinaryreader.ReadInt32();

if ( size >= 100)

Console.WriteLine("// {0}      Header Size", size);

else

Console.WriteLine("// {0}       Header Size", size);

Console.WriteLine("// {0}        Major Runtime Version", majorruntimeversion);

Console.WriteLine("// {0}        Minor Runtime Version", minorruntimeversion);

Console.WriteLine("// {0}        Flags", corflags.ToString("x"));

string dummy = "// " + entrypointtoken.ToString("x");

dummy = dummy.PadRight(12) + "Entrypoint Token";

Console.WriteLine(dummy);

DisplayDataDirectory(metadatarva , metadatasize , "Metadata Directory");

DisplayDataDirectory(resourcesrva, resourcessize, "Resources Directory");

DisplayDataDirectory(strongnamesigrva, strongnamesigsize, "Strong Name Signature");

DisplayDataDirectory(codemanagerrva, codemanagersize, "CodeManager Table");

DisplayDataDirectory(vtablerva, vtablesize, "VTableFixups Directory");

DisplayDataDirectory(exportaddressrva, exportaddresssize , "Export Address Table");

DisplayDataDirectory(managednativeheaderrva, managednativeheadersize, "Precompile Header");

Console.WriteLine("// Code Manager Table:");

if ( codemanagerrva == 0)

Console.WriteLine("//  default");

}

public void ReadStreamsData()

{

startofmetadata = ConvertRVA(metadatarva);

if ( debug )

Console.WriteLine("Start of Metadata {0} rva={1}" , metadatarva , startofmetadata );

mfilestream.Position = startofmetadata ;

mfilestream.Seek(4 + 2 + 2 + 4 , SeekOrigin.Current);

int lengthofstring = mbinaryreader.ReadInt32();

if ( debug )

Console.WriteLine("Length of String {0}" , lengthofstring );

mfilestream.Seek(lengthofstring , SeekOrigin.Current);

long padding = mfilestream.Position % 4 ;

if ( debug )

Console.WriteLine("Padding {0}" , padding );

mfilestream.Seek(2 , SeekOrigin.Current);

int streams = mbinaryreader.ReadInt16();

if ( debug )

Console.WriteLine("No of streams {0} Position={1}" , streams , mfilestream.Position);

streamnames = new string[5];

offset = new int[5];

ssize  = new int[5];

names = new byte[5][];

names[0] = new byte[10];

names[1] = new byte[10];

names[2] = new byte[10];

names[3] = new byte[10];

names[4] = new byte[10];

int j ;

for ( int i = 0 ; i < streams ; i++)

{

if (debug)

Console.WriteLine("At Start Position={0} {1}" , mfilestream.Position  , mfilestream.Position % 4);

offset[i] = mbinaryreader.ReadInt32();

ssize[i] = mbinaryreader.ReadInt32();

if (debug)

Console.WriteLine("offset={0} size={1} Position={2}" , offset[i] , ssize[i] , mfilestream.Position);

j = 0;

byte bb ;

while ( true )

{

bb = mbinaryreader.ReadByte();

if ( bb == 0)

break;

names[i][j] = bb;

j++;

}

names[i][j] = bb;

streamnames[i] = GetStreamNames(names[i]);

while ( true )

{

if ( mfilestream.Position % 4 == 0 )

break;

byte  b = mbinaryreader.ReadByte();

}

if (debug)

Console.WriteLine("At End Position={0} {1}" , mfilestream.Position  , mfilestream.Position % 4);

}

for ( int i = 0 ; i < streams ; i++)

{

if ( streamnames[i]  == "#~"  || streamnames[i]  == "#-" )

{

metadata = new byte[ssize[i]];

mfilestream.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);

for ( int k = 0 ; k < ssize[i] ; k ++)

metadata[k] = mbinaryreader.ReadByte();

}

if ( streamnames[i]  == "#Strings" )

{

strings = new byte[ssize[i]];

mfilestream.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);

for ( int k = 0 ; k < ssize[i] ; k ++)

strings[k] = mbinaryreader.ReadByte();

}

if ( streamnames[i]  == "#US" )

{

us = new byte[ssize[i]];

mfilestream.Seek(startofmetadata  + offset[i] , SeekOrigin.Begin);

for ( int k = 0 ; k < ssize[i] ; k ++)

us[k] = mbinaryreader.ReadByte();

}

if ( streamnames[i]  == "#GUID" )

{

guid = new byte[ssize[i]];

mfilestream.Seek(startofmetadata  + offset[i] , SeekOrigin.Begin);

for ( int k = 0 ; k < ssize[i] ; k ++)

guid[k] = mbinaryreader.ReadByte();

}

if ( streamnames[i]  == "#Blob" )

{

blob = new byte[ssize[i]];

mfilestream.Seek(startofmetadata  + offset[i] , SeekOrigin.Begin);

for ( int k = 0 ; k < ssize[i] ; k ++)

blob[k] = mbinaryreader.ReadByte();

}

}

if ( debug )

{

for ( int i = 0 ; i < streams ; i++)

{

Console.WriteLine("{0} offset {1} size {2}" , streamnames[i] ,  offset[i] , ssize[i]);

if ( streamnames[i] == "#~" || streamnames[i]  == "#-" )

{

for ( int ii = 0 ; ii <= 9 ; ii++)

Console.Write("{0} " , metadata[ii].ToString("X"));

Console.WriteLine();

}

if ( streamnames[i] == "#Strings")

{

for ( int ii = 0 ; ii <= 9 ; ii++)

Console.Write("{0} " , strings[ii].ToString("X"));

Console.WriteLine();

}

if ( streamnames[i] == "#US")

{

for ( int ii = 0 ; ii <= 9 ; ii++)

Console.Write("{0} " , us[ii].ToString("X"));

Console.WriteLine();

}

if ( streamnames[i] == "#GUID")

{

for ( int ii = 0 ; ii <= 9 ; ii++)

Console.Write("{0} " , guid[ii].ToString("X"));

Console.WriteLine();

}

if ( streamnames[i] == "#Blob")

{

for ( int ii = 0 ; ii <= 9 ; ii++)

Console.Write("{0} " , blob[ii].ToString("X"));

Console.WriteLine();

}

}

}

int heapsizes = metadata[6];

if ( (heapsizes & 0x01) == 0x01)

offsetstring  = 4;

if ( (heapsizes & 0x02) == 0x02)

offsetguid = 4;

if ( (heapsizes & 0x04) == 0x04)

offsetblob = 4;

valid = BitConverter.ToInt64(metadata, 8);

tableoffset = 24;

rows = new int[64];

Array.Clear (rows, 0, rows.Length);

for ( int k = 0 ; k <= 63 ; k++)

{

int tablepresent = (int)(valid >> k ) & 1;

if ( tablepresent == 1)

{

rows[k] = BitConverter.ToInt32(metadata , tableoffset);

tableoffset += 4;

}

}

if ( debug )

{

for ( int k = 62 ; k >= 0 ; k--)

{

int tablepresent = (int)(valid >> k ) & 1;

if ( tablepresent == 1)

{

Console.WriteLine("{0} {1}" , tablenames[k] , rows[k]);

}

}

}

}

public string GetStreamNames(byte [] b)

{

int i = 0;

while (b[i] != 0 )

{

i++;

}

System.Text.Encoding e = System.Text.Encoding.UTF8;

string  dummy = e.GetString(b , 0 , i  );

return dummy;

}

public void FillTableSizes()

{

int modulesize = 2 + offsetstring + offsetguid + offsetguid + offsetguid ;

int typerefsize  = GetCodedIndexSize("ResolutionScope") + offsetstring + offsetstring ;

int typedefsize = 4 + offsetstring + offsetstring + GetCodedIndexSize("TypeDefOrRef") + GetTableSize("Method") + GetTableSize("Field");

int fieldsize = 2 + offsetstring + offsetblob ;

int methodsize = 4 + 2 + 2 + offsetstring + offsetblob + GetTableSize("Param");

int paramsize = 2 + 2 + offsetstring;

int interfaceimplsize = GetTableSize("TypeDef") + GetCodedIndexSize("TypeDefOrRef");

int memberrefsize = GetCodedIndexSize("MemberRefParent") + offsetstring  + offsetblob ;

int constantsize = 2 + GetCodedIndexSize("HasConst") + offsetblob;

int customattributesize = GetCodedIndexSize("HasCustomAttribute") + GetCodedIndexSize("HasCustomAttributeType") + offsetblob;

int fieldmarshallsize = GetCodedIndexSize("HasFieldMarshal") + offsetblob;

int declsecuritysize = 2 + GetCodedIndexSize("HasDeclSecurity") + offsetblob;

int classlayoutsize = 2 + 4 + GetTableSize("TypeDef");

int fieldlayoutsize = 4 + GetTableSize("Field");

int stanalonssigsize = offsetblob;

int eventmapsize = GetTableSize("TypeDef") +  GetTableSize("Event");

int eventsize = 2 + offsetstring + GetCodedIndexSize("TypeDefOrRef");

int propertymapsize = GetTableSize("Properties") + GetTableSize("TypeDef") ;

int propertysize = 2 + offsetstring + offsetblob;

int methodsemantics = 2 + GetTableSize("Method") + GetCodedIndexSize("HasSemantics");

int methodimplsize = GetTableSize("TypeDef") + GetCodedIndexSize("MethodDefOrRef") + GetCodedIndexSize("MethodDefOrRef");

int modulerefsize = offsetstring;

int typespecsize = offsetblob;

int implmapsize = 2 + GetCodedIndexSize("MemberForwarded") + offsetstring + GetTableSize("ModuleRef");

int fieldrvasize = 4  + GetTableSize("Field");

int assemblysize = 4 + 2 + 2 + 2 + 2 + 4 +  offsetblob + offsetstring + offsetstring ;

int assemblyrefsize = 2 + 2 + 2 + 2 + 4 +  offsetblob + offsetstring + offsetstring + offsetblob;

int filesize = 4 + offsetstring + offsetblob;

int exportedtype = 4 + 4 + offsetstring + offsetstring + GetCodedIndexSize("Implementation");

int manifestresourcesize = 4 + 4 + offsetstring + GetCodedIndexSize("Implementation");

int nestedclasssize = GetTableSize("TypeDef") + GetTableSize("TypeDef") ;

sizes = new int[]{ modulesize, typerefsize , typedefsize ,2, fieldsize ,2,methodsize ,2,paramsize ,interfaceimplsize,memberrefsize ,constantsize ,customattributesize ,fieldmarshallsize ,declsecuritysize ,classlayoutsize ,fieldlayoutsize,stanalonssigsize ,eventmapsize ,2,eventsize ,propertymapsize ,2,propertysize ,methodsemantics ,methodimplsize ,modulerefsize ,typespecsize ,implmapsize ,fieldrvasize ,2 , 2 , assemblysize ,4,12,assemblyrefsize ,6,14,filesize ,exportedtype ,manifestresourcesize ,nestedclasssize };

}

public int GetCodedIndexSize(string nameoftable)

{

if ( nameoftable == "Implementation")

{

if ( rows[0x26] >= 16384 || rows[0x23] >= 16384 || rows[0x27] >= 16384 )

return 4;

else

return 2;

}

else if ( nameoftable == "MemberForwarded")

{

if ( rows[0x04] >= 32768 || rows[0x06] >= 32768)

return 4;

else

return 2;

}

else if ( nameoftable == "MethodDefOrRef")

{

if ( rows[0x06] >= 32768 || rows[0x0A] >= 32768)

return 4;

else

return 2;

}

else if ( nameoftable == "HasSemantics")

{

if ( rows[0x14] >= 32768 || rows[0x17] >= 32768)

return 4;

else

return 2;

}

else if ( nameoftable == "HasDeclSecurity")

{

if ( rows[0x02] >= 16384 || rows[0x06] >= 16384 || rows[0x20] >= 16384)

return 4;

else

return 2;

}

else if ( nameoftable == "HasFieldMarshal")

{

if ( rows[0x04] >= 32768|| rows[0x08] >= 32768)

return 4;

else

return 2;

}

else if ( nameoftable == "TypeDefOrRef")

{

if ( rows[0x02] >= 16384 || rows[0x01] >= 16384  || rows[0x1B] >= 16384   )

return 4;

else

return 2;

}

else if ( nameoftable == "ResolutionScope")

{

if ( rows[0x00] >= 16384 || rows[0x1a] >= 16384  || rows[0x23] >= 16384  || rows[0x01] >= 16384 )

return 4;

else

return 2;

}

else if ( nameoftable == "HasConst")

{

if ( rows[4] >= 16384 || rows[8] >= 16384 || rows[0x17] >= 16384 )

return 4;

else

return 2;

}

else if ( nameoftable == "MemberRefParent")

{

if ( rows[0x08] >= 8192 || rows[0x04] >= 8192 || rows[0x17] >= 8192  )

return 4;

else

return 2;

}

else if ( nameoftable == "HasCustomAttribute")

{

if ( rows[0x06] >= 2048 || rows[0x04] >= 2048 || rows[0x01] >= 2048 || rows[0x02] >= 2048 || rows[0x08] >= 2048 || rows[0x09] >= 2048 || rows[0x0a] >= 2048 || rows[0x00] >= 2048 || rows[0x0e] >= 2048 || rows[0x17] >= 2048 || rows[0x14] >= 2048 || rows[0x11] >= 2048 || rows[0x1a] >= 2048 || rows[0x1b] >= 2048 || rows[0x20] >= 2048 || rows[0x23] >= 2048 || rows[0x26] >= 2048 || rows[0x27] >= 2048 || rows[0x28] >= 2048 )

return 4;

else

return 2;

}

else if ( nameoftable == "HasCustomAttributeType")

{

if ( rows[2] >= 8192 || rows[1] >= 8192 || rows[6] >= 8192 || rows[0x0a] >= 8192 )

return 4;

else

return 2;

}

else

return 2;

}

public int ReadCodedIndex(byte [] metadataarray , int offset , string nameoftable)

{

int returnindex = 0;

int codedindexsize = GetCodedIndexSize(nameoftable);

if ( codedindexsize == 2)

returnindex = BitConverter.ToUInt16 (metadataarray , offset );

if ( codedindexsize == 4)

returnindex = (int)BitConverter.ToUInt32 (metadataarray , offset );

return returnindex;

}

public void ReadTablesIntoStructures()

{

if ( rows[5] > 0)

Console.WriteLine("........");

 

//Module

int old = tableoffset;

bool tablehasrows  = tablepresent(0);

int offs = tableoffset;

if ( debug )

Console.WriteLine("Module Table Offset {0} Size {1}" , offs , sizes[0]);

tableoffset = old;

if ( tablehasrows  )

{

ModuleStruct = new ModuleTable[rows[0] + 1];

for ( int k = 1 ; k <= rows[0] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ModuleStruct[k].Generation = BitConverter.ToUInt16 (metadata, offs);

offs += 2;

ModuleStruct[k].Name = ReadStringIndex(metadata, offs);

offs += offsetstring;

ModuleStruct[k].Mvid = ReadGuidIndex(metadata, offs);

offs += offsetguid;

ModuleStruct[k].EncId = ReadGuidIndex(metadata, offs);

offs += offsetguid;

ModuleStruct[k].EncBaseId = ReadGuidIndex(metadata, offs);

offs += offsetguid;

}

}

//TypeRef

old = tableoffset;

tablehasrows = tablepresent(1);

offs = tableoffset;

if ( debug )

Console.WriteLine("TypeRef Table Offset {0} Size {1}" , offs ,  sizes[1]);

tableoffset = old;

if ( tablehasrows )

{

//if ( debug )

//Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

TypeRefStruct = new TypeRefTable[rows[1] + 1];

for ( int k = 1 ; k <=rows[1] ; k++)

{

//if ( debug )

//Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

TypeRefStruct[k].resolutionscope = ReadCodedIndex(metadata , offs , "ResolutionScope");

offs = offs + GetCodedIndexSize("ResolutionScope");

TypeRefStruct[k].name = ReadStringIndex(metadata , offs);

offs = offs + offsetstring;

TypeRefStruct[k].nspace = ReadStringIndex(metadata , offs);

offs = offs + offsetstring;

//Console.WriteLine("......TypeRef {0}" , GetString(TypeRefStruct[k].name));

}

}

//TypeDef

old = tableoffset;

tablehasrows  = tablepresent(2);

offs = tableoffset;

if ( debug )

Console.WriteLine("TypeDef Table Offset {0} Size {1}" , offs , sizes[2]);

tableoffset = old;

if ( tablehasrows )

{

TypeDefStruct = new TypeDefTable[rows[2] + 1];

for ( int k = 1 ; k <= rows[2] ; k++)

{

//if ( debug )

//Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X") , metadata[offs+9].ToString("X") , metadata[offs+10].ToString("X")  );

TypeDefStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

TypeDefStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

TypeDefStruct[k].nspace = ReadStringIndex(metadata, offs);

offs += offsetstring;

TypeDefStruct[k].cindex = ReadCodedIndex(metadata , offs , "TypeDefOrRef");

offs += GetCodedIndexSize("TypeDefOrRef");

TypeDefStruct[k].findex = ReadTableIndex(metadata, offs , "Field");

offs += GetTableSize("Field");

TypeDefStruct[k].mindex = ReadTableIndex(metadata, offs , "Method");

offs += GetTableSize("Method");

//Console.WriteLine("......TypeDef {0}" , GetString(TypeDefStruct[k].name));

}

}

//FieldPtr

old = tableoffset;

tablehasrows  = tablepresent(3);

offs = tableoffset;

if ( debug )

Console.WriteLine("FieldPtr Table Offset {0} Size {1}" , offs , sizes[3]);

tableoffset = old;

if ( tablehasrows )

{

FieldPtrStruct = new FieldPtrTable[rows[3] + 1];

for ( int k = 1 ; k <= rows[3] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FieldPtrStruct[k].index = BitConverter.ToInt16(metadata, offs);

offs += 2;

}

}

//Field

old = tableoffset;

tablehasrows  = tablepresent(4);

offs = tableoffset;

if ( debug )

Console.WriteLine("Field Table Offset {0} Size {1}" , offs , sizes[4]);

tableoffset = old;

if ( tablehasrows )

{

FieldStruct = new FieldTable[rows[4] + 1];

for ( int k = 1 ; k <= rows[4] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FieldStruct[k].flags = BitConverter.ToInt16 (metadata, offs);

offs += 2;

FieldStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

FieldStruct[k].sig = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//MethodPtr

old = tableoffset;

tablehasrows  = tablepresent(5);

offs = tableoffset;

if ( debug )

Console.WriteLine("Method Table Offset {0} Size {1}" , offs , sizes[5]);

tableoffset = old;

if ( tablehasrows )

{

MethodPtrStruct = new MethodPtrTable[rows[5] + 1];

for ( int k = 1 ; k <= rows[5] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

MethodPtrStruct[k].index = BitConverter.ToInt16(metadata, offs);

offs += 2;

}

}

//Method

old = tableoffset;

tablehasrows  = tablepresent(6);

offs = tableoffset;

if ( debug )

Console.WriteLine("Method Table Offset {0} Size {1}" , offs , sizes[6]);

tableoffset = old;

if ( tablehasrows )

{

MethodStruct = new MethodTable[rows[6] + 1];

for ( int k = 1 ; k <= rows[6] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

MethodStruct[k].rva = BitConverter.ToInt32 (metadata, offs);

offs += 4;

MethodStruct[k].impflags = BitConverter.ToInt16 (metadata, offs);

offs += 2;

MethodStruct[k].flags = (int)BitConverter.ToInt16 (metadata, offs);

offs += 2;

MethodStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

MethodStruct[k].signature = ReadBlobIndex(metadata, offs);

offs += offsetblob;

MethodStruct[k].param = ReadTableIndex(metadata, offs , "Param");

offs += GetTableSize("Param");

//Console.WriteLine("Method name={0} ParmNo={1}" , GetString(MethodStruct[k].name),MethodStruct[k].param);

}

}

//Param

old = tableoffset;

tablehasrows  = tablepresent(8);

offs = tableoffset;

if ( debug )

Console.WriteLine("Param Table Offset {0} Size {1}" , offs , sizes[8]);

tableoffset = old;

if ( tablehasrows )

{

ParamStruct = new ParamTable[rows[8] + 1];

for ( int k = 1 ; k <= rows[8] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ParamStruct[k].pattr = BitConverter.ToInt16 (metadata, offs);

offs += 2;

ParamStruct[k].sequence = BitConverter.ToInt16 (metadata, offs);

offs += 2;

ParamStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

//Console.WriteLine("Param {0} name={2} seq={1} attr={3}" ,k, ParamStruct[k].sequence , GetString(ParamStruct[k].name) , ParamStruct[k].pattr);

}

}

//InterfaceImpl

old = tableoffset;

tablehasrows  = tablepresent(9);

offs = tableoffset;

if ( debug )

Console.WriteLine("InterfaceImpl Table Offset {0} Size {1}" , offs , sizes[9]);

tableoffset = old;

if ( tablehasrows )

{

InterfaceImplStruct = new InterfaceImplTable[rows[9] + 1];

for ( int k = 1 ; k <= rows[9] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

InterfaceImplStruct[k].classindex = ReadCodedIndex(metadata , offs , "TypeDefOrRef");

offs += GetCodedIndexSize("TypeDefOrRef");

InterfaceImplStruct[k].interfaceindex = ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

}

}

//MemberRef

old = tableoffset;

tablehasrows  = tablepresent(10);

offs = tableoffset;

if ( debug )

Console.WriteLine("MemberRef Table Offset {0} Size {1}" , offs, sizes[10]);

tableoffset = old;

if ( tablehasrows )

{

MemberRefStruct = new MemberRefTable[rows[10] + 1];

for ( int k = 1 ; k <= rows[10] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

MemberRefStruct[k].clas = ReadCodedIndex(metadata , offs , "MemberRefParent");

offs += GetCodedIndexSize("MemberRefParent");

MemberRefStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

MemberRefStruct[k].sig = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//Constants

old = tableoffset;

tablehasrows  = tablepresent(11);

offs = tableoffset;

if ( debug )

Console.WriteLine("Constant Table Offset {0} Size {1}" , offs, sizes[11]);

tableoffset = old;

if ( tablehasrows )

{

ConstantsStruct = new ConstantsTable[rows[11] + 1];

for ( int k = 1 ; k <= rows[11] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ConstantsStruct[k].dtype = metadata[offs];

offs += 2;

ConstantsStruct[k].parent = ReadCodedIndex(metadata , offs , "HasConst");

offs += GetCodedIndexSize("HasConst");

ConstantsStruct[k].value = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//CustomAttribute

old = tableoffset;

tablehasrows  = tablepresent(12);

offs = tableoffset;

if ( debug )

Console.WriteLine("CustomAttribute Table Offset {0} Size {1}" , offs , sizes[12]);

tableoffset = old;

if ( tablehasrows )

{

CustomAttributeStruct = new CustomAttributeTable[rows[12] + 1];

for ( int k = 1 ; k <= rows[12] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

CustomAttributeStruct[k].parent = ReadCodedIndex(metadata , offs , "HasCustomAttribute");

offs += GetCodedIndexSize("HasCustomAttribute");

CustomAttributeStruct[k].type = ReadCodedIndex(metadata , offs , "HasCustomAttributeType");

offs += GetCodedIndexSize("HasCustomAttributeType");

CustomAttributeStruct[k].value = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//FieldMarshal

old = tableoffset;

tablehasrows  = tablepresent(13);

offs = tableoffset;

if ( debug )

Console.WriteLine("FieldMarshal Table Offset {0} Size {1}" , offs , sizes[13]);

tableoffset = old;

if ( tablehasrows )

{

FieldMarshalStruct = new FieldMarshalTable[rows[13] + 1];

for ( int k = 1 ; k <= rows[13] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FieldMarshalStruct[k].coded = ReadCodedIndex(metadata , offs , "HasFieldMarshal");

offs += GetCodedIndexSize("HasFieldMarshal");

FieldMarshalStruct[k].index = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//DeclSecurity

old = tableoffset;

tablehasrows  = tablepresent(14);

offs = tableoffset;

if ( debug )

Console.WriteLine("DeclSecurity Table Offset {0} Size {1}" , offs , sizes[14]);

tableoffset = old;

if ( tablehasrows )

{

DeclSecurityStruct = new DeclSecurityTable[rows[14] + 1];

for ( int k = 1 ; k <= rows[14] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

DeclSecurityStruct[k].action = BitConverter.ToInt16 (metadata, offs);

offs += 2;

DeclSecurityStruct[k].coded = ReadCodedIndex(metadata , offs , "HasDeclSecurity");

offs += GetCodedIndexSize("HasDeclSecurity");

DeclSecurityStruct[k].bindex = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//ClassLayout

old = tableoffset;

tablehasrows  = tablepresent(15);

offs = tableoffset;

if ( debug )

Console.WriteLine("ClassLayout Table Offset {0} Size {1}" , offs, sizes[15]);

tableoffset = old;

if ( tablehasrows )

{

ClassLayoutStruct = new ClassLayoutTable[rows[15] + 1];

for ( int k = 1 ; k <= rows[15] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ClassLayoutStruct[k].packingsize = BitConverter.ToInt16 (metadata, offs);

offs += 2;

ClassLayoutStruct[k].classsize = BitConverter.ToInt32 (metadata, offs);

offs += 4;

ClassLayoutStruct[k].parent = ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

}

}

//FieldLayout

old = tableoffset;

tablehasrows  = tablepresent(16);

offs = tableoffset;

if ( debug )

Console.WriteLine("FieldLayout Table Offset {0} {1}" , offs, sizes[16]);

tableoffset = old;

if ( tablehasrows )

{

FieldLayoutStruct = new FieldLayoutTable[rows[16] + 1];

for ( int k = 1 ; k <= rows[16] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FieldLayoutStruct[k].offset = BitConverter.ToInt32 (metadata, offs);

offs += 4;

FieldLayoutStruct[k].fieldindex = ReadTableIndex(metadata, offs , "Field");

offs += GetTableSize("Field");

}

}

//StandAloneSig

old = tableoffset;

tablehasrows  = tablepresent(17);

offs = tableoffset;

if ( debug )

Console.WriteLine("StandAloneSig Table Offset {0} Size {1}" , offs, sizes[17]);

tableoffset = old;

if ( tablehasrows )

{

StandAloneSigStruct = new StandAloneSigTable[rows[17] + 1];

for ( int k = 1 ; k <= rows[17] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

StandAloneSigStruct[k].index = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//EventMap

old = tableoffset ;

tablehasrows  = tablepresent(18);

offs = tableoffset;

if ( debug )

Console.WriteLine("EventMap Table Offset {0} Size {1}" , offs, sizes[18]);

tableoffset = old;

if ( tablehasrows )

{

EventMapStruct = new EventMapTable [rows[18] + 1];

for ( int k = 1 ; k <= rows[18] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

EventMapStruct[k].index = ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

EventMapStruct[k].eindex = ReadTableIndex(metadata, offs , "Event");

offs += GetTableSize("Event");

}

}

//Event

old = tableoffset;

tablehasrows  = tablepresent(20);

offs = tableoffset;

if ( debug )

Console.WriteLine("Event Table Offset {0} Size {1}" , offs, sizes[20]);

tableoffset = old;

if ( tablehasrows )

{

EventStruct = new EventTable[rows[20] + 1];

for ( int k = 1 ; k <= rows[20] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

EventStruct[k].attr = BitConverter.ToInt16 (metadata, offs);

offs += 2;

EventStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

EventStruct[k].coded = ReadCodedIndex(metadata , offs , "TypeDefOrRef");

offs += GetCodedIndexSize("TypeDefOrRef");

}

}

//PropertyMap

old = tableoffset;

tablehasrows  = tablepresent(21);

offs = tableoffset;

if ( debug )

Console.WriteLine("PropertyMap Table Offset {0} Size {1}" , offs, sizes[21]);

tableoffset = old;

if ( tablehasrows )

{

PropertyMapStruct = new PropertyMapTable[rows[21] + 1];

for ( int k = 1 ; k <= rows[21] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

PropertyMapStruct[k].parent = ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

PropertyMapStruct[k].propertylist = ReadTableIndex(metadata, offs , "Properties");

offs += GetTableSize("Properties");

}

}

//Property

old = tableoffset;

tablehasrows  = tablepresent(23);

offs = tableoffset;

if ( debug )

Console.WriteLine("Property Table Offset {0} Size {1}" , offs, sizes[23]);

tableoffset = old;

if ( tablehasrows )

{

PropertyStruct = new PropertyTable[rows[23] + 1];

for ( int k = 1 ; k <= rows[23] ; k++)

{

//if ( debug )

//Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

PropertyStruct[k].flags = BitConverter.ToInt16 (metadata, offs);

offs += 2;

PropertyStruct[k].name= ReadStringIndex(metadata, offs);

offs += offsetstring;

PropertyStruct[k].type = ReadBlobIndex(metadata, offs);

offs += offsetblob;

//Console.WriteLine("...{0} {1} {2} {3}" , k , GetString(PropertyStruct[k].name) , PropertyStruct[k].flags , PropertyStruct[k].type);

}

}

//MethodSemantics

old = tableoffset ;

tablehasrows  = tablepresent(24);

offs = tableoffset;

if ( debug )

Console.WriteLine("MethodSemantics Table Offset {0} Size {1}" , offs, sizes[24]);

tableoffset = old;

if ( tablehasrows )

{

MethodSemanticsStruct = new MethodSemanticsTable[rows[24] + 1];

for ( int k = 1 ; k <= rows[24] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

MethodSemanticsStruct[k].methodsemanticsattributes  = BitConverter.ToInt16 (metadata, offs);

offs += 2;

MethodSemanticsStruct[k].methodindex = ReadTableIndex(metadata, offs , "Method");

offs += GetTableSize("Method");

MethodSemanticsStruct[k].association = ReadCodedIndex(metadata , offs , "HasSemantics");

offs += GetCodedIndexSize("HasSemantics");

}

}

//MethodImpl

old = tableoffset;

tablehasrows  = tablepresent(25);

offs = tableoffset;

if ( debug )

Console.WriteLine("MethodImpl Table Offset {0} {1}" , offs, sizes[25]);

tableoffset = old;

if ( tablehasrows )

{

MethodImpStruct = new MethodImpTable[rows[25] + 1];

for ( int k = 1 ; k <= rows[25] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

MethodImpStruct[k].classindex = ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

MethodImpStruct[k].codedbody = ReadCodedIndex(metadata , offs , "MethodDefOrRef");

offs += GetCodedIndexSize("MethodDefOrRef");

MethodImpStruct[k].codeddef = ReadCodedIndex(metadata , offs , "MethodDefOrRef");

offs += GetCodedIndexSize("MethodDefOrRef");

}

}

//ModuleRef

old = tableoffset;

tablehasrows  = tablepresent(26);

offs = tableoffset;

if ( debug )

Console.WriteLine("ModuleRef Table Offset {0} Size {1}" , offs, sizes[26]);

tableoffset = old;

if ( tablehasrows )

{

ModuleRefStruct = new ModuleRefTable[rows[26] + 1];

for ( int k = 1 ; k <= rows[26] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ModuleRefStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

}

}

//TypeSpec

old = tableoffset;

tablehasrows  = tablepresent(27);

offs = tableoffset;

if ( debug )

Console.WriteLine("TypeSpec Table Offset {0} Size={1}" , offs , sizes[27]);

tableoffset = old;

if ( tablehasrows )

{

TypeSpecStruct = new TypeSpecTable[rows[27] + 1];

for ( int k = 1 ; k <= rows[27] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

TypeSpecStruct[k].signature = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//ImplMap

old = tableoffset;

tablehasrows  = tablepresent(28);

offs = tableoffset;

if ( debug )

Console.WriteLine("ImplMap Table Offset offs={0} Size {1}" , offs , sizes[28]);

tableoffset = old;

if ( tablehasrows )

{

ImplMapStruct = new ImplMapTable[rows[28] + 1];

for ( int k = 1 ; k <= rows[28] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ImplMapStruct[k].attr = BitConverter.ToInt16 (metadata, offs);

offs += 2;

ImplMapStruct[k].cindex = ReadCodedIndex(metadata , offs , "MemberForwarded");

offs += GetCodedIndexSize("MemberForwarded");

ImplMapStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

ImplMapStruct[k].scope = ReadTableIndex(metadata, offs , "ModuleRef");

offs += GetTableSize("ModuleRef");

}

}

//FieldRVA

old = tableoffset;

tablehasrows  = tablepresent(29);

offs = tableoffset;

if ( debug )

Console.WriteLine("FieldRVA Table Offset {0} Size {1}" , offs, sizes[29]);

tableoffset = old;

if ( tablehasrows )

{

FieldRVAStruct = new FieldRVATable[rows[29] + 1];

for ( int k = 1 ; k <= rows[29] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FieldRVAStruct[k].rva = BitConverter.ToInt32 (metadata, offs);

offs += 4;

FieldRVAStruct[k].fieldi = ReadTableIndex(metadata, offs , "Field");

offs += GetTableSize("Field");

}

}

//Assembley

old = tableoffset;

tablehasrows  = tablepresent(32);

offs = tableoffset;

if ( debug )

Console.WriteLine("Assembly Table Offset {0} Size {1}" , offs, sizes[32]);

tableoffset = old;

AssemblyStruct = new AssemblyTable[rows[32] + 1];

if ( tablehasrows )

{

for ( int k = 1 ; k <= rows[32] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

AssemblyStruct[k].HashAlgId = BitConverter.ToInt32 (metadata, offs);

offs += 4;

AssemblyStruct[k].major = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyStruct[k].minor = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyStruct[k].build= BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyStruct[k].revision = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

AssemblyStruct[k].publickey = ReadBlobIndex(metadata, offs);

offs += offsetblob;

AssemblyStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

AssemblyStruct[k].culture = ReadStringIndex(metadata, offs);

offs += offsetstring;

}

}

//AssemblyRef

old = tableoffset;

tablehasrows  = tablepresent(35);

offs = tableoffset;

if ( debug )

Console.WriteLine("AssembleyRef Table Offset {0} Size {1}" , offs, sizes[35]);

tableoffset = old;

if ( tablehasrows )

{

AssemblyRefStruct = new AssemblyRefTable[rows[35] + 1];

for ( int k = 1 ; k <= rows[35]; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

AssemblyRefStruct[k].major = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyRefStruct[k].minor = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyRefStruct[k].build= BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyRefStruct[k].revision = BitConverter.ToInt16 (metadata, offs);

offs += 2;

AssemblyRefStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

AssemblyRefStruct[k].publickey = ReadBlobIndex(metadata, offs);

offs += offsetblob;

AssemblyRefStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

AssemblyRefStruct[k].culture = ReadStringIndex(metadata, offs);

offs += offsetstring;

AssemblyRefStruct[k].hashvalue = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//File

old = tableoffset;

tablehasrows  = tablepresent(38);

offs = tableoffset;

if ( debug )

Console.WriteLine("File Table Offset {0} Size {1}" , offs, sizes[38]);

tableoffset = old;

if ( tablehasrows )

{

FileStruct = new FileTable[rows[38] + 1];

for ( int k = 1 ; k <= rows[38] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

FileStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

FileStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

FileStruct[k].index = ReadBlobIndex(metadata, offs);

offs += offsetblob;

}

}

//ExportedType

old = tableoffset;

tablehasrows  = tablepresent(39);

offs = tableoffset;

if ( debug )

Console.WriteLine("ExportedType Table Offset {0} Size {1}" , offs, sizes[39]);

tableoffset = old;

if ( tablehasrows )

{

ExportedTypeStruct = new ExportedTypeTable[rows[39] + 1];

for ( int k = 1 ; k <= rows[39] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X")  );

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} " , metadata[offs+8].ToString("X") , metadata[offs+9].ToString("X") , metadata[offs+10].ToString("X") ,metadata[offs+11].ToString("X") ,metadata[offs+12].ToString("X") ,metadata[offs+13].ToString("X") , metadata[offs+14].ToString("X") );

ExportedTypeStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

ExportedTypeStruct[k].typedefindex = BitConverter.ToInt32 (metadata, offs);

offs += 4;

ExportedTypeStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

ExportedTypeStruct[k].nspace = ReadStringIndex(metadata, offs);

offs += offsetstring;

ExportedTypeStruct[k].coded = ReadCodedIndex ( metadata, offs , "Implementation");

offs += GetCodedIndexSize("Implementation");

//Console.WriteLine("......{0} {1}" , ExportedTypeStruct[k].coded , ExportedTypeStruct[k].name );

}

}

//ManifestResource

old = tableoffset;

tablehasrows  = tablepresent(40);

offs = tableoffset;

if ( debug )

Console.WriteLine("ManifestResource Table Offset {0} Size {1}" , offs, sizes[40]);

tableoffset = old;

if ( tablehasrows )

{

ManifestResourceStruct = new ManifestResourceTable[rows[40] + 1];

for ( int k = 1 ; k <= rows[40] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

ManifestResourceStruct[k].offset = BitConverter.ToInt32 (metadata, offs);

offs += 4;

ManifestResourceStruct[k].flags = BitConverter.ToInt32 (metadata, offs);

offs += 4;

ManifestResourceStruct[k].name = ReadStringIndex(metadata, offs);

offs += offsetstring;

ManifestResourceStruct[k].coded = ReadCodedIndex(metadata , offs , "Implementation");

offs += GetCodedIndexSize("");

}

}

//Nested Classes

old = tableoffset;

tablehasrows  = tablepresent(41);

offs = tableoffset;

if ( debug )

Console.WriteLine("Nested Classes Offset {0} Size {1}" , offs, sizes[41]);

tableoffset = old;

if ( tablehasrows )

{

NestedClassStruct = new NestedClassTable[rows[41] + 1];

for ( int k = 1 ; k <= rows[41] ; k++)

{

if ( debug )

Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7}" , metadata[offs].ToString("X") , metadata[offs+1].ToString("X") , metadata[offs+2].ToString("X") ,metadata[offs+3].ToString("X") ,metadata[offs+4].ToString("X") ,metadata[offs+5].ToString("X") , metadata[offs+6].ToString("X") , metadata[offs+7].ToString("X") , metadata[offs+8].ToString("X")  );

NestedClassStruct[k].nestedclass= ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

NestedClassStruct[k].enclosingclass= ReadTableIndex(metadata, offs , "TypeDef");

offs += GetTableSize("TypeDef");

}

}

int ii ;

for ( ii = 1 ; ii <= TypeDefStruct.Length - 1 ; ii++)

{

//Console.WriteLine("........{0} {1} {2}" , TypeDefStruct.Length , IsTypeNested(ii) , ii);

if ( ! IsTypeNested(ii) )

lasttypedisplayed = ii;

}

}

public bool tablepresent(byte tableindex)

{

int tablebit = (int)(valid >> tableindex) & 1;

for ( int j = 0 ; j < tableindex ; j++)

{

int o = sizes[j] * rows[j];

tableoffset = tableoffset + o;

}

if ( tablebit == 1)

return true;

else

return false;

}

public void ReadandDisplayExportAddressTableJumps()

{

Console.WriteLine("// Export Address Table Jumps:");

if ( exportaddressrva == 0)

{

Console.WriteLine("// No data.");

Console.WriteLine();

}

}

public void CreateFieldSignature (byte [] blobarray , int row)

{

//Console.WriteLine("Field Length={0} method row={1} name={2}" , blobarray.Length , row.ToString("X") , GetString(FieldStruct[row].name));

int aa = -1;

if ( row == aa )

{

for ( int l = 0 ; l < blobarray.Length ; l++)

Console.Write("{0} " , blobarray[l].ToString("X"));

Console.WriteLine();

Console.WriteLine("Length of array is {0}" , blobarray.Length);

}

int howmanybytes , uncompressedbyte;

int index = 0;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + howmanybytes;

string returnstring = GetElementType(index , blobarray ,  out howmanybytes , 0 , "");

returnstring = returnstring.Replace("^",",");

if ( row == aa )

Console.WriteLine("......returnstring={0}" , returnstring);

//if ( returnstring != "")

//returnstring = returnstring.Remove(returnstring.Length-1, 1);

fieldparamarray[row] = returnstring;

fieldflagsarray[row] = GetFieldAttributes(row);

}

public void CreateLocalVarSignature (byte [] blobarray , int row)

{

//Console.WriteLine("Local Variable Array Length={0} method row={1} " , blobarray.Length , row );

int aa = -1;

if ( blobarray.Length == 0)

return;

if ( row == aa)

{

for ( int l = 0 ; l < blobarray.Length ; l++)

Console.Write("{0} " , blobarray[l].ToString("X"));

Console.WriteLine();

Console.WriteLine("Length of array is {0}" , blobarray.Length);

}

int index = 0;

standalonesigarray[row] = "";

if ( blobarray[index] != 0x07)

return;

index++;

int howmanybytes,uncompressedbyte ;

howmanybytes = CorSigUncompressData(blobarray , index , out uncompressedbyte);

index = index + howmanybytes;

string returnstring = "";

for ( int l = 1 ; l <= uncompressedbyte ; l++)

{

string typestring = GetElementType(index , blobarray ,  out howmanybytes , 0 , "");

typestring = typestring.Replace("^",",");

if ( row == aa)

Console.WriteLine("......l={0} typestring={1} index={2} howmanybytes={3} value={4}" , l , typestring , index , howmanybytes , blobarray[index].ToString("X"));

//if ( typestring != "")

//typestring = typestring.Remove(typestring.Length-1 , 1);

int variableVindex = l - 1 ;

returnstring = returnstring + typestring +  " V_" + variableVindex.ToString() ;

if ( l != uncompressedbyte)

returnstring = returnstring + ",\r\n" + CreateSpaces(spacesforrest + 2 + spacesfornested) + CreateSpaces(9);

index = index + howmanybytes;

}

standalonesigarray[row] = returnstring;

}

public string GetPointerToken(int index , byte [] blobarray , out int howmanybytes)

{

string returnstring = "";

int howmanybytes2;

returnstring = GetElementType(index+1 , blobarray , out howmanybytes2 , 0 , "") + "*";

howmanybytes = howmanybytes2 + 1;

return returnstring;

}

public string GetByrefToken (int index , byte [] blobarray , out int howmanybytes)

{

string returnstring = "";

int howmanybytes2;

returnstring = GetElementType(index+1 , blobarray , out howmanybytes2 , 0 , "") + "&";

howmanybytes = howmanybytes2 + 1;

return returnstring;

}

public string GetSzArray(int index , byte [] blobarray , out int howmanybytes)

{

string returnstring = "";

int i = 1;

returnstring = "[]";

while ( true )

{

byte next = blobarray[index+i];

if ( next != 0x1d )

break;

returnstring = returnstring + "[]";

i = i +1 ;

}

int howmanybytes2;

returnstring = GetElementType(index + i , blobarray , out howmanybytes2,0 , "") + returnstring;

howmanybytes = i + howmanybytes2;

return returnstring;

}

public string GetTokenType ( byte [] blobarray , int index , out int howmanybytes)

{

string returnstring = "";

int uncompressedbyte;

int howmanybytes1 = 0;

howmanybytes1 = howmanybytes1  + CorSigUncompressData(blobarray , index + 1 , out uncompressedbyte);

string dummy1  = DecodeToken(uncompressedbyte , blobarray[index]);

if ( blobarray[index] == 0x12)

returnstring = "class " + dummy1; 

else if ( blobarray[index] == 0x11)

returnstring = "valuetype " + dummy1;

else

returnstring = dummy1;

howmanybytes = howmanybytes1;

return returnstring;

}

public string GetPointerType ( byte [] blobarray , int index , out int howmanybytes)

{

string returnstring = "";

returnstring = GetElementType(index , blobarray , out howmanybytes,0 , "") + "*" ;

return returnstring;

}

public void DisplayOverrideMethod (int methodrow)

{

if ( MethodImpStruct == null  )

return;

for ( int ii = 1 ; ii < MethodImpStruct.Length ; ii++)

{

string codeddeftablename = GetMethodDefTable(MethodImpStruct[ii].codeddef );

int codeddefindex = GetMethodDefValue(MethodImpStruct[ii].codeddef );

string codedbodytablename = GetMethodDefTable(MethodImpStruct[ii].codedbody);

int codedbodyindex = GetMethodDefValue(MethodImpStruct[ii].codedbody );

int typeindex = GetTypeForMethod(codedbodyindex);

if ( typeindex  == MethodImpStruct[ii].classindex && codedbodytablename  == "MethodDef" && codedbodyindex == methodrow)

{

if ( codeddeftablename == "MethodRef" )

{

Console.Write(CreateSpaces(spacesforrest+2 + spacesfornested));

Console.Write(".override ");

int typerefindex = GetTypeRefFromMethodRef(codeddefindex);

Console.WriteLine("{0}::{1} /*01{2}::0A{3}*/ " , typerefnames[typerefindex], NameReserved(GetString(MemberRefStruct[codeddefindex].name)) , typerefindex .ToString("X6") , codeddefindex.ToString("X6"));

}

if ( codeddeftablename  == "MethodDef" )

{

Console.Write(CreateSpaces(spacesforrest+2 + spacesfornested));

int typedefindex = GetTypeForMethod(codeddefindex);

Console.Write(".override {0}::{1} " , typedefnames[typedefindex],NameReserved(GetString(MethodStruct[codeddefindex].name)) );

Console.WriteLine("/*02{0}::06{1}*/ " , typedefindex.ToString("X6") , codeddefindex.ToString("X6"));

}

}

}

}

public bool IsGlobalMethod (int methodrow)

{

int start , startofnext=0;

//Console.WriteLine("........methodrow={0} TypeDefStruct.Length={1}" , methodrow , TypeDefStruct.Length);

if ( TypeDefStruct.Length == 2)

return true;

start =  TypeDefStruct[1].mindex ;

if ( TypeDefStruct.Length == 1 )

{

startofnext= MethodStruct.Length;

}

else

startofnext = TypeDefStruct[2].mindex;

if ( methodrow >= start && methodrow < startofnext )

return true;

else

return false;

}

public string GetMethodAttribute1 (int methodflags)

{

string returnstring = "";

if ( (methodflags & 0x0003) == 0x0003)

returnstring = returnstring + "runtime ";

else

if ( (methodflags & 0x0001) == 0x0001)

returnstring = returnstring + "native ";

else

if ( (methodflags & 0x0002) == 0x0002)

returnstring = returnstring + "optil ";

 

else

returnstring = returnstring + "cil ";

if ( (methodflags & 0x0004) == 0x0004)

returnstring = returnstring + "unmanaged";

else

returnstring = returnstring + "managed";

if ( (methodflags & 0x0080) == 0x0080)

returnstring = returnstring + " preservesig";

if ( (methodflags & 0x0010) == 0x0010)

returnstring = returnstring + " forwardref";

if ( (methodflags & 0x01000) == 0x1000)

returnstring = returnstring + " internalcall";

if ( (methodflags & 0x0020) == 0x0020)

returnstring = returnstring + " synchronized";

if ( (methodflags & 0x0008) == 0x0008)

returnstring = returnstring + " noinlining";

return returnstring;

}

int [] sizes;

public ExceptionTable [] ExceptionStruct;

int codesize ;

FileStream mfilestream ;

BinaryReader mbinaryreader ;

int subsystem;

int stackreserve ;

int stackcommit;

int datad;

int entrypoint;

int ImageBase;

int sectiona;

int filea;

int [] methodvtentryarray ;

string [] vtfixuparray;

string [] datavtfixuparray;

OpCode [] OpCodesArray; 

OpCode [] OpCodesArray1; 

int [] datadirectoryrva;

int [] datadirectorysize;

long sectionoffset;

short sections ;

int metadatarva;

int entrypointtoken;

int [] SVirtualAddress ;

int [] SSizeOfRawData;

int [] SPointerToRawData ;

string [] paramnames;

string [] typerefnames; 

string [] typedefnames; 

long startofmetadata;

string [] streamnames;

int tableoffset ;

int [] rows;

long valid ;

byte [] metadata;

byte [] strings;

byte [] us;

byte [] guid;

byte [] blob;

int [] offset;

int [] ssize ;

byte [][] names;

int offsetstring = 2;

int offsetblob = 2;

int offsetguid = 2;

//int cb;

int count;

int vtablerva;

int vtablesize;

int exportaddressrva;

int exportaddresssize;

int corflags;

string [] tablenames = new String[]{"Module" , "TypeRef" ,"TypeDef" ,"FieldPtr","Field", "MethodPtr","Method","ParamPtr" , "Param", "InterfaceImpl", "MemberRef", "Constant", "CustomAttribute", "FieldMarshal", "DeclSecurity", "ClassLayout", "FieldLayout", "StandAloneSig" , "EventMap","EventPtr", "Event", "PropertyMap", "PropertyPtr", "Properties","MethodSemantics","MethodImpl","ModuleRef","TypeSpec","ImplMap","FieldRVA","ENCLog","ENCMap","Assembly","AssemblyProcessor","AssemblyOS","AssemblyRef","AssemblyRefProcessor","AssemblyRefOS","File","ExportedType","ManifestResource","NestedClass","TypeTyPar","MethodTyPar"};

string [] standalonesigarray;

string [] propertytypearray;

string [] propertyreturnarray ;

string [] propertyparmarray;

string [] methoddefparamarray ;

string [] methoddefparamarray1 ;

string [] methoddefreturnarray ;

int [] methoddefparamcount;

string [] methoddeftypearray ;

string [] methodrefparamarray1 ;

string [] methodrefreturnarray ;

string [] methodreftypearray;

string [] fieldflagsarray ;

string [] fieldparamarray ;

public AssemblyTable [] AssemblyStruct;

public AssemblyRefTable [] AssemblyRefStruct ;

public CustomAttributeTable [] CustomAttributeStruct;

public ModuleTable[] ModuleStruct;

public TypeDefTable [] TypeDefStruct;

public TypeRefTable [] TypeRefStruct;

public InterfaceImplTable [] InterfaceImplStruct;

public FieldPtrTable [] FieldPtrStruct;

public MethodPtrTable [] MethodPtrStruct;

public MethodTable [] MethodStruct;

public StandAloneSigTable [] StandAloneSigStruct;

public MemberRefTable [] MemberRefStruct;

public TypeSpecTable [] TypeSpecStruct;

public ParamTable [] ParamStruct;

public FieldTable [] FieldStruct;

public FieldMarshalTable [] FieldMarshalStruct;

public FieldRVATable [] FieldRVAStruct;

public FieldLayoutTable [] FieldLayoutStruct;

public ConstantsTable [] ConstantsStruct;

public PropertyMapTable [] PropertyMapStruct;

public PropertyTable [] PropertyStruct;

public MethodSemanticsTable [] MethodSemanticsStruct;

public EventTable [] EventStruct;

public EventMapTable [] EventMapStruct;

public FileTable [] FileStruct;

public ModuleRefTable [] ModuleRefStruct;

public ManifestResourceTable [] ManifestResourceStruct;

public ClassLayoutTable [] ClassLayoutStruct;

public MethodImpTable [] MethodImpStruct;

public NestedClassTable [] NestedClassStruct;

public ExportedTypeTable [] ExportedTypeStruct;

public DeclSecurityTable [] DeclSecurityStruct;

public ImplMapTable [] ImplMapStruct;

string methodpinvokestring ;

int lasttypedisplayed;

bool debug = false;

bool tinyformat;

int first12;

int spacesfortry;

bool placedend = false;

bool notprototype = false;

bool writenamespace;

string filename;

int spacesforrest = 2;

int spacefornamespace ;

int spacesfornested;

string methodaccessattribute ;

public long ConvertRVA(long rva)

{

int i;

for ( i = 0 ; i < sections ; i++)

{

if ( rva >= SVirtualAddress[i]  && ( rva <  SVirtualAddress[i] + SSizeOfRawData[i] ))

break ;

}

return SPointerToRawData[i] + ( rva - SVirtualAddress[i] );

}

public string CreateSpaces (int howmanyspaces)

{

string returnstring = "";

for ( int j = 1 ; j <= howmanyspaces ; j++)

returnstring = returnstring + " ";

return returnstring ;

}

public string GetMemberRefParentCodedIndexTable(int memberrefparentcodedindex)

{

string returnstring = "";

memberrefparentcodedindex = memberrefparentcodedindex & 0x07;

if ( memberrefparentcodedindex == 0 )

returnstring = "TypeDef";

if ( memberrefparentcodedindex == 1 )

returnstring = "TypeRef";

if ( memberrefparentcodedindex == 2 )

returnstring = "ModuleRef";

if ( memberrefparentcodedindex == 3 )

returnstring = "MethodDef";

if ( memberrefparentcodedindex== 4 )

returnstring = "TypeSpec";

return returnstring;

}

public string GetString (int starting)

{

int ending = starting;

//Console.WriteLine(".........starting={0} strings.Length={1}" , starting , strings.Length);

if ( starting < 0)

return "";

if ( starting >= strings.Length )

return "";

while (strings[ending] != 0 )

{

ending++;

}

System.Text.Encoding e = System.Text.Encoding.UTF8;

string  returnstring = e.GetString(strings, starting , ending - starting  );

if ( returnstring.Length == 0)

return "";

else

return returnstring;

}

public int ReadTableIndex(byte [] metadataarray , int arrayoffset , string tablename)

{

int returnindex = 0;

int tablesize = GetTableSize(tablename);

if ( tablesize == 2)

returnindex = BitConverter.ToUInt16 (metadataarray , arrayoffset );

if ( tablesize == 4)

returnindex = (int)BitConverter.ToUInt32 (metadataarray , arrayoffset );

return returnindex;

}

public int ReadStringIndex(byte [] metadataarray , int arrayoffset)

{

int returnindex = 0;

if ( offsetstring == 2)

returnindex = BitConverter.ToUInt16 (metadataarray , arrayoffset );

if ( offsetstring == 4)

returnindex = (int)BitConverter.ToUInt32 (metadataarray , arrayoffset );

return returnindex;

}

public int ReadBlobIndex(byte [] metadataarray , int arrayoffset)

{

int returnindex = 0;

if ( offsetblob == 2)

returnindex = BitConverter.ToUInt16 (metadataarray , arrayoffset );

if ( offsetblob == 4)

returnindex = (int)BitConverter.ToUInt32 (metadataarray , arrayoffset );

return returnindex;

}

public int ReadGuidIndex(byte [] metadataarray , int arrayoffset)

{

int returnindex = 0;

if ( offsetguid == 2)

returnindex = BitConverter.ToUInt16 (metadataarray , arrayoffset );

if ( offsetguid == 4)

returnindex = (int)BitConverter.ToUInt32 (metadataarray , arrayoffset );

return returnindex;

}

public void DisplayGuid (int guidindex)

{

Console.Write("{");

Console.Write("{0}{1}{2}{3}", guid[guidindex+2].ToString("X2") , guid[guidindex+1].ToString("X2") , guid[guidindex].ToString("X2") , guid[guidindex-1].ToString("X2"));

Console.Write("-{0}{1}-",guid[guidindex+4].ToString("X2") , guid[guidindex+3].ToString("X2"));

Console.Write("{0}{1}-",guid[guidindex+6].ToString("X2") , guid[guidindex+5].ToString("X2"));

Console.Write("{0}{1}-",guid[guidindex+7].ToString("X2") , guid[guidindex+8].ToString("X2"));

Console.Write("{0}{1}{2}{3}{4}{5}",guid[guidindex+9].ToString("X2"),guid[guidindex+10].ToString("X2"),guid[guidindex+11].ToString("X2"),guid[guidindex+12].ToString("X2"),guid[guidindex+13].ToString("X2"),guid[guidindex+14].ToString("X2"));

Console.Write("}");

}

public void DisplayModuleAndMore()

{

Console.WriteLine(".module {0}" , NameReserved(GetString(ModuleStruct[1].Name)));

Console.Write("// MVID: ");

DisplayGuid(ModuleStruct[1].Mvid);

Console.WriteLine();

DisplayCustomAttribute("Module"  , 1 , 0);

Console.WriteLine(".imagebase 0x{0}" , ImageBase.ToString("x8"));

Console.WriteLine(".subsystem 0x{0}" , subsystem.ToString("X8"));

Console.WriteLine(".file alignment {0}" , filea);

Console.WriteLine(".corflags 0x{0}" , corflags.ToString("x8"));

Console.WriteLine("// Image base: 0x03000000");

}

public string GetTypeDefOrRefTable (int codedvalue)

{

string returnstring = "";

short tag = (short)(codedvalue & (short)0x03);

if ( tag  == 0)

returnstring = returnstring + "TypeDef";

if ( tag  == 1)

returnstring = returnstring + "TypeRef";

if ( tag  == 2)

returnstring = returnstring + "TypeSpec";

return returnstring;

}

public int GetTypeDefOrRefValue(int codedvalue)

{

return codedvalue >> 2;

}

public string GetFieldRVA (int fieldrow)

{

string returnstring = "";

int ii;

if ( FieldRVAStruct == null )

return "";

for ( ii = 1 ; ii < FieldRVAStruct.Length ; ii++)

{

int jj = FieldRVAStruct[ii].fieldi;

if ( jj == fieldrow  )

break;

}

if ( ii != FieldRVAStruct.Length )

{

int rva= FieldRVAStruct[ii].rva ;

returnstring = " D_" + rva.ToString("X8") ;

}

return returnstring;

}

public string GetMarshalTableValue (int fieldmarshalrow)

{

int ii;

for ( ii = 1 ; ii < FieldMarshalStruct.Length ; ii++)

{

int fieldmarshalrowcoded = FieldMarshalStruct[ii].coded >> 1;

if ( fieldmarshalrow == fieldmarshalrowcoded)

break;

}

int index = FieldMarshalStruct[ii].index;

int count = blob[index];

string returnstring = GetMarshallType(blob[index+1] , count , 0);

return returnstring;

}

public string GetType (int typebyte)

{

if ( typebyte == 0x01)

return "void";

if ( typebyte == 0x02)

return "bool";

if ( typebyte == 0x03)

return "char";

if ( typebyte == 0x04)

return "int8";

if ( typebyte == 0x05)

return "unsigned int8";

if ( typebyte == 0x06)

return "int16";

if ( typebyte == 0x07)

return "unsigned int16";

if ( typebyte == 0x08)

return "int32";

if ( typebyte == 0x09)

return "unsigned int32";

if ( typebyte == 0x0a)

return "int64";

if ( typebyte == 0x0b)

return "unsigned int64";

if ( typebyte == 0x0c)

return "float32";

if ( typebyte == 0x0d)

return "float64";

if ( typebyte == 0x0e)

return "string";

return "unknown";

}

public void DisplayGlobalFields()

{

int start , startofnext=0;

if ( TypeDefStruct == null || FieldStruct == null)

return;

start =  TypeDefStruct[1].findex ;

if ( TypeDefStruct.Length == 2 )

startofnext= FieldStruct.Length;

else

startofnext = TypeDefStruct[2].findex ;

if ( start != startofnext )

{

Console.WriteLine("//Global fields");

Console.WriteLine("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

DisplayAllFields(1);

}

}

public void DisplayGlobalMethods()

{

int start , startofnext=0;

start =  TypeDefStruct[1].mindex ;

if ( TypeDefStruct == null || MethodStruct == null)

return;

 

if ( TypeDefStruct.Length == 2 )

startofnext= MethodStruct.Length;

else

startofnext = TypeDefStruct[2].mindex ;

if ( start != startofnext )

{

Console.WriteLine("//Global methods");

Console.WriteLine("//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

spacesforrest = 0;

DisplayAllMethods(1);

spacesforrest = 2;

 

}

}

public void DisplayNestedTypes (int typedefindex)

{

if (NestedClassStruct == null)

return ;

for ( int ii = 1 ; ii < NestedClassStruct.Length ; ii++)

{

if (NestedClassStruct[ii].enclosingclass == typedefindex)

{

spacesfornested += 2;

DisplayOneType(NestedClassStruct[ii].nestedclass  );

spacesfornested -= 2;

}

}

}

public void DisplayNestedTypesPrototypes (int typedefindex)

{

if (NestedClassStruct == null)

return ;

for ( int ii = 1 ; ii < NestedClassStruct.Length ; ii++)

{

if (NestedClassStruct[ii].enclosingclass == typedefindex)

{

spacesfornested += 2;

DisplayOneTypePrototype(NestedClassStruct[ii].nestedclass  );

spacesfornested -= 2;

}

}

}

public string GetMethodSignatureBytes (int methodrow)

{

string returnstring =  "\r\n" + CreateSpaces(spacesforrest+ spacesfornested) + "// SIG: ";

int uncompressedbyte;

int signatureindex = MethodStruct[methodrow].signature;

int howmanybytes;

howmanybytes = CorSigUncompressData(blob , signatureindex, out uncompressedbyte);

int count = uncompressedbyte;

if ( howmanybytes == 2)

count++;

for (int j = howmanybytes ; j <= count ; j++)

{

returnstring = returnstring + blob[signatureindex + j ].ToString("X2") ;

if ( j != count )

returnstring = returnstring + " ";

}

return returnstring;

}

public int GetHasSemanticsValue(int asscoiationbyte)

{

return asscoiationbyte >> 1;

}

public string GetFileAttributes(int fileflags)

{

string returnstring = "";

if ( fileflags == 0x00)

returnstring= "";

if ( fileflags == 0x01)

returnstring= "nometadata ";

return returnstring;

}

public void DisplayModuleRefs()

{

if ( ModuleRefStruct == null  )

return;

for ( int ii = 1 ; ii < ModuleRefStruct.Length ; ii++)

{

string dummy = NameReserved(GetString(ModuleRefStruct[ii].name));

if ( dummy == "..\\unmanaged\\i386\\windowsidentity.dll")

Console.WriteLine(".module extern {0} /*1A{1}*/" ,  "'..\\\\unmanaged\\\\i386\\\\windowsidentity.dll'" , ii.ToString("X6"));

else

Console.WriteLine(".module extern {0} /*1A{1}*/" ,  dummy , ii.ToString("X6"));

}

}

public int GetManifestResourceValue(int manifiestvalue)

{

return manifiestvalue>> 2;

}

public string GetManifestResourceTable(int manifiestvalue)

{

string returnstring = "";

short tag = (short)(manifiestvalue & (short)0x03);

if ( tag  == 0)

returnstring = returnstring + "File";

if ( tag  == 1)

returnstring = returnstring + "AssemblyRef";

if ( tag  == 2)

returnstring = returnstring + "ExportedType";

return returnstring;

}

public string GetManifestResourceAttributes(int manifiestvalue)

{

string returnstring="";

if ( (manifiestvalue & 0x001) == 0x001)

returnstring = returnstring + "public ";

if ( (manifiestvalue & 0x002) == 0x002)

returnstring = returnstring + "private ";

return returnstring;

}

public void DisplayResources()

{

if ( ManifestResourceStruct == null)

return;

for ( int ii = 1 ; ii < ManifestResourceStruct.Length ; ii++)

{

string flags = GetManifestResourceAttributes(ManifestResourceStruct[ii].flags);

Console.WriteLine(".mresource /*28{0}*/ {1}{2}" ,  ii.ToString("X6") , flags, NameReserved(GetString(ManifestResourceStruct[ii].name)) );

Console.WriteLine("{");

string table = GetManifestResourceTable(ManifestResourceStruct[ii].coded);

int index = GetManifestResourceValue(ManifestResourceStruct[ii].coded);

if ( table == "AssemblyRef")

Console.WriteLine("  .assembly extern {0} /*23{1}*/ " , NameReserved(GetString(AssemblyRefStruct[index].name)) , index.ToString("X6"));

else if ( table == "File" && index > 0)

Console.WriteLine("  .file {0}/*26{1}*/  at 0x{2}" , NameReserved(GetString(FileStruct[index].name)) , index.ToString("X6") ,ManifestResourceStruct[ii].offset.ToString("X8") );

else

Console.WriteLine("  // WARNING: managed resource file {0} created",NameReserved(GetString(ManifestResourceStruct[ii].name) ) );

Console.WriteLine("}");

}

}

public int GetMethodDefValue(int implcoded)

{

return implcoded >> 1;

}

public string GetMethodDefTable(int implcoded)

{

string returnstring = "";

short tag = (short)(implcoded & (short)0x01);

if ( tag  == 0)

returnstring = returnstring + "MethodDef";

if ( tag  == 1)

returnstring = returnstring + "MethodRef";

return returnstring;

}

public string GetMemberRefTable(int memberrefcodedindex)

{

string returnstring = "";

short tag = (short)(memberrefcodedindex & (short)0x07);

if ( tag  == 0)

returnstring = returnstring + "NotUsed";

if ( tag  == 1)

returnstring = returnstring + "TypeRef";

if ( tag  == 2)

returnstring = returnstring + "ModuleRef";

if ( tag  == 3)

returnstring = returnstring + "MethodDef";

if ( tag  == 4)

returnstring = returnstring + "TypeSpec";

return returnstring;

}

public int GetMemberRefValue(int memberrefcodedindex)

{

return memberrefcodedindex >> 3;

}

public int GetTypeRefFromMethodRef(int methodrefrow)

{

int  memberrefcodedindex = 0;

memberrefcodedindex = MemberRefStruct[methodrefrow].clas;

string tablename = GetMemberRefTable(memberrefcodedindex);

int typerefindex = GetMemberRefValue(memberrefcodedindex);

return typerefindex;

}

public void DisplayClassExtern ()

{

if (ExportedTypeStruct == null)

return;

for ( int ii = 1 ; ii < ExportedTypeStruct.Length ; ii++)

{

string ss1 = GetTypeAttributeFlagsForClassExtern(ExportedTypeStruct[ii].flags );

string ss = GetString(ExportedTypeStruct[ii].nspace) ;

if ( ss.Length != 0)

ss = ss + ".";

ss = ss + NameReserved(GetString(ExportedTypeStruct[ii].name));

int table = ExportedTypeStruct[ii].coded & 0x03;

int index = ExportedTypeStruct[ii].coded >> 2;

if ( table == 1)

Console.WriteLine(".............");

if ( index != 0)

{

Console.Write(".class extern /*27{0}*/ {1}" , ii.ToString("X6") , ss1 );

Console.WriteLine(ss);

Console.WriteLine("{");

DisplayCustomAttribute("ExportedType" , ii , 2);

if ( table == 0)

{

Console.WriteLine("  .file {0}/*26{1}*/ " , NameReserved(GetString(FileStruct[index].name)) , index.ToString("X6"));

}

if ( table == 2)

{

Console.WriteLine("  .comtype '{0}' /*27{1}*/ " , NameReserved(GetString(ExportedTypeStruct[index].name)) , index.ToString("X6"));

}

if ( ExportedTypeStruct[ii].typedefindex != 0)

Console.WriteLine("  .class 0x{0}", ExportedTypeStruct[ii].typedefindex.ToString("X8"));

Console.WriteLine("}");

}

}

}

public int GetHasConstValue(int constcodedindex)

{

return constcodedindex >> 2;

}

public string GetHasConstTable(int constcodedindex)

{

string returnstring = "";

int tag = constcodedindex & 0x03;

if ( tag == 0)

returnstring = returnstring + "FieldDef";

if ( tag == 1)

returnstring = returnstring + "ParamDef";

if ( tag == 2)

returnstring = returnstring + "Property";

return returnstring;

}

public void DisplayData ()

{

if ( FieldRVAStruct == null)

return;

for ( int ii = 1 ; ii < FieldRVAStruct.Length ; ii++)

{

Console.WriteLine(".11data D_{0} = bytearray (" , FieldRVAStruct[ii].rva.ToString("X8"));

if ( ii == 1)

{

Console.Write("{0} vijay8319){1}// " , CreateSpaces(16) , CreateSpaces(37));

Console.Write("{");

Console.WriteLine("...");

}

else

Console.WriteLine("{0} 0C 00 00 00) " , CreateSpaces(16));

}

if (datavtfixuparray == null)

return;

for ( int ii = 0 ; ii < datavtfixuparray.Length ; ii++)

Console.WriteLine(datavtfixuparray[ii]);

}

public string NameReserved (string name)

{

if ( name == null)

return name;

if ( name.Length == 0)

return name;

if ( name.Length >= 2 && name[0] == 63 && name[1] == 63)

return name ;

if ( (byte)name[0] == 7  )

return "'\\a'";

if ( (byte)name[0] == 8  )

return "'\\b'";

if ( (byte)name[0] == 9)

return "'\\t'";

if ( (byte)name[0] == 10)

return "'\\n'";

if ( (byte)name[0] == 11  )

return "'\\v'";

if ( (byte)name[0] == 12  )

return "'\\f'";

if ( (byte)name[0] == 13  )

return "'\\r'";

if ( (byte)name[0] == 32  )

return "' '";

if ( name == "'")

return "'\\''";

if ( name == "\"")

return "'\\\"'";

if ( name.Length == 2 && (byte)name[1] == 7  )

return "'" + name[0] + "\\a'";

if ( name.Length == 2 && (byte)name[1] == 8  )

return "'" + name[0] + "\\b'";

if ( name.Length == 2 && (byte)name[1] == '\t'  )

return "'" + name[0] + "\\t'";

if ( name.Length == 2 && (byte)name[1] == '\n'  )

return "'" + name[0] + "\\n'";

if ( name.Length == 2 && (byte)name[1] == '\v'  )

return "'" + name[0] + "\\v'";

if ( name.Length == 2 && (byte)name[1] == '\f'  )

return "'" + name[0] + "\\f'";

if ( name.Length == 2 && (byte)name[1] == '\r'  )

return "'" + name[0] + "\\r'";

if ( name.Length == 2 && (byte)name[1] == '"'  )

return "'" + name[0] + "\\\"'";

if ( name.Length == 2 && (byte)name[1] == '\''  )

return "'" + name[0] + "\\\''";

if ( name.Length >= 1 && name[0] == '\'' && name[name.Length-1] == '\'' )

return name;

int i = 0;

while ( i < name.Length )

{

if ( (name[i] >= '0' &&  name[i] <= '9') && i == 0 )

return "'" + name + "'";

if ( name[i] >= 1 &&  name[i] <= 31  )

return "'" + name + "'";

if ( name[i] >= 127 || name[i] == '<'  || name[i] == '+'  || name[i] == '-'  || name[i] == ' ' || name[i] == '\''  )

{

int ind = name.IndexOf("'");

if ( ind != -1)

name = name.Insert(ind , "\\");

return "'" + name + "'";

}

i++;

}

string [] namesarray = {"value","blob","object","method" ,"init",".init","array","policy.2.0.myasm","policy.2.0.myasm.dll","add", "assembly", "serializable", "lcid" , "stream" , "filter" , "handler" , "record", "request", "opt", "clsid", "hresult", "cf", "custom" , "to", "ret", "import", "field", "sub", "any", "pop", "final", "rem" , "storage", "error", "nested", "il" , "instance", "date", "iunknown", "literal", "implements", "unused", "not" , "alignment", "unicode", "bstr", "auto", "retval", "variant", "or", "family", "arglist", "br", "wrapper", "demand", "fault", "call" ,  "algorithm", "native",  "fixed",  "string",  "char" ,  "decimal",  "float" ,  "int",  "void",  "pinned",  "div",  "true" ,  "false",  "default",  "abstract" , "^" , "`", "{", "|" , "}", "~" , "!" , "#" , "(", "%", "-"  , ")", ":" , ";", "=", ">", "assert", "synchronized", "runtime", "with",  "class", "newarr",  "ldobj", "ldloc", "stobj", "stloc", "starg", "refany",  "ldelema",  "ldarga",  "ldarg",  "initobj" ,  "box"  ,"demand" ,  "ldfld", "ldflda", "ldsfld", "ldsflda", "vector",  "in" , "out", "and", "int8", "xor" , "as", "at", "struct", "finally" , "interface" , ".CPmain", "enum", "vararg", "marshal", "policy.1.0.MathLibrary","policy.1.0.MathLibrary.dll","final", "System.Windows.Forms.Design.256_2.bmp" , "System.Windows.Forms.Design.256_1.bmp"};

for ( int ii = 0 ; ii < namesarray.Length ; ii++)

{

if ( name == namesarray[ii])

{

int ind = name.IndexOf("'");

if ( ind != -1)

name = name.Insert(ind , "\\");

return "'" + name + "'";

}

}

return name;

}

public string GetActionSecurity (int actionbyte)

{

string returnstring = "";

if ( actionbyte == 1)

returnstring = "request";

if ( actionbyte == 2)

returnstring = "demand";

if ( actionbyte == 3)

returnstring = "assert";

if ( actionbyte == 4)

returnstring = "deny";

if ( actionbyte == 5)

returnstring = "permitonly";

if ( actionbyte == 6)

returnstring = "linkcheck";

if ( actionbyte == 7)

returnstring = "inheritcheck";

if ( actionbyte == 8)

returnstring = "reqmin";

if ( actionbyte == 9)

returnstring = "reqopt";

if ( actionbyte == 10)

returnstring = "reqrefuse";

if ( actionbyte == 11)

returnstring = "prejitgrant";

if ( actionbyte == 12)

returnstring = "prejitdeny";

if ( actionbyte == 13)

returnstring = "noncasdemand";

if ( actionbyte == 14)

returnstring = "noncaslinkdemand";

if ( actionbyte == 15)

returnstring = "noncasinheritance";

return returnstring;

}

public int GetTypeForField (int fieldrow)

{

int ii = 0;

for ( ii = 1 ; ii < TypeDefStruct.Length - 1  ; ii++)

{

int start = TypeDefStruct[ii].findex;

int end = TypeDefStruct[ii+1].findex - 1;

if ( rows[3] >= 1)

{

start = FieldPtrStruct[start].index;

end  = FieldPtrStruct[end].index;

}

if ( fieldrow >= start && fieldrow <= end)

return ii;

}

return ii;

}

public int CorSigUncompressData( byte [] blobarray , int index , out int answer)

{

int howmanybytes = 0;

answer = 0;

if ( (blobarray[index] & 0x80) == 0x00)

{

howmanybytes = 1;

answer = blobarray[index];

}

else if ( (blobarray[index] & 0xC0) == 0x80)

{

howmanybytes = 2;

answer = ((blobarray[index] & 0x3f) <<8 ) |  blobarray[index+1];

}

else if ( (blobarray[index] & 0xE0) == 0xC0)

{

howmanybytes = 4;

answer = ((blobarray[index] & 0x1f) <<24 ) |  (blobarray[index+1] << 16) |  (blobarray[index+2] << 8) | blobarray[index+3];

}

return howmanybytes;

}

public int GetTableSize(string tablename)

{

int ii;

for ( ii = 0 ; ii < tablenames.Length ; ii++)

{

if ( tablename == tablenames[ii] )

break;

}

if ( rows[ii] >= 65535)

return 4;

else

return 2;

}

public bool HasCustomAttribute ( string tablename , int index)

{

if ( CustomAttributeStruct == null)

return false;

for ( int ii = 1 ; ii < CustomAttributeStruct.Length ; ii++)

{

string parentcodedtablename= GetHasCustomAttributeTable(CustomAttributeStruct[ii].parent) ;

int parentcodedindex= GetHasCustomAttributeValue(CustomAttributeStruct[ii].parent);

//Console.WriteLine(".......{0} {1} index={2}",parentcodedtablename , parentcodedindex , index);

if ( parentcodedtablename == tablename  && parentcodedindex == index)

return true;

}

return false;

}

public string GetTypeAttributeFlagsForClassExtern(int typeattributeflags )

{

typeattributeflags = typeattributeflags & 0x07;

string visibiltymaskstring="";

if ( typeattributeflags == 1)

visibiltymaskstring = "public ";

if ( typeattributeflags == 2)

visibiltymaskstring = "nested public ";

return visibiltymaskstring;

}

public string GetParamAttrforParamCalling (int paramindex)

{

string returnstring = "";

if (ParamStruct == null  )

return "";

if (paramindex >= ParamStruct.Length )

return "";

if (ParamStruct[paramindex].sequence == 0)

return returnstring;

int pattr = ParamStruct[paramindex].pattr;

if ( (pattr & 0x01) == 0x01)

returnstring = returnstring + "[in]" ;

if ( (pattr & 0x02) == 0x02)

returnstring = returnstring + "[out]" ;

if ( (pattr & 0x10) == 0x10)

returnstring = returnstring + "[opt]" ;

if ( returnstring != "")

returnstring = returnstring + " ";

return returnstring ;

}

public string GetParamAttrforMethodCalling (int methodindex)

{

string returnstring = "";

if (ParamStruct == null)

return returnstring;

int end;

int start = MethodStruct[methodindex].param;

if ( methodindex == (MethodStruct.Length -1) )

end = ParamStruct.Length + 1;

else

end =  MethodStruct[methodindex+1].param;

if ( start == ParamStruct.Length)

return returnstring;

if ( start == end)

return returnstring;

if (ParamStruct[start].sequence != 0)

return "";

int pattr = ParamStruct[start].pattr;

if ( (pattr & 0x01) == 0x01)

returnstring = returnstring + "[in]" ;

if ( (pattr & 0x02) == 0x02)

returnstring = returnstring + "[out]" ;

if ( (pattr & 0x10) == 0x10)

returnstring = returnstring + "[opt]" ;

if ( returnstring != "")

returnstring = returnstring + " ";

return returnstring ;

}

public string GetFieldAttributes (int fieldrow)

{

int flags = FieldStruct[fieldrow].flags;

string returnstring = "";

string arrayoffset = "";

int ii;

if ( FieldLayoutStruct != null)

{

for ( ii = 1 ; ii < FieldLayoutStruct.Length ; ii++)

{

int jj = FieldLayoutStruct[ii].fieldindex ;

if ( jj == fieldrow )

break;

}

if ( ii != FieldLayoutStruct.Length )

{

int offset = FieldLayoutStruct[ii].offset ;

arrayoffset = "[" + offset.ToString("") + "] ";

}

}

if ( (flags & 0x06) == 0x06)

returnstring = returnstring + "public ";

else

if ( (flags & 0x05) == 0x05)

returnstring = returnstring + "famorassem ";

else

if ( (flags & 0x03) == 0x03)

returnstring = returnstring + "assembly ";

else

if ( (flags & 0x01) == 0x01)

returnstring = returnstring + "private ";

else

if ( (flags & 0x02) == 0x02)

returnstring = returnstring + "famandassem ";

else

if ( (flags & 0x04) == 0x04)

returnstring = returnstring + "family ";

else

returnstring = returnstring + "privatescope ";

if ( (flags & 0x10) == 0x10)

{

int firstfourbits = flags & 0xF;

if ( (firstfourbits == 0x06) || (firstfourbits  == 0x01))

{

returnstring = returnstring + "static " ;

}

else

returnstring = "static " + returnstring;

}

returnstring = arrayoffset + returnstring;

if ( (flags & 0x20) == 0x20)

returnstring = returnstring + "initonly ";

if ( (flags & 0x40) == 0x40)

returnstring = returnstring + "literal ";

if ( (flags & 0x80) == 0x80)

returnstring = returnstring + "notserialized ";

if ( (flags & 0x200) == 0x200)

returnstring = returnstring + "specialname ";

if ( (flags & 0x400) == 0x400)

returnstring = returnstring + "rtspecialname ";

if ( (flags & 0x400) == 0x400)

returnstring = returnstring + "";

returnstring = returnstring +  DecodeParamAttributes ( flags , 0 , fieldrow , 0x1000);

return returnstring;

}

public void DisplayAllSecurity (int tabletype , int tableindex)

{

if (DeclSecurityStruct == null)

return;

for ( int ii = 1 ; ii < DeclSecurityStruct.Length ; ii++)

{

int coded = DeclSecurityStruct[ii].coded;

int table = coded & 0x03;

int row = coded >> 2;

if ( (table == tabletype && row == tableindex ) )

{

string returnstring;

if ( tabletype == 2)

returnstring = CreateSpaces(2 );

else if ( tabletype == 0)

returnstring = CreateSpaces(spacesforrest + spacesfornested);

else

returnstring = CreateSpaces(spacesforrest +2 + spacesfornested);

returnstring = returnstring + ".permissionset " ;

string actionname = GetActionSecurity(DeclSecurityStruct[ii].action);

returnstring = returnstring + actionname ;

returnstring = returnstring + " = (" ;

Console.Write(returnstring);

int index = DeclSecurityStruct[ii].bindex;

if ( index == 0)

Console.WriteLine(")");

else

DisplayFormattedColumns(index ,returnstring.Length, false , false);

}

}

}

public void DisplayFileTable ()

{

if ( FileStruct == null  )

return;

for ( int ii = 1 ; ii < FileStruct.Length ; ii++)

{

Console.WriteLine(".file /*26{0}*/ {1}{2}" , ii.ToString("X6") , GetFileAttributes(FileStruct[ii].flags) , NameReserved(GetString(FileStruct[ii].name)));

int table = entrypointtoken >> 24;

if ( table == 0x26 )

{

int row = entrypointtoken & 0x00ffffff;

if ( row == (ii) )

Console.WriteLine("    .entrypoint");

}

if ( FileStruct[ii].index != 0)

{

Console.Write("    .hash = (");

int index = FileStruct[ii].index ;

DisplayFormattedColumns(index ,13 , false , false);

}

DisplayCustomAttribute("File" , ii , 0);

}

}

public void DisplayAssembleyRefs ()

{

if (AssemblyRefStruct == null)

return;

for ( int i = 1 ; i < AssemblyRefStruct.Length ; i++)

{

//Console.WriteLine("...........{0} {1}" , AssemblyRefStruct[i].name , strings.Length);

Console.WriteLine(".assembly extern /*23{0}*/ {1}", i.ToString("X6") , NameReserved(GetString(AssemblyRefStruct[i].name)));

Console.WriteLine("{");

DisplayCustomAttribute("AssemblyRef" , i , 2 );

if (AssemblyRefStruct[i].publickey  != 0)

{

Console.Write("  .publickeytoken = (");

DisplayFormattedColumns(AssemblyRefStruct[i].publickey,22 , true , false);

}

if ( AssemblyRefStruct[i].hashvalue != 0 )

{

Console.Write("  .hash = (");

DisplayFormattedColumns(AssemblyRefStruct[i].hashvalue,11 , false , false);

}

int rev = AssemblyRefStruct[i].revision;

if ( rev < 0)

rev = 65536 + rev;

Console.WriteLine("  .ver {0}:{1}:{2}:{3}" , AssemblyRefStruct[i].major, AssemblyRefStruct[i].minor,AssemblyRefStruct[i].build,rev);

if ( AssemblyRefStruct[i].culture != 0 )

{

Console.Write("  .locale = (");

int index = AssemblyRefStruct[i].culture;

int cnt = 0;

while ( strings[index] != 0)

{

Console.Write("{0} 00 " , strings[index].ToString("X"));

cnt++;

index++;

}

int nos = 64 - (14 + 6 + (6*cnt+1));

Console.Write("00 00");

Console.Write(" ){0}// " , CreateSpaces(nos));

index = AssemblyRefStruct[i].culture;

while ( strings[index] != 0)

{

Console.Write("{0}." , (char)strings[index]);

index++;

}

Console.WriteLine("..");

}

Console.WriteLine("}");

}

}

public void DisplayAssembley()

{

if (AssemblyStruct.Length  == 1)

return;

Console.WriteLine(".assembly /*20000001*/ {0}" , NameReserved(GetString(AssemblyStruct[1].name)));

Console.WriteLine("{");

DisplayCustomAttribute("Assembly" , 1 , 2 + spacefornamespace);

DisplayAllSecurity( 2 , 1);

if ( AssemblyStruct[1].publickey != 0)

{

Console.Write("  .publickey = (");

DisplayFormattedColumns(AssemblyStruct[1].publickey ,16 , true , false);

}

if ( AssemblyStruct[1].HashAlgId != 0)

Console.WriteLine("  .hash algorithm 0x{0}",AssemblyStruct[1].HashAlgId.ToString("x8"));

int rev = AssemblyStruct[1].revision;

if ( rev < 0)

rev = 65536 + rev;

Console.WriteLine("  .ver {0}:{1}:{2}:{3}" , AssemblyStruct[1].major, AssemblyStruct[1].minor,AssemblyStruct[1].build,rev);

if ( AssemblyStruct[1].culture != 0 )

{

Console.Write("  .locale = (");

int index = AssemblyStruct[1].culture;

int cnt = 0;

while ( strings[index] != 0)

{

Console.Write("{0} 00 " , strings[index].ToString("X"));

index++;

cnt++;

}

Console.Write("00 00");

Console.Write(" )");

int nos =  64 - (15 + cnt*6 + 6);

Console.Write(CreateSpaces(nos));

Console.Write("// ");

index = AssemblyStruct[1].culture;

while ( strings[index] != 0)

{

Console.Write("{0}." , (char)strings[index]);

index++;

}

Console.WriteLine("..");

}

Console.WriteLine("}");

}

public string DisplayExceptionBytes(int i)

{

string ss = "// HEX: " ;

ss = ss + ConvertInt32ToString(ExceptionStruct[i].flags);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].tryoffset);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].trylength);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].handleroffset);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].handlerlength);

ss = ss + ConvertInt32ToString(ExceptionStruct[i].token);

ss = ss.Remove(ss.Length-1,1);

return ss + "\r\n";

}

public string ConvertInt32ToString(int i)

{

string ss = "";

int b1  = i & 0xff;

int b2 = (i & 0xff00 ) >> 8;

int b3 = (i & 0xff0000 ) >> 16;

int b4 = i >> 24;

if ( b4 == -1)

b4 = 0xff;

ss = b1.ToString("X2") + " " + b2.ToString("X2") + " " + b3.ToString("X2") + " " + b4.ToString("X2") + " " ;

return ss;

}

public void ReadExceptions (long pos, int codesize , int methodindex )

{

int aa = -1;

long where = mfilestream.Position;

long pos1 = pos + codesize + 12 ;

long extra = 0 ;

extra = pos1 % 4 ;

if ( extra != 0 )

extra = 4 - extra ;

long newpos = pos1 + extra;

mfilestream.Position = newpos;

int first = mbinaryreader.ReadByte();

if ( methodindex == aa)

Console.WriteLine("...........Flag={0}" , first.ToString("X"));

if ( (first & 0x40) != 0x40)

{

int second = mbinaryreader.ReadByte();

mbinaryreader.ReadInt16();

int cnt = (second - 4 ) / 12;

if ( methodindex == aa)

Console.WriteLine("................count={0}" , cnt);

ExceptionStruct = new ExceptionTable[cnt];

for ( int jj = 0 ; jj < cnt   ; jj++ )

{

ExceptionStruct[jj].flags = mbinaryreader.ReadInt16();

ExceptionStruct[jj].tryoffset = mbinaryreader.ReadInt16();

ExceptionStruct[jj].trylength = mbinaryreader.ReadByte();

ExceptionStruct[jj].handleroffset = mbinaryreader.ReadInt16();

ExceptionStruct[jj].handlerlength = mbinaryreader.ReadByte();

ExceptionStruct[jj].token = mbinaryreader.ReadInt32();

ExceptionStruct[jj].oneline =0;

}

if ( methodindex == aa)

Console.WriteLine("...........If Over" );

}

else

{

if ( methodindex == aa)

Console.WriteLine("............in else");

int a1 = mbinaryreader.ReadByte();

int a2 = mbinaryreader.ReadByte();

int a3 = mbinaryreader.ReadByte();

int second = a1 + a2 * 256 + a3 * 65536;

if ( methodindex == aa)

Console.WriteLine("............a1={0} a2={1} a3={2} second={3}" , a1 , a2 , a3 , second);

int cnt;

if ( second == 24)

cnt = 1;

else if ( second == 48)

cnt = 2;

else

cnt = (second - 4 ) / 24;

ExceptionStruct = new ExceptionTable[cnt];

if ( methodindex == aa)

Console.WriteLine("................count={0}" , cnt);

for ( int jj = 0 ; jj < cnt   ; jj++ )

{

ExceptionStruct[jj].flags = mbinaryreader.ReadInt32();

ExceptionStruct[jj].tryoffset = mbinaryreader.ReadInt32();

ExceptionStruct[jj].trylength = mbinaryreader.ReadInt32();

ExceptionStruct[jj].handleroffset = mbinaryreader.ReadInt32();

ExceptionStruct[jj].handlerlength = mbinaryreader.ReadInt32();

ExceptionStruct[jj].token = mbinaryreader.ReadInt32();

ExceptionStruct[jj].oneline =0;

}

}

mfilestream.Position = where;

}

public void DisplayMethodILCode( string classname , string methodname  ,int methodindex )

{

byte [] codearray = new byte[codesize];

for ( int i = 1 ; i <= codesize ; i++)

{

codearray[i-1] = mbinaryreader.ReadByte();

}

spacesfortry = 0;

if ( (first12&0x08) == 0x08 && !tinyformat)

CreateExceptionArray(methodindex , codearray );

for ( int arrayoffset = 0 ; arrayoffset  < codesize ; )

{

int instructionbyte  = codearray[arrayoffset ];

OpCode opcode;

if ( (first12&0x08) == 0x08 && !tinyformat)

DisplayExceptions(arrayoffset , codearray );

string strings = "";

int twobyte = 0;

if ( instructionbyte == 0xFE)

{

instructionbyte = codearray[arrayoffset +1];

opcode = OpCodesArray1[instructionbyte] ;

strings = CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested);

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X") + " | ";

//Console.Write(strings);

arrayoffset  = arrayoffset  + 1;

twobyte = 1;

}

else

{

opcode = OpCodesArray[instructionbyte];

strings = CreateSpaces(spacesforrest+2+spacesfortry + spacesfornested);

twobyte = 0;

if ( ! (opcode.Value == 0 && opcode.Name != "nop"))

{

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + opcode.Value.ToString("X2") + "   | ";

//Console.Write(strings);

}

}

if ( opcode.Value == 0 && opcode.Name != "nop")

{

strings = strings + "IL_" + arrayoffset .ToString("x4") + ":  /* " + instructionbyte.ToString("X2") + "   | ";

strings = strings + CreateSpaces(17) + "*/ unused" ;

Console.WriteLine("{0}", strings );

arrayoffset  = arrayoffset  + 1;

}

else

{

int sizeofinstructionanddata  = DecodeILInstrcution2( opcode , arrayoffset  , codearray , methodindex , strings );

Console.WriteLine();

if ( (first12&0x08) == 0x08 && !tinyformat)

DisplayExceptions1(arrayoffset , codearray , twobyte);

arrayoffset  = arrayoffset  + sizeofinstructionanddata;

}

}

if ( (first12&0x08) == 0x08 && !tinyformat)

{

if ( ExceptionStruct[0].oneline == 2)

{

Console.Write(CreateSpaces(spacesforrest+ spacesfornested + 2 ));

Console.WriteLine("IL_{0:x4}:  " , codearray.Length);

Console.Write(CreateSpaces(spacesforrest+ spacesfornested + 2 ));

Console.WriteLine("// Exception count 1");

DisplayOneLineTry(0);

}

}

Console.Write(CreateSpaces(spacesforrest+ spacesfornested));

Console.Write("}");

if ( GetTypeForMethod(methodindex)== 1)

Console.WriteLine(" // end of global method {0}\r\n" , methodname);

else

Console.WriteLine(" // end of method {0}::{1}\r\n" , classname , methodname);

}

public void CreateExceptionArray(int methodindex , byte [] codearray)

{

if (ExceptionStruct == null)

return;

if ( ExceptionStruct[0].handleroffset + ExceptionStruct[0].handlerlength == codearray.Length && ExceptionStruct.Length == 1)

ExceptionStruct[0].oneline = 2;

if ( ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset && ExceptionStruct.Length == 1)

ExceptionStruct[0].oneline = 1;

if ( ExceptionStruct.Length == 2)

{

bool a = ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset;

bool b = ExceptionStruct[1].tryoffset + ExceptionStruct[1].trylength != ExceptionStruct[1].handleroffset;

if ( a && b)

{

ExceptionStruct[0].oneline = 1;

ExceptionStruct[1].oneline = 1;

}

}

if ( ExceptionStruct.Length == 2)

{

bool a = ExceptionStruct[0].tryoffset + ExceptionStruct[0].trylength != ExceptionStruct[0].handleroffset;

bool b = ExceptionStruct[1].tryoffset + ExceptionStruct[1].trylength == ExceptionStruct[1].handleroffset;

if ( a && b)

{

ExceptionStruct[0].oneline = 1;

ExceptionStruct[1].oneline = 0;

}

}

if ( ExceptionStruct.Length == 2)

{

if ( ExceptionStruct[0].tryoffset == ExceptionStruct[1].tryoffset  && ExceptionStruct[0].trylength == ExceptionStruct[1].trylength && ExceptionStruct[1].handleroffset + ExceptionStruct[1].handlerlength == codearray.Length -1 && ExceptionStruct[0].handlerlength == 1)

if ( ExceptionStruct[0].handleroffset + ExceptionStruct[0].handlerlength != ExceptionStruct[1].handleroffset)

ExceptionStruct[1].oneline = 1;

}

if ( ExceptionStruct.Length == 3 &&  ExceptionStruct[0].tryoffset == ExceptionStruct[1].tryoffset && ExceptionStruct[0].tryoffset > ExceptionStruct[2].tryoffset &&  ExceptionStruct[0].flags == ExceptionStruct[1].flags &&  ExceptionStruct[2].flags == ExceptionStruct[1].flags && ExceptionStruct[1].flags== 2)

{

ExceptionTable a = ExceptionStruct[0];

ExceptionStruct[0] = ExceptionStruct[2];

ExceptionStruct[2] = a;

}

for ( int ii = 0 ; ii < ExceptionStruct.Length - 1 ; ii++)

{

int secondtry = ExceptionStruct[ii].tryoffset +  ExceptionStruct[ii].trylength;

int thirdtry = ExceptionStruct[ii+1].tryoffset +  ExceptionStruct[ii+1].trylength;

if ( ExceptionStruct[ii].tryoffset > ExceptionStruct[ii+1].tryoffset && secondtry > thirdtry)

{

ExceptionTable a = ExceptionStruct[ii];

ExceptionStruct[ii] = ExceptionStruct[ii+1];

ExceptionStruct[ii+1] = a;

}

}

if ( methodindex == -1)

{

for (int ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

Console.WriteLine(" Flags {0} " , ExceptionStruct[ii].flags.ToString("X8"));

Console.WriteLine(" Try Offset {0} 0x{1}" , ExceptionStruct[ii].tryoffset , ExceptionStruct[ii].tryoffset.ToString("X"));

Console.WriteLine(" Try Length {0} 0x{1}" , ExceptionStruct[ii].trylength , ExceptionStruct[ii].trylength.ToString("X"));

Console.WriteLine(" Handler  Offset {0} 0x{1}" , ExceptionStruct[ii].handleroffset , ExceptionStruct[ii].handleroffset.ToString("X") );

Console.WriteLine(" Handler length {0} 0x{1}" , ExceptionStruct[ii].handlerlength , ExceptionStruct[ii].handlerlength.ToString("X"));

Console.WriteLine(" Token {0:X}" , ExceptionStruct[ii].token , ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength);

Console.WriteLine("EndTry={0:X} Endhandler={1:X} codearray={2:X} oneline={3}" , ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength, ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength , codearray.Length , ExceptionStruct[ii].oneline);

Console.WriteLine();

}

}

}

public void DisplayExceptions (int instructionnumber , byte [] codearray )

{

int ii ;

bool endtry = false;

for ( ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

bool showtry = true;

if ( ii >= 1 ) // to show a try or not

{

int first = ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength;

int second = ExceptionStruct[ii-1].tryoffset + ExceptionStruct[ii-1].trylength;

if ( first == second && ExceptionStruct[ii-1].oneline != 1)

showtry = false;

else

showtry = true;

}

if ( instructionnumber == ExceptionStruct[ii].tryoffset && showtry && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine(".try");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry+ spacesfornested));

Console.Write("{\r\n");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength && !endtry && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.WriteLine("}  // end .try");

spacesfortry = spacesfortry - 2;

endtry= true;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 0 && ExceptionStruct[ii].oneline == 0)

{

int token = ExceptionStruct[ii].token;

int table = token >> 24;

int tablerow = token & 0xffffff;

string typename="";

if ( table == 2)

typename = typedefnames[tablerow];

if ( table == 1)

typename = typerefnames[tablerow];

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("catch {0} " , typename);

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

//Console.WriteLine("........{0} {1}" , table, tablerow);

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 2 && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("finally");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset && ExceptionStruct[ii].flags == 4 && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("fault");

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.WriteLine("{");

spacesfortry = spacesfortry + 2;

}

if ( instructionnumber == ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength  && ExceptionStruct[ii].oneline == 0)

{

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.WriteLine("}  // end handler");

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested));

Console.Write(DisplayExceptionBytes(ii));

spacesfortry = spacesfortry - 2;

}

}

}

public void DisplayExceptions1(int instructionnumber , byte [] codearray, int twobyte )

{

int ii ;

//Console.WriteLine(".......{0:X} {1:X}" , instructionnumber , codearray[instructionnumber] );

for ( ii = 0 ; ii < ExceptionStruct.Length ; ii++)

{

int trypos = ExceptionStruct[ii].tryoffset+ ExceptionStruct[ii].trylength ;

int handlerpos = ExceptionStruct[ii].handleroffset+ ExceptionStruct[ii].handlerlength ;

int offset;

//div_i4.exe div_i8.exe

if ( trypos > handlerpos)

offset = trypos;

else

offset = handlerpos;

 

if ( instructionnumber ==  offset + twobyte && ExceptionStruct[ii].oneline == 1 )

DisplayOneLineTry(ii);

}

}

public void DisplayOneLineTry( int ii)

{

int token = ExceptionStruct[ii].token;

int table = token >> 24;

int tablerow = token & 0xffffff;

string typename="";

if ( table == 2)

typename = typedefnames[tablerow];

if ( table == 1)

typename = typerefnames[tablerow];

Console.Write(CreateSpaces(spacesforrest+2+ spacesfortry + spacesfornested));

Console.Write(".try IL_{0} to" , ExceptionStruct[ii].tryoffset.ToString("x4"));

int end = ExceptionStruct[ii].tryoffset + ExceptionStruct[ii].trylength;

Console.Write(" IL_{0} " , end.ToString("x4"));

if ( ExceptionStruct[ii].flags == 0)

Console.Write("catch {0} handler " , typename);

else if ( ExceptionStruct[ii].flags == 2)

Console.Write("finally handler " );

else if ( ExceptionStruct[ii].flags == 4)

Console.Write("fault handler " );

else

Console.Write("filter IL_{0} handler " , token.ToString("x4"));

Console.Write("IL_{0} to",ExceptionStruct[ii].handleroffset.ToString("x4"));

int end1 = ExceptionStruct[ii].handleroffset + ExceptionStruct[ii].handlerlength;

Console.WriteLine(" IL_{0}" , end1.ToString("x4"));

Console.Write(CreateSpaces(spacesforrest+spacesfortry + spacesfornested + 2));

Console.Write(DisplayExceptionBytes(ii));

ExceptionStruct[ii].oneline = 0;

}

public void DisplayFinalBytes(int ii , string returnstring)

{

int index = CustomAttributeStruct[ii].value;

int howmanybytes,uncompressedbyte ;

howmanybytes = CorSigUncompressData(blob , index , out uncompressedbyte);

index = index + howmanybytes;

byte [] blobarray = new byte[uncompressedbyte];

Array.Copy(blob , index , blobarray , 0 , uncompressedbyte);

bool displayoneline = true;

string displaystring = "";

for ( int  jj = 0 ; jj < uncompressedbyte ; jj++)

{

if ( blobarray[jj] < 0x20)

displayoneline = false;

if ( blobarray[jj] >= 0x7f)

displayoneline = false;

}

int countascii = 0;

for ( int  jj = 0 ; jj < uncompressedbyte ; jj++)

{

if ( blobarray[jj] >= 0x20 && blobarray[jj] <= 0x7f)

countascii++;

}

if ( displayoneline)

{

displaystring = " = \"";

for ( int  jj = 0 ; jj < uncompressedbyte ; jj++)

{

displaystring = displaystring + (char)blobarray[jj];

}

displaystring = displaystring + "\"";

Console.WriteLine(displaystring);

}

else

{

int startoffunctionclosebracket = returnstring.LastIndexOf(")");

int startoflastopenbracket = returnstring.Length - 1;

int lastenter = returnstring.LastIndexOf("\r\n");

int firstenter = returnstring.IndexOf("\r\n");

int firstopenbracket = returnstring.IndexOf("(");

if ( lastenter == -1)

lastenter = -2;

int diff2 = startoffunctionclosebracket - lastenter + 19;

Console.Write(" = ( ");

DisplayFormattedColumns(CustomAttributeStruct[ii].value,diff2 , false , false);

}

}

public void DisplayFinalCustomAttributes()

{

if ( CustomAttributeStruct == null)

return;

for ( int ii = 1 ; ii < CustomAttributeStruct.Length ; ii++)

{

string parentcodedtablename= GetHasCustomAttributeTable(CustomAttributeStruct[ii].parent) ;

int parentcodedindex= GetHasCustomAttributeValue(CustomAttributeStruct[ii].parent);

string typecodetable = GetCustomAttributeTypeTable(CustomAttributeStruct[ii].type) ;

int typecodedindex  = GetCustomAttributeTypevalue(CustomAttributeStruct[ii].type);

int typeindexofmethod = GetTypeForMethod(parentcodedindex);

int typeindexforfield = GetTypeForField(parentcodedindex);

if ( parentcodedtablename == "Property" )

{

}

if ( parentcodedtablename == "FieldDef" && GetString(TypeDefStruct[typeindexforfield].name) == "_Deleted")

{

string returnstring ="  .custom /*0C" + ii.ToString("X6") + "*/ (UNKNOWN_OWNER/*040000" + parentcodedindex.ToString("X2");

returnstring = returnstring + "*/ ) instance void " ;

int typerefindex = MemberRefStruct[typecodedindex].clas >> 3;

string typerefname = typerefnames[typerefindex] ;

returnstring = returnstring + typerefname  + "::" + NameReserved(GetString(MemberRefStruct[typecodedindex].name)) + "(";

returnstring = returnstring + methodrefparamarray1[typecodedindex] + ") /* 0A0000" + typecodedindex.ToString("X2") + " */";

Console.Write(returnstring);

DisplayFinalBytes(ii , returnstring);

}

if ( parentcodedtablename == "TypeDef" && GetString(TypeDefStruct[parentcodedindex].name) == "_Deleted")

{

string returnstring = "  .custom /*0C" + ii.ToString("X6") + "*/ (" + GetString(TypeDefStruct[parentcodedindex].nspace) + "." + GetString(TypeDefStruct[parentcodedindex].name);

returnstring = returnstring + "/* 020000" + parentcodedindex.ToString("X2") + " *//*020000" + parentcodedindex.ToString("X2") + "*/ ) instance void ";

int typerefindex = MemberRefStruct[typecodedindex].clas >> 3;

string typerefname = typerefnames[typerefindex] ;

returnstring = returnstring + typerefname + "::" + NameReserved(GetString(MemberRefStruct[typecodedindex].name)) + "() /* 0A0000" + typecodedindex.ToString("X2") + " */";

Console.Write(returnstring);

DisplayFinalBytes(ii , returnstring);

}

if ( parentcodedtablename == "MethodDef" && GetString(TypeDefStruct[typeindexofmethod ].name) == "_Deleted")

{

string methodtype = "";

if ( GetString(MethodStruct[parentcodedindex].name) != "Main")

methodtype = methoddeftypearray[typeindexofmethod];

if ( GetString(MethodStruct[parentcodedindex].name) == "InitializeComponent")

methodtype = "instance ";

Console.Write("  .custom /*0C{0}*/ (method {1}void " , ii.ToString("X6") , methodtype , methoddefreturnarray[typeindexofmethod]);

Console.Write("{0}.{1}/* 02{2}" , GetString(TypeDefStruct[typeindexofmethod].nspace), GetString(TypeDefStruct[typeindexofmethod].name) , typeindexofmethod.ToString("X6"));

Console.Write(" */::{0}() /* 060000{1} *//*060000{1}*/ ) " , GetString(MethodStruct[parentcodedindex].name),  parentcodedindex.ToString("X2"));

int typerefindex = MemberRefStruct[typecodedindex].clas >> 3;

string typerefname = typerefnames[typerefindex] ;

Console.Write("instance void {1}::{2}() /* 0A0000{3} */ = ( 01 00 00 00 ) ", methoddefreturnarray[typeindexofmethod] , typerefname , ".ctor", typecodedindex.ToString("X2") );

Console.WriteLine();

}

}

}

}

 

End------------------------