PECOFF Headers

PE/COFF Headers

Figure 3-2 illustrates the structure of operating system specific headers of a PE file. The headers include an MS-DOS stub, the PE signature, the COFF header, the PE header, and section headers. All of these components—and the data directory table in the PE header—are discussed in the following sections.

Figure 3-2 The memory layout of operating system specific headers.

MS-DOS Stub and PE Signature

The MS-DOS stub is present in image files only. Placed at the beginning of an image file, it is a valid application that runs under MS-DOS. (Isn’t that exciting!) The default stub prints the message This program cannot be run in DOS mode when the image file is run in MS-DOS. This is probably the least interesting part of OS-specific headers; the only relevant fact is that the MS-DOS stub, at offset 0x3C, contains the file pointer to the PE signature, which allows the operating system to properly execute the image file.

The PE signature that follows the MS-DOS stub is a 4-byte item, identifying the file as a PE format image file. The signature contains the characters P and E, followed by 2 null bytes.

COFF Header

A standard COFF header is located immediately after the PE signature of an image file. The COFF header provides the most general characteristics of a PE/COFF file, applicable to both object and executable files. The structure of the COFF header and the meaning of its fields are shown in Table 3-1.

Table 3-1  The Format of a COFF Header

Offset

Size

Field Name

Description

0

2

Machine

Number identifying the type of target machine. (See Table 3-2.) If the managed PE file is intended for various machine types, this field should be set to IMAGE_FILE_MACHINE_I386 (0x014C).

2

2

NumberOfSections

Number of entries in the section table, which immediately follows the headers.

4

4

TimeDateStamp

Time and date of file creation.

8

4

PointerToSymbolTable

File pointer of the COFF symbol table. Because this table is never used in managed PE files, this field must be set to 0.

12

4

NumberOfSymbols

Number of entries in the COFF symbol table. This field must be set to 0 in managed PE files.

16

2

SizeOfOptionalHeader

Size of the PE header. This field is specific to PE files; it is set to 0 in COFF files.

18

2

Characteristics

Flags indicating the attributes of the file. (See Table 3-3.)

The structure of the standard COFF header is defined in Winnt.h as follows:

typedef struct _IMAGE_FILE_HEADER {     WORD    Machine;     WORD    NumberOfSections;     DWORD   TimeDateStamp;     DWORD   PointerToSymbolTable;     DWORD   NumberOfSymbols;     WORD    SizeOfOptionalHeader;     WORD    Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

The Machine types are also defined in Winnt.h, as listed in Table 3-2.

Table 3-2  The Machine Field Values 

Constant

Value

Description

IMAGE_FILE_MACHINE_UNKNOWN

0

Contents assumed to be applicable to any machine type—for unmanaged PE files only.

IMAGE_FILE_MACHINE_I386

0x014c

Intel 386 or later. For managed PE files, contents are applicable to any machine type.

IMAGE_FILE_MACHINE_R3000

0x0162

MIPS little endian—the least significant byte precedes the most significant byte. 0x0160 big endian—the most significant byte precedes the least significant byte.

IMAGE_FILE_MACHINE_R4000

0x0166

MIPS little endian

IMAGE_FILE_MACHINE_R10000

0x0168

MIPS little endian

IMAGE_FILE_MACHINE_WCEMIPSV2

0x0169

MIPS little endian running Microsoft Windows CE 2

IMAGE_FILE_MACHINE_ALPHA

0x0184

Alpha AXP

IMAGE_FILE_MACHINE_POWERPC

0x01F0

IBM PowerPC little endian

IMAGE_FILE_MACHINE_SH3

0x01a2

SH3 little endian

IMAGE_FILE_MACHINE_SH3E

0x01a4

SH3E little endian

IMAGE_FILE_MACHINE_SH4

0x01a6

SH4 little endian

IMAGE_FILE_MACHINE_ARM

0x01c0

ARM little endian

IMAGE_FILE_MACHINE_THUMB

0x01c2

ARM processor with Thumb decompressor

IMAGE_FILE_MACHINE_IA64

0x0200

Intel IA64

IMAGE_FILE_MACHINE_MIPS16

0x0266

MIPS

IMAGE_FILE_MACHINE_MIPSFPU

0x0366

MIPS with FPU

IMAGE_FILE_MACHINE_MIPSFPU16

0x0466

MIPS16 with FPU

IMAGE_FILE_MACHINE_ALPHA64

0x0284

ALPHA AXP64

IMAGE_FILE_MACHINE_AXP64

0x0284

ALPHA AXP64

tip

As noted in Tables 3-1 and 3-2, the best strategy for a managed PE file is to specify IMAGE_FILE_MACHINE_I386 in the Machine field. Doing so ensures that the PE file will be able to execute on any machine that has the common language runtime installed.

The Characteristics field of a COFF header contains flags that indicate attributes of the PE/COFF file. These flags are defined in Winnt.h as shown in Table 3-3. Notice that the table refers to pure-IL managed PE files; the term pure-IL indicates that the image file contains no embedded native code.

Table 3-3  The Characteristics Field Values 

Flag

Value

Description

IMAGE_FILE_RELOCS_STRIPPED

0x0001

Image file only. This flag indicates that the file contains no base relocations and must be loaded at its preferred base address. In the case of base address conflict, the operating system loader reports an error. This flag should not be set for managed PE files.

IMAGE_FILE_EXECUTABLE_IMAGE

0x0002

Flag indicates that the file is an image file (EXE or DLL). This flag should be set for managed PE files. If it is not set, this generally indicates a linker error.

IMAGE_FILE_LINE_NUMS_STRIPPED

0x0004

COFF line numbers have been removed. This flag should be set for managed PE files because they do not use the debug information embedded in the PE file itself. Instead, the debug information is saved in accompanying program database (PDB) files.

IMAGE_FILE_LOCAL_SYMS_STRIPPED

0x0008

COFF symbol table entries for local symbols have been removed. This flag should be set for managed PE files, for the reason given in the preceding entry.

IMAGE_FILE_AGGRESIVE_WS_TRIM

0x0010

Aggressively trim the working set. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_LARGE_ADDRESS_AWARE

0x0020

Application can handle addresses beyond the 2-GB range. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_BYTES_REVERSED_LO

0x0080

Little endian. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_32BIT_MACHINE

0x0100

Machine is based on 32-bit architecture. This flag is set by the current versions of code generators producing managed PE files.

IMAGE_FILE_DEBUG_STRIPPED

0x0200

Debug information has been removed from the image file.

IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP

0x0400

If the image file is on removable media, copy and run it from the swap file. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_NET_RUN_FROM_SWAP

0x0800

If the image file is on a network, copy and run it from the swap file. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_SYSTEM

0x1000

The image file is a system file (for example, a device driver). This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_DLL

0x2000

The image file is a DLL rather than an EXE. It cannot be directly run.

IMAGE_FILE_UP_SYSTEM_ONLY

0x4000

The image file should be run on a uniprocessor machine only. This flag should not be set for pure-IL managed PE files.

IMAGE_FILE_BYTES_REVERSED_HI

0x8000

Big endian. This flag should not be set for pure-IL managed PE files.

The typical Characteristics value produced by existing code generators—the one employed by the MC++ compiler and linker as well as the one used by all the rest of the managed compilers, including ILAsm—for an EXE image file is 0x010E (IMAGE_FILE_EXECUTABLE_IMAGE IMAGE_FILE_LINE_NUMS_ STRIPPED IMAGE_FILE_LOCAL_SYMS_STRIPPED IMAGE_FILE_32BIT_ MACHINE). For a DLL image file, this value is 0x210E (IMAGE_FILE_ EXECUTABLE_IMAGE IMAGE_FILE_LINE_NUMS_STRIPPED IMAGE_FILE_ LOCAL_SYMS_STRIPPED IMAGE_FILE_32BIT_MACHINE IMAGE_FILE_DLL).

PE Header

The PE header, which immediately follows the COFF header, provides the information for the OS loader. Although this header is sometimes referred to as the optional header, it is optional only in the sense that object files usually don’t contain it. For PE files, this header is mandatory.

The size of the PE header is not fixed. It depends on the number of data directories defined in the header and is specified in the SizeOfOptionalHeader field of the COFF header. The structure of the PE header is defined in Winnt.h as follows:

typedef struct _IMAGE_OPTIONAL_HEADER {     // Standard fields     WORD    Magic;     BYTE    MajorLinkerVersion;     BYTE    MinorLinkerVersion;     DWORD   SizeOfCode;     DWORD   SizeOfInitializedData;     DWORD   SizeOfUninitializedData;     DWORD   AddressOfEntryPoint;     DWORD   BaseOfCode;     DWORD   BaseOfData;     // NT additional fields     DWORD   ImageBase;     DWORD   SectionAlignment;     DWORD   FileAlignment;     WORD    MajorOperatingSystemVersion;     WORD    MinorOperatingSystemVersion;     WORD    MajorImageVersion;     WORD    MinorImageVersion;     WORD    MajorSubsystemVersion;     WORD    MinorSubsystemVersion;     DWORD   Win32VersionValue;     DWORD   SizeOfImage;     DWORD   SizeOfHeaders;     DWORD   CheckSum;     WORD    Subsystem;     WORD    DllCharacteristics;     DWORD   SizeOfStackReserve;     DWORD   SizeOfStackCommit;     DWORD   SizeOfHeapReserve;     DWORD   SizeOfHeapCommit;     DWORD   LoaderFlags;     DWORD   NumberOfRvaAndSizes;     IMAGE_DATA_DIRECTORY          DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

Table 3-4 describes the fields of the PE header.

Table 3-4  PE Header Fields 

Offset

32/64

Size

32/64

Field

Description

0

2

Magic

“Magic number” identifying the state of the image file. Acceptable values are 0x010B for a 32-bit PE file, 0x020B for a 64-bit PE file, and 0x107 for a ROM image file. Managed PE files must have this field set to 0x010B.

2

1

MajorLinkerVersion

Linker major version number. The MC++ compiler and linker set this field to 7; the pure-IL code generator employed by other compilers sets it to 6.

3

1

MinorLinkerVersion

Linker minor version number.

4

4

SizeOfCode

Size of the code section (.text), or the sum of all code sections if multiple code sections exist. The ILAsm compiler always emits the single code section.

8

4

SizeOfInitializedData

Size of the initialized data section (held in the field SizeOfRawData of the respective section header), or the sum of all such sections. The initialized data is defined as specific values, stored in the disk image file.

12

4

SizeOfUninitializedData

Size of the uninitialized data section (.bss), or the sum of all such sections. This data is not part of the disk file and does not have specific values, but the OS loader commits space for the data.

16

4

AddressOfEntryPoint

RVA of the entry point function. For unmanaged DLLs, this can be 0. For managed PE files, this value always points to the common language runtime invocation stub.

20

4

BaseOfCode

RVA of the beginning of the file’s code section(s).

24/-

4/-

BaseOfData

RVA of the beginning of the file’s data section(s).

28/24

4/8

ImageBase

Image’s preferred starting virtual address. In ILAsm, this field can be specified explicitly by the directive .imagebase <integer value> and/or the command-line option /BASE=<integer value>. The command-line option takes precedence over the directive.

32

4

SectionAlignment

Alignment of sections when loaded in memory. This setting must be greater than or equal to the value of the FileAlignment field. The default is the memory page size.

36

4

FileAlignment

Alignment of sections in the disk image file. The value should be a power of 2, from 512 to 64 K. If SectionAlignment is set to less than the memory page size, FileAlignment must match SectionAlignment. In ILAsm, this field can be specified explicitly by the directive .file alignment <integer value> and/or the command-line option /ALIGNMENT= <integer value>. The command-line option takes precedence over the directive.

40

2

MajorOperatingSystemVersion

Major version number of the required OS.

42

2

MinorOperatingSystemVersion

Minor version number of the required OS.

44

2

MajorImageVersion

Major version number of the application.

46

2

MinorImageVersion

Minor version number of the application.

48

2

MajorSubsystemVersion

Major version number of the subsystem.

50

2

MinorSubsystemVersion

Minor version number of the subsystem.

52

4

Win32VersionValue

Reserved.

56

4

SizeOfImage

Size of the image file (in bytes), including all headers. This field must be set to a multiple of the SectionAlignment value.

60

4

SizeOfHeaders

Sum of the sizes of the MS-DOS stub, the COFF header, the PE header, and the section headers, rounded up to a multiple of the FileAlignment value.

64

4

CheckSum

Checksum of the disk image file.

68

2

Subsystem

Subsystem required to run this image file. The values are defined in Winnt.h and are as follows:

  • NATIVE (1)  No subsystem required (for example, a device driver)

  • WINDOWS_GUI (2)  Runs in the Windows GUI subsystem

  • WINDOWS_CUI (3)  Runs in Windows console mode

  • OS2_CUI (5)  Runs in OS/2 1.x console mode

  • POSIX_CUI (7)  Runs in POSIX console mode

  • NATIVE_WINDOWS (8)  The image file is a native Win9x driver

  • WINDOWS_CE_GUI (9)  Runs in the Windows CE GUI subsystem.

In ILAsm, this field can be specified explicitly by the directive .subsystem <integer value> and/or the command-line option /SUBSYSTEM=<integer value>. The command-line option takes precedence over the directive.

70

2

DllCharacteristics

Obsolete, set to 0.

72

4/8

SizeOfStackReserve

Size of virtual memory to reserve for the initial thread’s stack. Only the SizeOfStackCommit field is committed; the rest is available in one-page increments. The default is 1 MB.

76/80

4/8

SizeOfStackCommit

Size of virtual memory initially committed for the initial thread’s stack. The default is one page.

80/88

4/8

SizeOfHeapReserve

Size of virtual memory to reserve for the initial process heap. Only the SizeOfHeapCommit field is committed; the rest is available in one-page increments. The default is 1 MB.

84/96

4/8

SizeOfHeapCommit

Size of virtual memory initially committed for the process heap. The default is one page.

88/104

4

LoaderFlags

Obsolete, set to 0.

92/108

4

NumberOfRvaAndSizes

Number of entries in the DataDirectory array; at least 16. Although it is theoretically possible to emit more than 16 data directories, all existing managed compilers emit exactly 16 data directories, with the sixteenth (last) data directory never used (reserved).

Data Directory Table

The data directory table starts at offset 96 in a 32-bit PE header and at offset 112 in a 64-bit PE header. Each entry in the data directory table contains the relative virtual address and size of a table or a string used by the operating system. The data directory table entry is an 8-byte structure defined in Winnt.h as follows:

typedef struct _IMAGE_DATA_DIRECTORY {     DWORD   VirtualAddress;     DWORD   Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

The first field, named VirtualAddress, is, however, not a virtual address but rather an RVA; it is the address of the table when the image file is loaded into memory, relative to the base address of the image. The RVAs given in this table do not necessarily point to the beginning of a section, and the sections containing specific tables do not necessarily have specific names. The second field is the size in bytes.

Sixteen standard data directories are defined in the data directory table:

  • Export Directory table address and size  The Export Directory table contains information about four other tables, which hold data on unmanaged exports of the PE file. Among managed compilers, only the MC++ compiler and linker and ILAsm are capable of exposing the managed methods exported by a managed PE file as unmanaged exports, to be consumed by an unmanaged caller. See Chapter 15, “Managed and Unmanaged Code Interoperation,” for details.

  • Import table address and size  This table contains data on unmanaged imports consumed by the PE file. Among managed compilers, only the MC++ compiler and linker make any nontrivial use of this table, importing the unmanaged external functions used in the embedded unmanaged native code. Because other compilers, including the ILAsm compiler, do not embed the unmanaged native code in the managed PE files, Import Address tables (IATs) of the files produced by these compilers contain a single entry, that of the runtime entry function.

  • Resource table address and size  Contains unmanaged resources embedded in the PE file; managed resources aren’t part of this data.

  • Exception table address and size  This table contains information on unmanaged exceptions only.

  • Certificate table address and size  The address entry points to a table of attribute certificates, which are not loaded into memory as part of the image file. As such, the first field of this entry is a file pointer rather than an RVA.

  • Base Relocation table address and size

  • Debug data address and size  A managed PE file does not carry embedded debug data, so both entries of this data directory are set to 0.

  • Architecture data address and size

  • Global pointer  RVA of the value to be stored in the global pointer register. The size must be set to 0.

  • TLS table address and size  Among managed compilers, only the MC++ compiler and linker and the ILAsm compiler are able to produce the code that would use the thread local storage data.

  • Load Configuration table address and size

  • Bound Import table address and size

  • Import Address table address and size

  • Delay Import Descriptor address and size

  • Common Language Runtime header address and size

  • Reserved

Section Headers

The table of section headers must immediately follow the PE header. Because the file header has no direct pointer to the section table, the location of this table is calculated as the total size of the file headers plus 1.

The NumberOfSections field of the COFF header defines the number of entries in the section header table. The section header enumeration in the table is one-based, with the order of the sections defined by the linker. The sections follow one another contiguously in the order set in the section header table, with starting RVAs aligned by the value of the SectionAlignment field of the PE header.

A section header is a 40-byte structure defined in Winnt.h as follows:

typedef struct _IMAGE_SECTION_HEADER {     BYTE    Name[8];     union {             DWORD   PhysicalAddress;             DWORD   VirtualSize;     } Misc;     DWORD   VirtualAddress;     DWORD   SizeOfRawData;     DWORD   PointerToRawData;     DWORD   PointerToRelocations;     DWORD   PointerToLinenumbers;     WORD    NumberOfRelocations;     WORD    NumberOfLinenumbers;     DWORD   Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

The fields contained in the IMAGE_SECTION_HEADER structure can be described as follows:

  • Name (8-byte ANSI string)  Represents the name of the section. Section names start with a dot (for instance, .reloc). If the section name contains exactly eight characters, the null terminator is omitted. If the section name has fewer than eight characters, the array Name is padded with null characters. Image files cannot have section names with more than eight characters. In object files, however, section names can be longer. (Imagine a long-winded code generator emitting a section named .myownsectionnobodyelsecouldevergrok.) In this case, the name is placed in the string table, and the field contains the / (slash) character in the first byte, followed by an ANSI string containing a decimal representation of the respective offset in the string table.

  • PhysicalAddress/VirtualSize (4-byte unsigned integer)  In image files, this field holds the actual (unaligned) size in bytes of the code or data in this section.

  • VirtualAddress (4-byte unsigned integer)  Despite its name, this field holds the RVA of the beginning of the section.

  • SizeOfRawData (4-byte unsigned integer)  In an image file, this field holds the size in bytes of the initialized data on disk, rounded up to a multiple of the FileAlignment value specified in the PE header. If SizeOfRawData is less than VirtualSize, the rest of the section is padded with null bytes.

  • PointerToRawData (4-byte unsigned integer)  This field holds a file pointer to the section’s first page. In image files, this value should be a multiple of the FileAlignment value specified in the PE header.

  • PointerToRelocations (4-byte unsigned integer)  This is a file pointer to the beginning of relocation entries for the section. In image files, this field is not used and should be set to 0.

  • PointerToLinenumbers (4-byte unsigned integer)  This field holds a file pointer to the beginning of line-number entries for the section. In managed PE files, the COFF line numbers are stripped and this field must be set to 0.

  • NumberofRelocations (2-byte unsigned integer)  In managed image files, this field should be set to 0.

  • NumberOfLinenumbers (2-byte unsigned integer)  In managed image files, this field should be set to 0.

  • Characteristics (4-byte unsigned integer)  This field specifies the characteristics of an image file and holds a combination of binary flags, described in Table 3-5.

The section Characteristics flags are defined in Winnt.h. Some of these flags are reserved, and some are relevant to object files only. Table 3-5 lists the flags that are valid for PE files.

Table 3-5  The Section Characteristics Flags in PE Files

Flag

Value

Description

IMAGE_SCN_SCALE_INDEX

0x00000001

TLS index is scaled (.tls section only).

IMAGE_SCN_CNT_CODE

0x00000020

Section contains the executable code. In ILAsm compiler generated PE files, only the .text section carries this flag.

IMAGE_SCN_CNT_INITIALIZED_DATA

0x00000040

Section contains initialized data.

IMAGE_SCN_CNT_UNINITIALIZED_DATA

0x00000080

Section contains uninitialized data.

IMAGE_SCN_NO_DEFER_SPEC_EXC

0x00004000

Reset speculative exception handling bits in the type library (TLB) entries for this section.

IMAGE_SCN_LNK_NRELOC_OVFL

0x01000000

Section contains extended relocations.

IMAGE_SCN_MEM_DISCARDABLE

0x02000000

Section can be discarded as needed.

IMAGE_SCN_MEM_NOT_CACHED

0x04000000

Section cannot be cached.

IMAGE_SCN_MEM_NOT_PAGED

0x08000000

Section cannot be paged.

IMAGE_SCN_MEM_SHARED

0x10000000

Section can be shared in memory.

IMAGE_SCN_MEM_EXECUTE

0x20000000

Section can be executed as code. In ILAsm compiler generated PE files, only the .text section carries this flag.

IMAGE_SCN_MEM_READ

0x40000000

Section can be read.

IMAGE_SCN_MEM_WRITE

0x80000000

Section can be written to. In ILAsm compiler generated PE files, only the .sdata and .tls sections carry this flag.

The ILAsm compiler generates the following sections in a PE file:

  • .text  A read-only section containing the common language runtime header, the metadata, the IL code, managed structured exception handling information, and managed resources.

  • .sdata  A read/write section containing data.

  • .reloc  A read-only section containing relocations.

  • .rsrc  A read-only section containing unmanaged resources.

  • .tls  A read/write section containing thread local storage data.



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