├── 9781430267614.jpg ├── LICENSE.txt ├── README.md ├── Samples ├── Simple.il ├── Simple1.il ├── Simple2.il ├── Simple3.il ├── Simple4.il ├── YDD.il ├── callback.il ├── cctor.il ├── cctors.il ├── gen_virt.il ├── genfptr.il ├── gv.il ├── illink.cpp ├── illink_readme.txt ├── overloads.il ├── override.il ├── override_v2.il ├── privatector.il ├── virt_not.il └── virt_not2.il └── contributing.md /9781430267614.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/dotnet-il-assembler/063705937d79a3efc3bc504fbfadd7a77bd4c88c/9781430267614.jpg -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/dotnet-il-assembler/063705937d79a3efc3bc504fbfadd7a77bd4c88c/LICENSE.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*.NET IL Assembler*](http://www.apress.com/9781430267614) by Serge Lidin (Apress, 2014). 4 | 5 | ![Cover image](9781430267614.jpg) 6 | 7 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 8 | 9 | ## Releases 10 | 11 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 12 | 13 | ## Contributions 14 | 15 | See the file Contributing.md for more information on how you can contribute to this repository. 16 | -------------------------------------------------------------------------------- /Samples/Simple.il: -------------------------------------------------------------------------------- 1 | //----------- Program header 2 | .assembly extern mscorlib { auto } 3 | .assembly OddOrEven { } 4 | .module OddOrEven.exe 5 | //----------- Class declaration 6 | .namespace Odd.or { 7 | .class public auto ansi Even extends [mscorlib]System.Object { 8 | //----------- Field declaration 9 | .field public static int32 val 10 | //----------- Method declaration 11 | .method public static void check( ) cil managed { 12 | .entrypoint 13 | .locals init (int32 Retval) 14 | AskForNumber: 15 | ldstr "Enter a number" 16 | call void [mscorlib]System.Console::WriteLine (string) 17 | call string [mscorlib]System.Console::ReadLine () 18 | ldsflda valuetype CharArray8 Format 19 | ldsflda int32 Odd.or.Even::val 20 | call vararg int32 sscanf(string,int8*,...,int32*) 21 | stloc Retval 22 | ldloc Retval 23 | brfalse Error 24 | ldsfld int32 Odd.or.Even::val 25 | ldc.i4 1 26 | and 27 | brfalse ItsEven 28 | ldstr "odd!" 29 | br PrintAndReturn 30 | ItsEven: 31 | ldstr "even!" 32 | br PrintAndReturn 33 | Error: 34 | ldstr "How rude!" 35 | PrintAndReturn: 36 | call void [mscorlib]System.Console::WriteLine (string) 37 | ldloc Retval 38 | brtrue AskForNumber 39 | ret 40 | } // End of method 41 | } // End of class 42 | } // End of namespace 43 | //----------- Global items 44 | .field public static valuetype CharArray8 Format at FormatData 45 | //----------- Data declaration 46 | .data FormatData = bytearray(25 64 00 00 00 00 00 00) // % d . . . . . . 47 | //----------- Value type as placeholder 48 | .class public explicit CharArray8 49 | extends [mscorlib]System.ValueType { .size 8 } 50 | //----------- Calling unmanaged code 51 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 52 | vararg int32 sscanf(string,int8*) cil managed preservesig { } 53 | -------------------------------------------------------------------------------- /Samples/Simple1.il: -------------------------------------------------------------------------------- 1 | //----------- Program header 2 | .assembly extern mscorlib { auto } 3 | .assembly OddOrEven { } 4 | .module OddOrEven.exe 5 | //----------- Class declaration 6 | .namespace Odd.or { 7 | .class public auto ansi Even 8 | extends [mscorlib]System.Object { 9 | //----------- Field declaration 10 | .field public static int32 val 11 | //----------- Method declaration 12 | .method public static void check( ) cil managed { 13 | .entrypoint 14 | .locals init (int32 Retval) 15 | AskForNumber: 16 | ldstr "Enter a number" 17 | call void [mscorlib]System.Console::WriteLine(string) 18 | call string [mscorlib]System.Console::ReadLine() 19 | ldstr "%d" // CHANGE! 20 | ldsflda int32 Odd.or.Even::val 21 | call vararg int32 sscanf(string,string,...,int32*) 22 | // CHANGE! 23 | stloc.0 // CHANGE! 24 | ldloc.0 // CHANGE! 25 | brfalse.s Error // CHANGE! 26 | ldsfld int32 Odd.or.Even::val 27 | ldc.i4.1 // CHANGE! 28 | and 29 | brfalse.s ItsEven // CHANGE! 30 | ldstr "odd!" 31 | br.s PrintAndReturn // CHANGE! 32 | ItsEven: 33 | ldstr "even!" 34 | br.s PrintAndReturn // CHANGE! 35 | Error: 36 | ldstr "How rude!" 37 | PrintAndReturn: 38 | call void [mscorlib]System.Console::WriteLine(string) 39 | ldloc.0 // CHANGE! 40 | brtrue.s AskForNumber // CHANGE! 41 | ret 42 | } // End of method 43 | } // End of class 44 | } // End of namespace 45 | //----------- Calling unmanaged code 46 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 47 | vararg int32 sscanf(string,string) cil managed preservesig { } 48 | -------------------------------------------------------------------------------- /Samples/Simple2.il: -------------------------------------------------------------------------------- 1 | //----------- Program header 2 | .assembly extern mscorlib { auto } 3 | .assembly OddOrEven { } 4 | .module OddOrEven.exe 5 | //----------- Class Declaration 6 | .namespace Odd.or { 7 | .class public auto ansi Even 8 | extends [mscorlib]System.Object { 9 | //------------ Field declaration 10 | .field public static int32 val 11 | //------------ Method declaration 12 | .method public static void check( ) cil managed { 13 | .entrypoint 14 | .locals init (int32 Retval) 15 | AskForNumber: 16 | ldstr "Enter a number" 17 | call void [mscorlib]System.Console::WriteLine(string) 18 | .try { // CHANGE! 19 | // Guarded block begins 20 | call string [mscorlib]System.Console::ReadLine() 21 | // pop // CHANGE! 22 | // ldnull // CHANGE! 23 | ldstr "%d" 24 | ldsflda int32 Odd.or.Even::val 25 | call vararg int32 sscanf(string,string,...,int32*) 26 | stloc.0 27 | leave.s DidntBlowUp // CHANGE! 28 | // Guarded block ends 29 | } // CHANGE! 30 | // CHANGE block begins! ---> 31 | catch [mscorlib]System.Exception 32 | { // Exception handler begins 33 | pop 34 | ldstr "KABOOM!" 35 | call void [mscorlib]System.Console::WriteLine(string) 36 | leave.s Return 37 | } // Exception handler ends 38 | DidntBlowUp: 39 | // <--- CHANGE block ends! 40 | ldloc.0 41 | brfalse.s Error 42 | ldsfld int32 Odd.or.Even::val 43 | ldc.i4.1 44 | and 45 | brfalse.s ItsEven 46 | ldstr "odd!" 47 | br.s PrintAndReturn 48 | ItsEven: 49 | ldstr "even!" 50 | br.s PrintAndReturn 51 | Error: 52 | ldstr "How rude!" 53 | PrintAndReturn: 54 | call void [mscorlib]System.Console::WriteLine(string) 55 | ldloc.0 56 | brtrue.s AskForNumber 57 | Return: // CHANGE! 58 | ret 59 | } // End of method 60 | } // End of class 61 | } // End of namespace 62 | //----------- Calling unmanaged code 63 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 64 | vararg int32 sscanf(string,string) cil managed preservesig { } 65 | -------------------------------------------------------------------------------- /Samples/Simple3.il: -------------------------------------------------------------------------------- 1 | //----------- Program header 2 | .assembly extern mscorlib { auto } 3 | .assembly OddOrEven { } 4 | .module OddOrEven.exe 5 | //----------- Aliasing 6 | .typedef [mscorlib]System.Console as TTY 7 | .typedef method void TTY::WriteLine(string) as PrintLine 8 | //----------- Class Declaration 9 | .class public Odd.Or.Even { 10 | //------------ Field declaration 11 | .field public static int32 val 12 | //------------ Method declaration 13 | .method public static void check( ) { 14 | .entrypoint 15 | .locals init (int32 Retval) 16 | AskForNumber: 17 | ldstr "Enter a number" 18 | call PrintLine 19 | .try { 20 | // Guarded block begins 21 | call string TTY::ReadLine() 22 | // pop 23 | // ldnull 24 | ldstr "%d" 25 | ldsflda int32 Odd.Or.Even::val 26 | call vararg int32 sscanf(string,string,...,int32*) 27 | stloc.0 28 | leave.s DidntBlowUp 29 | // Guarded block ends 30 | } 31 | catch [mscorlib]System.Exception 32 | { // Exception handler begins 33 | pop 34 | ldstr "KABOOM!" 35 | call PrintLine 36 | leave.s Return 37 | } // Exception handler ends 38 | DidntBlowUp: 39 | ldloc.0 40 | brfalse.s Error 41 | ldsfld int32 Odd.Or.Even::val 42 | ldc.i4.1 43 | and 44 | brfalse.s ItsEven 45 | ldstr "odd!" 46 | br.s PrintAndReturn 47 | ItsEven: 48 | ldstr "even!" 49 | br.s PrintAndReturn 50 | Error: 51 | ldstr "How rude!" 52 | PrintAndReturn: 53 | call PrintLine 54 | ldloc.0 55 | brtrue.s AskForNumber 56 | Return: 57 | ret 58 | } // End of method 59 | } // End of class 60 | //------------ Calling unmanaged code 61 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 62 | vararg int32 sscanf(string,string) preservesig { } 63 | -------------------------------------------------------------------------------- /Samples/Simple4.il: -------------------------------------------------------------------------------- 1 | // #define USE_MAPPED_FIELD 2 | // #define BLOW_UP 3 | //----------- Program header 4 | .assembly extern mscorlib { auto } 5 | .assembly OddOrEven { } 6 | .module OddOrEven.exe 7 | //----------- Aliasing 8 | .typedef [mscorlib]System.Console as TTY 9 | .typedef method void TTY::WriteLine(string) as PrintLine 10 | //----------- Class Declaration 11 | .class public Odd.Or.Even { 12 | //------------ Field declaration 13 | .field public static int32 val 14 | //------------ Method declaration 15 | .method public static void check( ) { 16 | .entrypoint 17 | .locals init (int32 Retval) 18 | AskForNumber: 19 | ldstr "Enter a number" 20 | call PrintLine 21 | .try { 22 | // Guarded block begins 23 | call string TTY::ReadLine() 24 | #ifdef BLOW_UP 25 | pop 26 | ldnull 27 | #endif 28 | 29 | #ifdef USE_MAPPED_FIELD 30 | ldsflda valuetype CharArray8 Format 31 | ldsflda int32 Odd.Or.Even::val 32 | call vararg int32 sscanf(string,int8*,...,int32*) 33 | #else 34 | ldstr "%d" 35 | ldsflda int32 Odd.Or.Even::val 36 | call vararg int32 sscanf(string,string,...,int32*) 37 | #endif 38 | stloc.0 39 | leave.s DidntBlowUp 40 | // Guarded block ends 41 | } 42 | catch [mscorlib]System.Exception 43 | { // Exception handler begins 44 | pop 45 | ldstr "KABOOM!" 46 | call PrintLine 47 | leave.s Return 48 | } // Exception handler ends 49 | DidntBlowUp: 50 | ldloc.0 51 | brfalse.s Error 52 | ldsfld int32 Odd.Or.Even::val 53 | ldc.i4.1 54 | and 55 | brfalse.s ItsEven 56 | ldstr "odd!" 57 | br.s PrintAndReturn 58 | ItsEven: 59 | ldstr "even!" 60 | br.s PrintAndReturn 61 | Error: 62 | ldstr "How rude!" 63 | PrintAndReturn: 64 | call PrintLine 65 | ldloc.0 66 | brtrue.s AskForNumber 67 | Return: 68 | ret 69 | } // End of method 70 | } // End of class 71 | #ifdef USE_MAPPED_FIELD 72 | //----------- Global items 73 | .field public static valuetype CharArray8 Format at FormatData 74 | //----------- Data declaration 75 | .data FormatData = bytearray(25 64 00 00 00 00 00 00) 76 | //----------- Value type as placeholder 77 | .class public explicit value CharArray8 { .size 8 } 78 | //----------- Calling unmanaged code 79 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 80 | vararg int32 sscanf(string,int8*) preservesig { } 81 | #else 82 | //------------ Calling unmanaged code 83 | .method public static pinvokeimpl("msvcrt.dll" cdecl) 84 | vararg int32 sscanf(string,string) preservesig { } 85 | #endif 86 | -------------------------------------------------------------------------------- /Samples/YDD.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly YDD { } 3 | .module YDD.dll 4 | .corflags 0x00000002 5 | .vtfixup [1] int32 fromunmanaged at VT_01 // 1st VTFixup 6 | .vtfixup [1] int32 fromunmanaged at VT_02 // 2nd VTFixup 7 | .vtfixup [1] int32 fromunmanaged at VT_03 // 3rd VTFixup 8 | .data VT_01 = int32(0) // 1st v-table entry 9 | .data VT_02 = int32(0) // 2nd v-table entry 10 | .data VT_03 = int32(0) // 3rd v-table entry 11 | .method public static void Yabba() 12 | { 13 | .vtentry 1:1 14 | .export [1] 15 | ldstr "Yabba" 16 | call void [mscorlib]System.Console::WriteLine(string) 17 | ret 18 | } 19 | .method public static void Dabba() 20 | { 21 | .vtentry 2:1 22 | .export [2] 23 | ldstr "Dabba" 24 | call void [mscorlib]System.Console::WriteLine(string) 25 | ret 26 | } 27 | .method public static void Doo() 28 | { 29 | .vtentry 3:1 30 | .export [3] 31 | ldstr "Doo!" 32 | call void [mscorlib]System.Console::WriteLine(string) 33 | ret 34 | } 35 | -------------------------------------------------------------------------------- /Samples/callback.il: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/dotnet-il-assembler/063705937d79a3efc3bc504fbfadd7a77bd4c88c/Samples/callback.il -------------------------------------------------------------------------------- /Samples/cctor.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly cctor {} 3 | .module cctor.exe 4 | 5 | .class public value V 6 | { 7 | .field public static int32 v 8 | .method public static specialname void .cctor() 9 | { 10 | ldc.i4.3 11 | stsfld int32 V::v 12 | ret 13 | } 14 | } 15 | 16 | .method public static void Exec() 17 | { 18 | .entrypoint 19 | .locals (valuetype V x) 20 | 21 | ldsfld int32 V::v 22 | call void [mscorlib]System.Console::WriteLine(int32) 23 | 24 | ret 25 | } 26 | -------------------------------------------------------------------------------- /Samples/cctors.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly cctors {} 3 | .module cctors.exe 4 | 5 | .typedef [mscorlib]System.Console as TTY 6 | 7 | #define DEFLT_CTOR 8 | ".method public specialname void .ctor(){ldarg.0; call instance void .base::.ctor(); ret;}" 9 | 10 | .class public Base 11 | { 12 | DEFLT_CTOR 13 | .method public void DoSomething() 14 | { 15 | ldarg.0 16 | pop 17 | ldstr "Base::DoSomething()" 18 | call void TTY::WriteLine(string) 19 | ret 20 | } 21 | } 22 | .class public /*beforefieldinit*/ A extends Base 23 | { 24 | DEFLT_CTOR 25 | .method public static specialname void .cctor() 26 | { 27 | ldstr "A::.cctor()" 28 | call void TTY::WriteLine(string) 29 | ret 30 | } 31 | } 32 | .class public /*beforefieldinit*/ B extends Base 33 | { 34 | DEFLT_CTOR 35 | .method public static specialname void .cctor() 36 | { 37 | ldstr "B::.cctor()" 38 | call void TTY::WriteLine(string) 39 | ret 40 | } 41 | } 42 | 43 | .method public static specialname void .cctor() 44 | { 45 | ldstr "::.cctor()" 46 | call void TTY::WriteLine(string) 47 | ret 48 | } 49 | 50 | .method public static void Exec() 51 | { 52 | .entrypoint 53 | .locals init(class Base b1) 54 | 55 | ldstr "Enter string" 56 | call void TTY::WriteLine(string) 57 | call string TTY::ReadLine() 58 | call bool string::IsNullOrEmpty(string) 59 | brtrue L1 // use result of IsNullOrEmpty 60 | 61 | // Instantiate class A with .cctor 62 | newobj instance void A::.ctor() 63 | stloc.s b1 64 | br L2 65 | L1: 66 | // Instantiate class B with .cctor 67 | newobj instance void B::.ctor() 68 | stloc.s b1 69 | L2: 70 | // Use the instance 71 | ldloc.s b1 72 | call instance void Base::DoSomething() 73 | 74 | ret 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /Samples/gen_virt.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly gen_virt{} 3 | .module gen_virt.exe 4 | 5 | #define DEFLT_CTOR ".method public specialname void .ctor(){ldarg.0; call instance void .base::.ctor(); ret;}" 6 | 7 | .typedef method void [mscorlib]System.Console::WriteLine(string) as PrintString 8 | .typedef method void [mscorlib]System.Console::WriteLine(int32) as PrintInt 9 | .typedef [mscorlib]System.Type as SysType 10 | 11 | // Non-generic interface with generic method 12 | .class public interface IX 13 | { 14 | .method public virtual abstract int32 Do(!!T theT){} 15 | } 16 | 17 | // Implicit override of generic virtual method 18 | .class public A implements IX 19 | { 20 | DEFLT_CTOR 21 | .method public virtual int32 Do(!!T theT) 22 | { 23 | ldarga.s theT 24 | constrained. !!T 25 | callvirt instance string object::ToString() 26 | call PrintString 27 | ldc.i4.2 28 | ret 29 | } 30 | } 31 | 32 | // Explicit override of generic method, short form 33 | .class public B implements IX 34 | { 35 | DEFLT_CTOR 36 | .method public virtual int32 DoIt(!!T theT) 37 | { 38 | .override method instance int32 IX::Do<[1]>(!!0) 39 | ldarga.s theT 40 | constrained. !!T 41 | callvirt instance string object::ToString() 42 | call PrintString 43 | ldc.i4.3 44 | ret 45 | } 46 | } 47 | 48 | // Generic instance constructor and 49 | // Explicit override of generic method, long form 50 | .class public C implements IX 51 | { 52 | .method public specialname void .ctor(!!U u) 53 | { 54 | ldarg.0 55 | call instance void .base::.ctor() 56 | 57 | ldtoken !!U 58 | call class SysType SysType::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 59 | callvirt instance string SysType::ToString() 60 | call PrintString 61 | 62 | ldarga.s u 63 | constrained. !!U 64 | callvirt instance string object::ToString() 65 | call PrintString 66 | 67 | ret 68 | } 69 | .override method instance int32 IX::Do<[1]>(!!0) 70 | with method instance int32 .this::DoIt<[1]>(!!0) 71 | .method public virtual int32 DoIt(!!T theT) 72 | { 73 | ldarga.s theT 74 | constrained. !!T 75 | callvirt instance string object::ToString() 76 | call PrintString 77 | ldc.i4.4 78 | ret 79 | } 80 | } 81 | 82 | // Test executing method 83 | .method public static void Exec() 84 | { 85 | .entrypoint 86 | 87 | newobj instance void A::.ctor() 88 | ldstr "Hehe" 89 | callvirt instance int32 IX::Do(!!0) 90 | call PrintInt 91 | 92 | newobj instance void B::.ctor() 93 | ldstr "Haha" 94 | callvirt instance int32 IX::Do(!!0) 95 | call PrintInt 96 | 97 | ldstr "Huhu" 98 | newobj instance void C::.ctor(!!0) 99 | ldstr "Hoho" 100 | callvirt instance int32 IX::Do(!!0) 101 | call PrintInt 102 | 103 | ret 104 | } 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Samples/genfptr.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly genfptr {} 3 | .module genfptr.exe 4 | 5 | .typedef method void [mscorlib]System.Console::WriteLine(string) as PrintString 6 | .method public static !!T GetMedian(!!T[] tarray) 7 | { 8 | ldstr "GetMedian called" 9 | call PrintString 10 | ldarg.0 11 | dup 12 | ldlen 13 | ldc.i4.1 14 | shr 15 | ldelem !!T 16 | ret 17 | } 18 | .method public static !!T Invoke(method !!T*(!!T[]) medFunc, !!T[] tarr) 19 | { 20 | ldstr "Invoke called" 21 | call PrintString 22 | ldarg.1 23 | ldarg.0 24 | calli !!T (!!T[]) 25 | ret 26 | } 27 | 28 | #define CALL_VIA_INVOKE 29 | 30 | .method public static void Exec() 31 | { 32 | .entrypoint 33 | #ifdef CALL_VIA_INVOKE 34 | ldftn !!0 GetMedian(!!0[]) 35 | #endif 36 | ldc.i4.3 37 | newarr string 38 | dup 39 | dup 40 | dup 41 | ldc.i4.0 42 | ldstr "One" 43 | stelem.ref 44 | ldc.i4.1 45 | ldstr "Two" 46 | stelem.ref 47 | ldc.i4.2 48 | ldstr "Three" 49 | stelem.ref 50 | #ifdef CALL_VIA_INVOKE 51 | call !!0 Invoke(method !!0*(!!0[]), !!0[]) 52 | #else 53 | ldftn !!0 GetMedian(!!0[]) 54 | calli string(string[]) 55 | #endif 56 | call PrintString 57 | ret 58 | } 59 | 60 | -------------------------------------------------------------------------------- /Samples/gv.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly gv {} 3 | .module gv.exe 4 | 5 | .class public interface IX 6 | { 7 | .method public abstract virtual void F(!T){} 8 | } 9 | 10 | .class public A implements class IX 11 | { 12 | .method public specialname void .ctor() 13 | { 14 | ldarg.0 15 | call instance void .base::.ctor() 16 | ret 17 | } 18 | .method public virtual void G(!T) 19 | { 20 | .override method instance void class IX::F(!0) 21 | ldstr "IX::F" 22 | call void [mscorlib]System.Console::WriteLine(string) 23 | ret 24 | } 25 | } 26 | 27 | .method public static void Exec() 28 | { 29 | .entrypoint 30 | newobj instance void class A::.ctor() 31 | ldstr "Hehe" 32 | callvirt instance void class IX::F(!0) 33 | ret 34 | } 35 | -------------------------------------------------------------------------------- /Samples/illink.cpp: -------------------------------------------------------------------------------- 1 | // =============================================================== 2 | // 3 | // ILLINK -- Microsoft (R) .NET Framework IL Linker 4 | // 5 | // Author: Serge Lidin (slidin@microsoft.com) 6 | // 7 | // Version: 1.0 (April 05,2002) 8 | // 9 | // This source code is provided "as is" without any warranties of any kind 10 | // 11 | // =============================================================== 12 | #include "windows.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // Used for parsing the command line arguments 19 | WCHAR* EqualOrColon(WCHAR* szArg) 20 | { 21 | WCHAR* pchE = wcschr(szArg,L'='); 22 | WCHAR* pchC = wcschr(szArg,L':'); 23 | WCHAR* ret; 24 | if(pchE == NULL) ret = pchC; 25 | else if(pchC == NULL) ret = pchE; 26 | else ret = (pchE < pchC)? pchE : pchC; 27 | return ret; 28 | } 29 | 30 | // Used for eliminating the leading spaces of a text line 31 | WCHAR* SkipBlanks(WCHAR* wz) 32 | { 33 | WCHAR* wch; 34 | for(wch = wz; *wch == ' '; wch++); // ILDASM guarantees the strings are terminated 35 | return wch; 36 | } 37 | 38 | // Used in search for resolution scopes and data labels 39 | BOOL NotCommentOrLiteral(WCHAR* wzString, WCHAR* wzPtr) 40 | { 41 | BOOL fIsComment=FALSE; 42 | BOOL fIsLiteral=FALSE; 43 | for(WCHAR* wz=wzString; wz> 6]; 76 | wzRet[1] = wzSymbol[i & 0x3F]; 77 | wzRet[2] = 0; 78 | return wzRet; 79 | } 80 | 81 | extern "C" int _cdecl wmain(int argc, WCHAR *argv[]) 82 | { 83 | WCHAR wzOutputFilename[512]; 84 | WCHAR *pwzInputFile[1024]; 85 | WCHAR *pwzModuleName[1024]; 86 | unsigned i, j; 87 | unsigned NumFiles = 0; 88 | WCHAR szOpt[4]; 89 | int exitval=1; 90 | bool bLogo = TRUE; 91 | BOOL fAutoResFile = FALSE; 92 | BOOL fDeleteIntermediateFiles = TRUE; 93 | WCHAR wz[4096]; 94 | WCHAR wzOther[4096]; 95 | WCHAR *wzSubsystem=NULL, *wzComImageFlags=NULL, *wzFileAlignment=NULL, *wzDebug=NULL, 96 | *wzBaseAddress=NULL,*wzKeySourceName=NULL,*wzResFile=NULL; 97 | DWORD dwVTEntryBase=0,dwVTEntries,dwExportBase=0,dwExports; 98 | 99 | OSVERSIONINFO osVerInfo; 100 | 101 | osVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 102 | if (!(GetVersionEx(&osVerInfo) && osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)) 103 | { 104 | fprintf(stderr,"The ILLINK utility is not intended for Windows 9x and ME systems\n"); 105 | exit(1); 106 | } 107 | 108 | memset(wzOutputFilename,0,sizeof(wzOutputFilename)); 109 | 110 | if (argc < 3 || ! wcscmp(argv[1], L"/?") || ! wcscmp(argv[1],L"-?")) 111 | { 112 | printf("\nMicrosoft (R) .NET Framework IL Linker. Version 1.0\n\n"); 113 | ErrorExit: 114 | printf("\n\nUsage: illink /out= []"); 115 | printf("\n\n The names of files being linked must maintain casing of respective"); 116 | printf("\n modules or assemblies. For example, if you link assembly System.Windows.Forms,"); 117 | printf("\n specify it as System.Windows.Forms.dll"); 118 | printf("\n\nOptions:"); 119 | printf("\n/RESOURCE= Link the specified resource file (*.res) \n\t\t\tinto resulting .exe or .dll"); 120 | printf("\n/DEBUG Include debug information"); 121 | printf("\n/PRESERVE Don't delete the intermediate .IL files on exit"); 122 | printf("\n/KEY= Link with strong signature \n\t\t\t( contains private key)"); 123 | printf("\n/KEY=@ Link with strong signature \n\t\t\t( is the private key source name)"); 124 | printf("\n/SUBSYSTEM= Set Subsystem value in the NT Optional header"); 125 | printf("\n/FLAGS= Set CLR ImageFlags value in the CLR header"); 126 | printf("\n/ALIGNMENT= Set FileAlignment value in the NT Optional header"); 127 | printf("\n/BASE= Set ImageBase value in the NT Optional header"); 128 | printf("\n\nKey may be '-' or '/'\nOptions are recognized by first 3 characters\n'=' and ':' in options are interchangeable\n\n"); 129 | if(argc >= 3) exitval = 0; 130 | exit(exitval); 131 | } 132 | 133 | //------------------------------------------------- 134 | for (i = 1; i < (unsigned)argc; i++) 135 | { 136 | if((argv[i][0] == L'/') || (argv[i][0] == L'-')) 137 | { 138 | wcsncpy(szOpt,&argv[i][1],3); 139 | szOpt[3] = 0; 140 | if (!_wcsicmp(szOpt, L"out")) 141 | { 142 | WCHAR *pStr = EqualOrColon(argv[i]); 143 | if(pStr == NULL) goto ErrorExit; 144 | for(pStr++; *pStr == L' '; pStr++); //skip the blanks 145 | if(wcslen(pStr)==0) goto ErrorExit; //if no file name 146 | wcscpy(wzOutputFilename,pStr); 147 | } 148 | else if (!_wcsicmp(szOpt, L"ali")) wzFileAlignment = argv[i]; 149 | else if (!_wcsicmp(szOpt, L"fla")) wzComImageFlags = argv[i]; 150 | else if (!_wcsicmp(szOpt, L"sub")) wzSubsystem = argv[i]; 151 | else if (!_wcsicmp(szOpt, L"bas")) wzBaseAddress = argv[i]; 152 | else if (!_wcsicmp(szOpt, L"deb")) wzDebug = argv[i]; 153 | else if (!_wcsicmp(szOpt, L"key")) wzKeySourceName = argv[i]; 154 | else if (!_wcsicmp(szOpt, L"res")) wzResFile = argv[i]; 155 | else if (!_wcsicmp(szOpt, L"pre")) fDeleteIntermediateFiles = FALSE; 156 | else 157 | { 158 | fwprintf(stderr,L"Error : Invalid Option: %s", argv[i]); 159 | goto ErrorExit; 160 | } 161 | } 162 | else 163 | { 164 | for(j = 0; j < NumFiles; j++) 165 | { 166 | if(!_wcsicmp(argv[i],pwzInputFile[j])) break; 167 | } 168 | if(j >= NumFiles) 169 | { 170 | WCHAR *wc = wcsrchr(argv[i],'\\'); 171 | if(!wc) wc = wcsrchr(argv[i],':'); 172 | if(!wc) wc = argv[i]; 173 | else wc++; 174 | if(NumFiles >= 1024) 175 | { 176 | fwprintf(stderr,L"Cannot link more than 1024 files.\n"); 177 | exit(1); 178 | } 179 | pwzModuleName[NumFiles] = wc; 180 | pwzInputFile[NumFiles++] = argv[i]; 181 | } 182 | else 183 | fwprintf(stderr,L"Duplicate input file %s, ignored.\n",argv[i]); 184 | } 185 | 186 | } 187 | if((NumFiles == 0)||(wzOutputFilename[0] == 0)) goto ErrorExit; 188 | if(NumFiles == 1) // trivial case: nothing to link 189 | { 190 | wcscpy(wz,L"copy "); 191 | wcscat(wz,pwzInputFile[0]); 192 | wcscat(wz,L" "); 193 | wcscat(wz,wzOutputFilename); 194 | _wsystem(wz); 195 | exit(0); 196 | } 197 | 198 | BOOL fAssemblyDeclared = FALSE; 199 | BOOL fModuleDeclared = FALSE; 200 | FILE *pTempIL, *pOutIL,*pOutHeader, *pOut; 201 | system("mkdir illinktempdir"); 202 | 203 | pOutHeader = fopen("illinktempdir\\illinktempoutheader.il","wb"); 204 | if(pOutHeader==NULL) 205 | { 206 | fprintf(stderr,"Failed to open intermediate header file.\n"); 207 | exit(1); 208 | } 209 | fwrite("\377\376",2,1,pOutHeader); // UNICODE signature 210 | pOutIL = fopen("illinktempdir\\illinktempoutfile.il","wb"); 211 | if(pOutIL==NULL) 212 | { 213 | fprintf(stderr,"Failed to open intermediate output file.\n"); 214 | fclose(pOutHeader); 215 | DeleteFileA("illinktempoutheader.il"); 216 | exit(1); 217 | } 218 | //fwrite("\377\376",2,1,pOutIL); // UNICODE signature 219 | SetCurrentDirectoryA(".\\illinktempdir"); 220 | for(i = 0; i < NumFiles; i++) 221 | { 222 | // 1. Disassemble the input file to temp. il file 223 | wcscpy(wz,L"ildasm /nob /uni /out:illinktempinfile.il "); 224 | if(wzDebug) wcscat(wz,L"/lin "); 225 | if(wcschr(pwzInputFile[i],'\\')==NULL) wcscat(wz,L"..\\"); 226 | wcscat(wz,pwzInputFile[i]); 227 | _wsystem(wz); 228 | 229 | // 2. Pump temp. il file to output il file, editing as necessary 230 | pTempIL = fopen("illinktempinfile.il","rb"); 231 | if(pTempIL == NULL) 232 | { 233 | fprintf(stderr,"Failed to open intermediate input file. Possible failure disassembling %s\n",pwzInputFile[i]); 234 | fclose(pOutIL); 235 | DeleteFileA("illinktempoutfile.il"); 236 | fclose(pOutHeader); 237 | DeleteFileA("illinktempoutheader.il"); 238 | goto CleanUpAndExit; 239 | } 240 | // If the /RESOURCE= option is not specified, try using the .res file of first linked module 241 | if((i==0)&&(wzResFile==NULL)) 242 | { 243 | pOut = fopen("illinktempinfile.res","rb"); 244 | if(pOut) 245 | { 246 | fclose(pOut); 247 | system("copy illinktempinfile.res illinkautores32.res"); 248 | fAutoResFile = TRUE; 249 | } 250 | } 251 | DeleteFileA("illinktempinfile.res"); 252 | 253 | dwVTEntries = 0; 254 | dwExports = 0; 255 | 256 | fgetws(wz,4095,pTempIL); 257 | fgetws(wz,4095,pTempIL); 258 | fgetws(wz,4095,pTempIL); 259 | 260 | pOut = pOutHeader; // Manifest and forward class decls go to header file 261 | memset(wz,0,sizeof(wz)); 262 | while(fgetws(wz,4095,pTempIL)) 263 | { 264 | WCHAR* wch = SkipBlanks(wz); 265 | 266 | // 2.1. Skip the blank and comment lines 267 | if(*wch == '\r') continue; 268 | if((*wch == '/')&&(*(wch+1) == '/')) 269 | { 270 | if(wcsstr(wch,L"// =============== GLOBAL FIELDS AND METHODS")) pOut = pOutIL; 271 | // Globals, class members and data go to IL file 272 | continue; 273 | } 274 | 275 | // 2.2. Skip duplicate assembly decls 276 | if(!wcsncmp(wch,L".assembly ",10)) 277 | { 278 | BOOL fSkipToClosingBraceAndContinue=FALSE; 279 | if(wcsncmp(wch,L".assembly extern",16)) 280 | { 281 | if(fAssemblyDeclared) fSkipToClosingBraceAndContinue = TRUE; 282 | else fAssemblyDeclared = TRUE; 283 | } 284 | else 285 | { 286 | WCHAR *wzAssemblyName = wzOther; 287 | for(j = 0; j < NumFiles; j++) 288 | { 289 | wcscpy(wzAssemblyName,pwzModuleName[j]); 290 | wch = wcsrchr(wzAssemblyName,'.'); 291 | if(wch) *wch = 0; 292 | wch = wcsstr(wz,wzAssemblyName); 293 | if(wch) 294 | { 295 | wch += wcslen(wzAssemblyName); 296 | if((*wch == ' ')||(*wch == '\r')||(*wch == '\n')) 297 | { 298 | fSkipToClosingBraceAndContinue = TRUE; 299 | break; 300 | } 301 | } 302 | } 303 | } 304 | if(fSkipToClosingBraceAndContinue) 305 | { 306 | while(fgetws(wz,4095,pTempIL)) 307 | { 308 | wch = SkipBlanks(wz); 309 | if(*wch == '}') break; 310 | } 311 | } 312 | else fputws(wz,pOut); 313 | 314 | } 315 | // 2.3. Skip module ref decls pertinent to linked files 316 | else if(!wcsncmp(wch,L".module ",8)) 317 | { 318 | if(!wcsncmp(wch,L".module extern ",15)) 319 | { 320 | for(j = 0; j < NumFiles; j++) 321 | { 322 | wch = wcsstr(wz,pwzModuleName[j]); 323 | if(wch) break; 324 | } 325 | if(j >= NumFiles) fputws(wz,pOut); 326 | } 327 | else 328 | { 329 | if(!fModuleDeclared) 330 | { 331 | fModuleDeclared = TRUE; 332 | fputws(wz,pOut); 333 | } 334 | } 335 | } 336 | // 2.4. Skip file decls pertinent to linked files 337 | else if(!wcsncmp(wch,L".file ",6)) 338 | { 339 | for(j = 0; j < NumFiles; j++) 340 | { 341 | wch = wcsstr(wz,pwzModuleName[j]); 342 | if(wch) break; 343 | } 344 | if(j < NumFiles) // .file can be followed by .entrypoint and .hash = () 345 | { 346 | if(fgetws(wz,4095,pTempIL)) 347 | { 348 | wch = SkipBlanks(wz); 349 | if(!wcsncmp(wch,L".entrypoint",11)) 350 | { 351 | wch = fgetws(wz,4095,pTempIL); 352 | if(wch) wch = SkipBlanks(wz); 353 | } 354 | if(!wcsncmp(wch,L".hash = (",9)) 355 | { 356 | do 357 | { 358 | wch = wcsstr(wz,L"//"); 359 | if(wch) *wch = 0; // cut off the comments which may contain anything 360 | if(wcschr(wz,')')) break; 361 | } 362 | while(fgetws(wz,4095,pTempIL)); 363 | } 364 | else fputws(wz,pOut); 365 | } 366 | } 367 | else fputws(wz,pOut); 368 | } 369 | // 2.5. Skip exported type decls pertinent to linked files 370 | else if(!wcsncmp(wch,L".class extern ",14)) 371 | { 372 | WCHAR *wzNext = &wzOther[4000]; // next line is only opening brace 373 | WCHAR *wzAfterNext = wzOther; // implementation 374 | BOOL fWriteLines = TRUE; 375 | if(!fgetws(wzNext,95,pTempIL)) continue; 376 | if(!fgetws(wzAfterNext,3999,pTempIL)) continue; 377 | wch = SkipBlanks(wzAfterNext); 378 | if(!wcsncmp(wch,L".file ",6)) 379 | { 380 | for(j = 0; j < NumFiles; j++) 381 | { 382 | wch = wcsstr(wz,pwzModuleName[j]); 383 | if(wch) break; 384 | } 385 | if(j < NumFiles) 386 | { 387 | while(fgetws(wz,4095,pTempIL)) 388 | { 389 | wch = SkipBlanks(wz); 390 | if(*wch == '}') break; 391 | } 392 | fWriteLines = FALSE; 393 | } 394 | } 395 | if(fWriteLines) 396 | { 397 | fputws(wz,pOut); 398 | fputws(wzNext,pOut); 399 | fputws(wzAfterNext,pOut); 400 | } 401 | } 402 | else // No line skipping any more, in-line surgery 403 | { 404 | // 2.6. Shift .vtentry entry number, leave slot number as is 405 | if(!wcsncmp(wch,L".vtentry ",9)) 406 | { 407 | DWORD dwVTEntry; 408 | WCHAR* wch1; 409 | wch += 9; 410 | wch1 = wcschr(wch,':'); // can't really be NULL -- it's ILDASM output 411 | if(wch1) 412 | { 413 | *wch1 = 0; 414 | swscanf(wch,L"%d",&dwVTEntry); 415 | if(dwVTEntry > dwVTEntries) dwVTEntries = dwVTEntry; 416 | if(dwVTEntryBase) 417 | { 418 | dwVTEntry += dwVTEntryBase; 419 | wcscpy(wzOther,wch1+1); 420 | swprintf(wch,L"%d :",dwVTEntry); 421 | wcscat(wz,wzOther); 422 | } 423 | else *wch1 = ':'; 424 | } 425 | 426 | } 427 | // 2.7. Shift .export number 428 | else if(!wcsncmp(wch,L".export [",9)) 429 | { 430 | DWORD dwExport; 431 | WCHAR* wch1; 432 | wch += 9; 433 | wch1 = wcschr(wch,']'); // can't really be NULL -- it's ILDASM output 434 | if(wch1) 435 | { 436 | *wch1 = 0; 437 | swscanf(wch,L"%d",&dwExport); 438 | if(dwExport > dwExports) dwExports = dwExport; 439 | if(dwExportBase) 440 | { 441 | dwExport += dwExportBase; 442 | wcscpy(wzOther,wch1+1); 443 | swprintf(wch,L"%d]",dwExport); 444 | wcscat(wz,wzOther); 445 | } 446 | else *wch1 = ']'; 447 | } 448 | 449 | } 450 | 451 | // 2.8. Remove class ref res.scopes pertinent to linked files 452 | for(j = 0; j < NumFiles; j++) 453 | { 454 | WCHAR *wzPattern = wzOther; 455 | WCHAR *wcopen=NULL, *wcclose=wz; 456 | wcscpy(wzPattern,pwzModuleName[j]); 457 | wch = wcsrchr(wzPattern,'.'); 458 | if(wch) *wch = 0; // off with the extension 459 | while((wcopen=wcschr(wcclose,'['))&&(wcclose=wcschr(wcopen,']'))) 460 | { 461 | if(NotCommentOrLiteral(wz,wcopen)) 462 | { 463 | if((wch = wcsstr(wcopen,wzPattern))&&(wch < wcclose)) 464 | { 465 | wcclose++; 466 | if(*wcclose == ':') wcclose+=2; 467 | wcscpy(wcopen,wcclose); 468 | wcclose = wcopen+1; 469 | } 470 | } 471 | } 472 | } 473 | // 2.9. Modify data labels 474 | while((wch = wcsstr(wz,L" D_00"))||(wch = wcsstr(wz,L" T_00"))) 475 | { 476 | if(NotCommentOrLiteral(wz,wch)) 477 | { 478 | wcscpy(wch+2,EncodeInt(i)); 479 | *(wch+4) = '0'; 480 | } 481 | } 482 | fputws(wz,pOut); 483 | } 484 | // 485 | memset(wz,0,sizeof(wz)); 486 | } // end while(fgetws(wz,4095,pTempIL)) 487 | fclose(pTempIL); 488 | DeleteFileA("illinktempinfile.il"); 489 | dwVTEntryBase += dwVTEntries; 490 | dwExportBase += dwExports; 491 | } // end for(i = 0; i < NumFiles; i++) 492 | 493 | // 3. Close the output il file and assemble it 494 | fclose(pOutHeader); 495 | fclose(pOutIL); 496 | _wsystem(L"copy /b illinktempoutheader.il+illinktempoutfile.il illinktemptotal.il"); 497 | wcscpy(wz,L"ilasm illinktemptotal.il /qui /out:"); 498 | if(wcschr(wzOutputFilename,'\\')==NULL) wcscat(wz,L"..\\"); 499 | wcscat(wz,wzOutputFilename); 500 | if(wcsstr(wzOutputFilename,L".dll")||wcsstr(wzOutputFilename,L".DLL")) wcscat(wz,L" /dll"); 501 | if(wzDebug) { wcscat(wz,L" "); wcscat(wz,wzDebug); } 502 | if(wzSubsystem) { wcscat(wz,L" "); wcscat(wz,wzSubsystem); } 503 | if(wzComImageFlags) { wcscat(wz,L" "); wcscat(wz,wzComImageFlags); } 504 | if(wzFileAlignment) { wcscat(wz,L" "); wcscat(wz,wzFileAlignment); } 505 | if(wzBaseAddress) { wcscat(wz,L" "); wcscat(wz,wzBaseAddress); } 506 | if(wzKeySourceName) { wcscat(wz,L" "); wcscat(wz,wzKeySourceName); } 507 | if(wzResFile) { wcscat(wz,L" "); wcscat(wz,wzResFile); } 508 | else if(fAutoResFile) wcscat(wz,L" /res:illinkautores32.res"); 509 | 510 | wcscat(wz,L" > ilasm.log"); 511 | 512 | _wsystem(wz); 513 | SetCurrentDirectoryA("..\\"); 514 | 515 | exitval = 0; 516 | CleanUpAndExit: 517 | // Temporary files and directory removal 518 | if(fDeleteIntermediateFiles) 519 | { 520 | system("del illinktempdir\\*.* /Q"); 521 | system("rmdir illinktempdir"); 522 | } 523 | exit(exitval); 524 | } 525 | -------------------------------------------------------------------------------- /Samples/illink_readme.txt: -------------------------------------------------------------------------------- 1 | 2 | ILLINK -- Microsoft (R) .NET Framework IL Linker, Version 1.0 3 | -------------------------------------------------------------- 4 | 5 | 6 | 7 | The ILLINK utility is intended for linking multiple managed modules or assemblies into a single 8 | module or assembly. The utility relies on round-tripping using the ILASM and ILDASM utilities and 9 | is not able to link the modules containing embedded native code. Only pure-IL modules, such as 10 | those generated by C#, VB.NET or ILASM compilers, can be linked. 11 | 12 | The general principle of the ILLINK functioning is the corrective round-tripping. The modules 13 | being linked are disassembled into IL Assembly language source text, the text is processed and 14 | then re-assembled into a single module. The text processing includes the following: 15 | - removal of multiple assembly and module declarations; 16 | - removal of assembly references, module references and file references pertinent to the modules 17 | being linked; 18 | - removal of exported type declarations pertinent to the modules being linked; 19 | - removal of class reference resolution scopes pertinent to the modules being linked; 20 | - renaming of data labels in order to avoid same-name labels originating from different modules 21 | being linked; 22 | - renumbering of the VTableFixup table entries and export ordinals for the managed methods exposed 23 | as unmanaged exports. 24 | 25 | The following special cases are not covered by the ILLINK processing and will lead to link failure: 26 | - presence of same-name, same-signature global methods or fields in the modules being linked; 27 | - presence of the classes with identical full names in the modules being linked; such classes are 28 | interpreted by the ILASM as augmentation of the same class, and the result is unpredictable. 29 | 30 | The ILLINK is a console application. The command line structure is as follows: 31 | illink /out= [] 32 | 33 | The names of files being linked must maintain casing of respective modules or assemblies. For 34 | example, if you link assembly System.Windows.Forms, specify it as System.Windows.Forms.dll 35 | 36 | Options: 37 | /RESOURCE= -- Link the specified Win32 resource file (*.res) into the resulting module; 38 | If this option is not specified, ILLINK will use the resource file 39 | (if any) extracted from the first module being linked. 40 | /DEBUG -- Include debug information. If the modules being linked have the debug 41 | information (local variable names, line-to-code bindings, etc.), and 42 | are linked with /DEBUG option, the resulting module will retain the 43 | original debug information; 44 | /PRESERVE -- Don't delete the intermediate files and temporary directory 45 | 'illinktempdir'on exit; 46 | /KEY= -- Link with strong name signature ( contains private key); 47 | /KEY=@ -- Link with strong name signature ( is the private key 48 | source name); 49 | /SUBSYSTEM= -- Set Subsystem value in the NT Optional header; 50 | /FLAGS= -- Set CLR ImageFlags value in the CLR header; 51 | /ALIGNMENT= -- Set FileAlignment value in the NT Optional header; 52 | /BASE= -- Set ImageBase value in the NT Optional header. 53 | 54 | Option key may be '-' or '/'. Options are recognized by first 3 characters and are case-insensitive. 55 | Symbols '=' and ':' in options are interchangeable. Thus, the following options are equivalent: 56 | /RESOURCE=MyRes.res 57 | /RES=MyRes.res 58 | -res:MyRes.res 59 | 60 | 61 | -------------------------------------------------------------------------------- /Samples/overloads.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { } 2 | .assembly overloads{ } 3 | .module overloads.exe 4 | 5 | #define DEFLT_CTOR 6 | ".method public specialname void .ctor(){ldarg.0; call instance void .base::.ctor(); ret}" 7 | 8 | .typedef method void [mscorlib]System.Console::WriteLine(string) as PrintString 9 | 10 | 11 | .class public A 12 | { 13 | DEFLT_CTOR 14 | .method public void Foo() 15 | { 16 | ldstr "instance void Foo" 17 | call PrintString 18 | ret 19 | } 20 | .method public static void Foo() 21 | { 22 | ldstr "static void Foo" 23 | call PrintString 24 | ret 25 | } 26 | .method public vararg void Foo() 27 | { 28 | ldstr "instance vararg void Foo" 29 | call PrintString 30 | ret 31 | } 32 | .method public static vararg void Foo() 33 | { 34 | ldstr "static vararg void Foo" 35 | call PrintString 36 | ret 37 | } 38 | .method public int32 Foo() 39 | { 40 | ldstr "instance int32 Foo" 41 | call PrintString 42 | ldc.i4.1 43 | ret 44 | } 45 | .method public static int32 Foo() 46 | { 47 | ldstr "static int32 Foo" 48 | call PrintString 49 | ldc.i4.1 50 | ret 51 | } 52 | } 53 | .method public static void Exec() 54 | { 55 | .entrypoint 56 | newobj instance void A::.ctor() // Create instance of A 57 | 58 | dup // We need 3 instance pointers 59 | dup // On stack for 3 calls 60 | 61 | 62 | call instance void A::Foo() 63 | call instance vararg void A::Foo() 64 | call instance int32 A::Foo() 65 | pop 66 | call void A::Foo() 67 | call vararg void A::Foo() 68 | call int32 A::Foo() 69 | pop 70 | ret 71 | } 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Samples/override.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { } 2 | .assembly override { } 3 | .module override.exe 4 | 5 | .class public A 6 | { 7 | .method public specialname void .ctor() 8 | { 9 | ldarg.0 10 | call instance void [mscorlib]System.Object::.ctor() 11 | ret 12 | } 13 | .method public void Foo() 14 | { 15 | ldstr "A::Foo" 16 | call void [mscorlib]System.Console::WriteLine(string) 17 | ret 18 | } 19 | .method public virtual void Bar() 20 | { 21 | ldstr "A::Bar" 22 | call void [mscorlib]System.Console::WriteLine(string) 23 | ret 24 | } 25 | .method public virtual void Baz() 26 | { 27 | ldstr "A::Baz" 28 | call void [mscorlib]System.Console::WriteLine(string) 29 | ret 30 | } 31 | 32 | } 33 | 34 | .class public B extends A 35 | { 36 | .method public specialname void .ctor() 37 | { 38 | ldarg.0 39 | call instance void A::.ctor() 40 | ret 41 | } 42 | .method public void Foo() 43 | { 44 | ldstr "B::Foo" 45 | call void [mscorlib]System.Console::WriteLine(string) 46 | ret 47 | } 48 | .method public virtual void BarBaz() 49 | { 50 | .override A::Bar 51 | .override A::Baz 52 | ldstr "B::BarBaz" 53 | call void [mscorlib]System.Console::WriteLine(string) 54 | ret 55 | } 56 | } 57 | 58 | .class public C extends B 59 | { 60 | .method public specialname void .ctor() 61 | { 62 | ldarg.0 63 | call instance void B::.ctor() 64 | ret 65 | } 66 | // no overrides, let's inherit everything from B 67 | } 68 | 69 | 70 | .method public static void Exec() 71 | { 72 | .entrypoint 73 | newobj instance void B::.ctor() // create instance of derived class 74 | castclass class A // cast it to base class 75 | 76 | dup // we need 3 instance pointers 77 | dup // on stack for 3 calls 78 | 79 | call instance void A::Foo() 80 | callvirt instance void A::Bar() 81 | callvirt instance void A::Baz() 82 | 83 | //------------------------------------------------------------------- 84 | 85 | newobj instance void C::.ctor() // create instance of derived class 86 | castclass class A // cast it to "grandparent" 87 | 88 | dup // we need 3 instance pointers 89 | dup // on stack for 3 calls 90 | 91 | call instance void A::Foo() 92 | callvirt instance void A::Bar() 93 | callvirt instance void A::Baz() 94 | 95 | ret 96 | } 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Samples/override_v2.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { } 2 | .assembly override { } 3 | .module override.exe 4 | #define DEFLT_CTOR ".method public specialname void .ctor(){ ldarg.0; call instance void .base::.ctor(); ret}" 5 | .class public A 6 | { 7 | DEFLT_CTOR 8 | .method public void Foo() 9 | { 10 | ldstr "A::Foo" 11 | call void [mscorlib]System.Console::WriteLine(string) 12 | ret 13 | } 14 | .method public virtual void Bar() 15 | { 16 | ldstr "A::Bar" 17 | call void [mscorlib]System.Console::WriteLine(string) 18 | ret 19 | } 20 | .method public virtual void Baz() 21 | { 22 | ldstr "A::Baz" 23 | call void [mscorlib]System.Console::WriteLine(string) 24 | ret 25 | } 26 | 27 | } 28 | 29 | .class public B extends A 30 | { 31 | DEFLT_CTOR 32 | .method public void Foo() 33 | { 34 | ldstr "B::Foo" 35 | call void [mscorlib]System.Console::WriteLine(string) 36 | ret 37 | } 38 | .method public virtual void BarBaz() 39 | { 40 | .override A::Bar 41 | .override A::Baz 42 | ldstr "B::BarBaz" 43 | call void [mscorlib]System.Console::WriteLine(string) 44 | ret 45 | } 46 | } 47 | 48 | .class public C extends B 49 | { 50 | DEFLT_CTOR 51 | // no overrides, let's inherit everything from B 52 | } 53 | 54 | 55 | .method public static void Exec() 56 | { 57 | .entrypoint 58 | newobj instance void B::.ctor() // create instance of derived class 59 | castclass class A // cast it to base class 60 | 61 | dup // we need 3 instance pointers 62 | dup // on stack for 3 calls 63 | 64 | call instance void A::Foo() 65 | callvirt instance void A::Bar() 66 | callvirt instance void A::Baz() 67 | 68 | //------------------------------------------------------------------- 69 | 70 | newobj instance void C::.ctor() // create instance of derived class 71 | castclass class A // cast it to "grandparent" 72 | 73 | dup // we need 3 instance pointers 74 | dup // on stack for 3 calls 75 | 76 | call instance void A::Foo() 77 | callvirt instance void A::Bar() 78 | callvirt instance void A::Baz() 79 | 80 | ret 81 | } 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Samples/privatector.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { auto } 2 | .assembly privatector {} 3 | .module privatector.exe 4 | 5 | .typedef [mscorlib]System.Console as TTY 6 | 7 | #define PRIV_DEFLT_CTOR 8 | ".method private specialname void .ctor(){ldarg.0; call instance void .base::.ctor(); ret;}" 9 | 10 | .class public NoCtor 11 | { 12 | PRIV_DEFLT_CTOR 13 | .method public void DoSomething() 14 | { 15 | ldarg.0 16 | pop 17 | ldstr "NoCtor::DoSomething()" 18 | call void TTY::WriteLine(string) 19 | ret 20 | } 21 | .method public static class NoCtor New() 22 | { 23 | newobj instance void .this::.ctor() 24 | ret 25 | } 26 | } 27 | 28 | .method public static void Exec() 29 | { 30 | .entrypoint 31 | .locals init(class NoCtor nc) 32 | 33 | // Create the instance 34 | call class NoCtor NoCtor::New() 35 | stloc.0 36 | 37 | // Use the instance 38 | ldloc.0 39 | call instance void NoCtor::DoSomething() 40 | 41 | ret 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /Samples/virt_not.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { } 2 | .assembly virt_not { } 3 | .module virt_not.exe 4 | 5 | .class public A 6 | { 7 | .method public specialname void .ctor() 8 | { 9 | ldarg.0 10 | call instance void [mscorlib]System.Object::.ctor() 11 | ret 12 | } 13 | .method public void Foo() 14 | { 15 | ldstr "A::Foo" 16 | call void [mscorlib]System.Console::WriteLine(string) 17 | ret 18 | } 19 | .method public virtual void Bar() 20 | { 21 | ldstr "A::Bar" 22 | call void [mscorlib]System.Console::WriteLine(string) 23 | ret 24 | } 25 | .method public virtual void Baz() 26 | { 27 | ldstr "A::Baz" 28 | call void [mscorlib]System.Console::WriteLine(string) 29 | ret 30 | } 31 | 32 | } 33 | 34 | .class public B extends A 35 | { 36 | .method public specialname void .ctor() 37 | { 38 | ldarg.0 39 | call instance void A::.ctor() 40 | ret 41 | } 42 | .method public void Foo() 43 | { 44 | ldstr "B::Foo" 45 | call void [mscorlib]System.Console::WriteLine(string) 46 | ret 47 | } 48 | .method public virtual void Bar() 49 | { 50 | ldstr "B::Bar" 51 | call void [mscorlib]System.Console::WriteLine(string) 52 | ret 53 | } 54 | .method public virtual newslot void Baz() 55 | { 56 | ldstr "B::Baz" 57 | call void [mscorlib]System.Console::WriteLine(string) 58 | ret 59 | } 60 | 61 | } 62 | 63 | 64 | .method public static void Exec() 65 | { 66 | .entrypoint 67 | newobj instance void B::.ctor() // create instance of derived class 68 | castclass class A // cast it to base class 69 | 70 | dup // we need 3 instance pointers 71 | dup // on stack for 3 calls 72 | 73 | call instance void A::Foo() 74 | callvirt instance void A::Bar() 75 | callvirt instance void A::Baz() 76 | 77 | ret 78 | } 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Samples/virt_not2.il: -------------------------------------------------------------------------------- 1 | .assembly extern mscorlib { .locale "fr-CA" auto } 2 | .assembly virt_not2 { } 3 | .module virt_not2.exe 4 | 5 | #define DEFLT_CTOR ".method public specialname void .ctor(){ldarg.0; call instance void .base::.ctor(); ret;}" 6 | 7 | .typedef method void [mscorlib]System.Console::WriteLine(string) as PrintString 8 | 9 | .class public A 10 | { 11 | DEFLT_CTOR 12 | .method public void Foo() 13 | { 14 | ldstr "A::Foo" 15 | call PrintString 16 | ret 17 | } 18 | .method public virtual void Bar() 19 | { 20 | ldstr "A::Bar" 21 | call PrintString 22 | ret 23 | } 24 | .method public virtual void Baz() 25 | { 26 | ldstr "A::Baz" 27 | call PrintString 28 | ret 29 | } 30 | 31 | } 32 | 33 | .class public B extends A 34 | { 35 | DEFLT_CTOR 36 | .method public void Foo() 37 | { 38 | ldstr "B::Foo" 39 | call PrintString 40 | ret 41 | } 42 | .method public virtual void Bar() 43 | { 44 | ldstr "B::Bar" 45 | call PrintString 46 | ret 47 | } 48 | .method public virtual newslot void Baz() 49 | { 50 | ldstr "B::Baz" 51 | call PrintString 52 | ret 53 | } 54 | 55 | } 56 | 57 | 58 | .method public static void Exec() 59 | { 60 | .entrypoint 61 | newobj instance void B::.ctor() // create instance of derived class 62 | castclass class A // cast it to base class 63 | 64 | dup // we need 3 instance pointers 65 | dup // on stack for 3 calls 66 | 67 | call instance void A::Foo() 68 | callvirt instance void A::Bar() 69 | callvirt instance void A::Baz() 70 | 71 | ret 72 | } 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! --------------------------------------------------------------------------------