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------------------------