Common Language Runtime Header

Common Language Runtime Header

The fifteenth directory entry of the PE header contains the RVA and size of the runtime header in the image file. The runtime header, which contains all of the runtime-specific data entries and other information, should reside in a read-only, sharable section of the image file. The ILAsm compiler puts the common language runtime header in the .text section.

Header Structure

The common language runtime header is defined in CorHdr.h—a header file distributed as part of the Microsoft .NET Framework SDK—as follows:

typedef struct IMAGE_COR20_HEADER {     ULONG                   cb;                   USHORT                  MajorRuntimeVersion;     USHORT                  MinorRuntimeVersion;     // Symbol table and startup information     IMAGE_DATA_DIRECTORY    MetaData;             ULONG                   Flags;                ULONG                   EntryPointToken;     // Binding information     IMAGE_DATA_DIRECTORY    Resources;     IMAGE_DATA_DIRECTORY    StrongNameSignature;     // Regular fixup and binding information     IMAGE_DATA_DIRECTORY    CodeManagerTable;     IMAGE_DATA_DIRECTORY    VTableFixups;     IMAGE_DATA_DIRECTORY    ExportAddressTableJumps;     IMAGE_DATA_DIRECTORY    ManagedNativeHeader; } IMAGE_COR20_HEADER;

Table 3-6 takes a closer look at the fields of the header.

Table 3-6  Common Language Runtime Header Fields 

Offset

Size

Field

Description

0

4

Cb

Size of the header in bytes.

4

2

MajorRuntimeVersion

Major portion of the minimum version of the runtime required to run the program.

6

2

MinorRuntimeVersion

Minor portion of the version of the runtime required to run the program.

8

8

MetaData

RVA and size of the metadata.

16

4

Flags

Binary flags, discussed in the following section. In ILAsm, this value can be specified explicitly by the directive .corflags <integer value> and/or the command-line option /FLAGS=<integer value>. The command-line option takes precedence over the directive.

20

4

EntryPointToken

Metadata identifier (token) of the entry point for the image file; can be 0 for DLL images. This field identifies a method belonging to this module or a module containing the entry point method.

24

8

Resources

RVA and size of managed resources.

32

8

StrongNameSignature

RVA and size of the hash data for this PE file, used by the loader for binding and versioning.

40

8

CodeManagerTable

RVA and size of the Code Manager table. In the first release of the runtime, this field is reserved and must be set to 0.

48

8

VTableFixups

RVA and size in bytes of an array of virtual table (v-table) fixups. Among current managed compilers, only the MC++ compiler and linker and the ILAsm compiler can produce this array.

56

8

ExportAddressTableJumps

RVA and size of an array of addresses of jump thunks. Among current managed compilers, only the MC++ compiler and linker can produce this table, which allows the export of unmanaged native methods embedded in the managed PE file.

64

8

ManagedNativeHeader

Reserved; set to 0.

Flags Field

The Flags field of the common language runtime header can include one or more of the following flags:

  • COMIMAGE_FLAGS_ILONLY (0x00000001)  The image file contains IL code only, with no embedded native unmanaged code except the startup stub. Because common language runtime aware operating systems (such as Windows XP) ignore the startup stub, for all practical purposes the file can be considered pure-IL. However, using this flag can cause certain ILAsm compiler specific problems when running under Windows XP. If this flag is set, Windows XP ignores not only the startup stub but also the .reloc section. The .reloc section can contain relocations for the beginning and end of the .tls section as well as relocations for what is referred to as data-on-data (that is, data constants that are pointers to other data constants). Among existing managed compilers, only the MC++ compiler and linker and the ILAsm compiler can produce these items. The MC++ compiler and linker never set this flag because the image file they generate is never pure-IL. Currently, the ILAsm compiler is the only one capable of producing pure-IL image files that might require a .reloc section. To resolve this problem, the ILAsm compiler, if TLS-based data or data-on-data is emitted, clears this flag and sets the COMIMAGE_FLAGS_32BITREQUIRED flag instead.

  • COMIMAGE_FLAGS_32BITREQUIRED (0x00000002)  The image file can be loaded only into a 32-bit process. This flag is set when native unmanaged code is embedded in the PE file or when the .reloc section is not empty.

  • COMIMAGE_FLAGS_IL_LIBRARY (0x00000004)  This flag is obsolete and should not be set. Setting it—as the ILAsm compiler allows, using the .corflags directive—will render your module unloadable.

  • COMIMAGE_FLAGS_STRONGNAMESIGNED (0x00000008)  The image file is protected with a strong name signature. The strong name signature includes the public key and the signature hash and is a part of an assembly’s identity, along with the assembly name, version number, and the culture information. This flag is set when the strong name signing procedure is applied to the image file. No compiler, including ILAsm, can set this flag explicitly.

  • COMIMAGE_FLAGS_TRACKDEBUGDATA (0x00010000)  The loader and the JIT (just-in-time) compiler are required to track debug information about the methods.

EntryPointToken Field

The EntryPointToken field of the common language runtime header contains a token (metadata identifier) of either a method definition (MethodDef) or a file reference (File). A MethodDef token identifies a method defined in the module (a managed PE file) as an entry point method. A File token is used in one case only: in the runtime header of the prime module of a multimodule assembly, when the entry point method is defined in another module (identified by the file reference) of this assembly. In this case, the module identified by the file reference must contain the respective MethodDef token in the EntryPointToken field of its runtime header.

EntryPointToken must be specified in runnable executables (EXE files). The ILAsm compiler, for example, does not even try to generate an EXE file if the source code does not define the entry point. The loader imposes limitations on the signature of the entry point method: the method must return an unsigned integer or void, and it must have at most one parameter of type string or string[ ] (vector of strings).

With nonrunnable executables (DLL files), it’s a different story. Pure-IL DLLs don’t need the entry point method defined, and the EntryPointToken field in their runtime headers should be set to 0.

Mixed-code DLLs—DLLs containing IL and embedded native code—generated by the MC++ compiler and linker must run the unmanaged native function DllMain immediately at the DLL invocation in order to perform the initialization necessary for the unmanaged native components of the DLL. The signature of this unmanaged function must be as follows:

int DllMain(HINSTANCE, DWORD, void *);

To be visible from the managed code and the runtime, the function DllMain must be declared as a platform invocation of an embedded native method (local P/Invoke, also known in enlightened circles as IJW—It Just Works). See Chapter 15 for details about the interoperation of managed and unmanaged code.

note

The method referred to by the EntryPointToken field of the common language runtime header has nothing to do with the function to which the AddressOfEntryPoint field of the PE header points. AddressOfEntryPoint always points to the runtime invocation stub, which is invisible to the runtime, is not reflected in metadata, and hence cannot have a token.

VTableFixups Field

The VTableFixups field of the runtime header is a data directory containing the RVA and the size of the image file’s v-table fixup table. When a managed method must be called from unmanaged code, the common language runtime creates a marshaling thunk for it, and the address of this thunk is placed in the respective address table. If the managed method is called from the unmanaged native code embedded in the managed PE file, the thunk address goes to a special internal v-table. If the managed method is exported as unmanaged and is consumed somewhere outside the managed PE file, the address of the respective v-table entry must also go to the Export Address table. At loading time (and in the disk image file), the entries of this v-table contain the respective method tokens.

These v-table fixups represent the initializing information necessary for the runtime to create the thunks and lay out the respective tables. v-table fixup is defined in CorHdr.h as follows:

typedef struct _IMAGE_COR_VTABLEFIXUP {     ULONG       RVA;     USHORT      Count;     USHORT      Type;  } IMAGE_COR_VTABLEFIXUP;

In this definition, RVA points to the location of the v-table slot containing the respective method token(s). Count specifies the number of entries in the slot if multiple implementations of the same method exist, overriding one another. Type is a combination of the following flags, providing the runtime with information about the slot and what to do with it:

  • COR_VTABLE_32BIT (0x01)  Each entry is 32 bits wide.

  • COR_VTABLE_64BIT (0x02)  Each entry is 64 bits wide.

  • COR_VTABLE_FROM_UNMANAGED (0x04)  The thunk created by the common language runtime must provide data marshaling between managed and unmanaged code.

  • COR_VTABLE_CALL_MOST_DERIVED (0x10)  This flag is not currently used.

Obviously, the first two flags are mutually exclusive. The slots of the v-table must follow each other immediately—that is, the v-table must be contiguous.

Because the v-table should be fixed up after the image has been loaded into memory, this table is located in a read/write section. (In contrast, the v-table in an unmanaged image is located in a read-only section.)

Among existing managed compilers, only the MC++ compiler and linker and the ILAsm compiler can define the v-table and its fixups.

StrongNameSignature Field

The StrongNameSignature field of the common language runtime header contains the RVA and size of the strong name hash, which is used by the runtime to establish the authenticity of the image file. After the image file has been created, it is hashed using the public and private encryption keys provided by the producer of the image file, and the resulting hash blob is written into the space allocated inside the image file.

If even a single byte in the image file is subsequently modified, the authenticity check fails and the image file cannot be loaded. The strong name signature does not survive a round-tripping procedure; if you disassemble a strong-named module using the IL Disassembler and then reassemble it, the module must be strong name signed again.

The ILAsm compiler puts the strong name signature in the .text section of the image file.



Inside Microsoft. NET IL Assembler
Inside Microsoft .NET IL Assembler
ISBN: 0735615470
EAN: 2147483647
Year: 2005
Pages: 147
Authors: SERGE LIDIN

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net