6 Special Sections


Typical COFF sections contain code or data that linkers and Win32 loaders process without special knowledge of the sections' contents. The contents are relevant only to the application being linked or executed.

However, some COFF sections have special meanings when found in object files and/or image files. Tools and loaders recognize these sections because they have special flags set in the section header, or because they are pointed to from special locations in the image optional header, or because the section name is "magic": that is, the name indicates a special function of the section. (Even where the section name is not magic, the name is dictated by convention, so we will refer to a name.)

The reserved sections and their attributes are described in the table below, followed by detailed descriptions for a subset of them.

Section Name

Content

Characteristics

.bss

Uninitialized data

IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.data

Initialized data

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.edata

Export tables

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

.idata

Import tables

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.pdata

Exception information

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

.rdata

Read-only initialized data

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

.reloc

Image relocations

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE

.rsrc

Resource directory

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.sdata

GP-relative initialized data

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.sbss

GP-relative uninitialized data

IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.srdata

GP-relative read-only data

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE _SCN_GPREL

.text

Executable code

IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IIMAGE_SCN_MEM_READ

.tls

Thread-local storage

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE

.xdata

Exception information

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

.sxdata

Safe Exception Handler data (x86/object only)

IMAGE_SCN_CNT_INFO Contains the symbol index of each of the exception handlers being referred to by the code in that object file. The symbol can be for an UNDEF symbol or one that is defined in that module.

Some of the sections listed here are marked "(object only)" or "(image only)" to indicate that their special semantics are relevant only for object files or image files, respectively. A section that says "(image only)" may still appear in an object file as a way of getting into the image file, but the section has no special meaning to the linker, only to the image file loader.

6.1 The .debug Section

The .debug section is used in object files to contain compiler-generated debug information, and in image files to contain the total debug information generated. This section describes the packaging of debug information in object and image files. The actual format of Visual C++ debug information is not described here. See the document CV4 Symbolic Debug Information Specification.

The next section describes the format of the debug directory, which can be anywhere in the image. Subsequent sections describe the "groups" in object files that contain debug information.

The default for the linker is that debug information is not mapped into the address space of the image. A .debug section exists only when debug information is mapped in the address space.

6.1.1 Debug Directory (Image Only)

Image files contain an optional "debug directory" indicating what form of debug information is present and where it is. This directory consists of an array of "debug directory entries" whose location and size are indicated in the image optional header.

The debug directory may be in a discardable .debug section (if one exists) or it may be included in any other section in the image file, or not in a section at all.

Each debug directory entry identifies the location and size of a block of debug information. The RVA specified may be 0 if the debug information is not covered by a section header (i.e., it resides in the image file and is not mapped into the run-time address space). If it is mapped, the RVA is its address.

Here is the format of a debug directory entry:

Offset

Size

Field

Description

0

4

Characteristics

A reserved field intended to be used for flags, set to zero for now.

4

4

TimeDateStamp

Time and date the debug data was created.

8

2

MajorVersion

Major version number of the debug data format.

10

2

MinorVersion

Minor version number of the debug data format.

12

4

Type

Format of debugging information: this field enables support of multiple debuggers. See Section 6.1.2, "Debug Type," for more information.

16

4

SizeOfData

Size of the debug data (not including the debug directory itself).

20

4

AddressOfRawData

Address of the debug data when loaded, relative to the image base.

24

4

PointerToRawData

File pointer to the debug data.

6.1.2 Debug Type

The following values are defined for the Debug Type field of the debug directory:

Constant

Value

Description

IMAGE_DEBUG_TYPE_UNKNOWN

0

Unknown value, ignored by all tools.

IMAGE_DEBUG_TYPE_COFF

1

COFF debug information (line numbers, symbol table, and string table). This type of debug information is also pointed to by fields in the file headers.

IMAGE_DEBUG_TYPE_CODEVIEW

2

Visual C++ debug information. The format of the data block is described by the CV7 specification.

IMAGE_DEBUG_TYPE_FPO

3

Frame Pointer Omission (FPO) information. This information tells the debugger how to interpret non-standard stack frames, which use the EBP register for a purpose other than as a frame pointer.

IMAGE_DEBUG_TYPE_MISC

4

 

IMAGE_DEBUG_TYPE_EXCEPTION

5

 

IMAGE_DEBUG_TYPE_FIXUP

6

 

IMAGE_DEBUG_TYPE_OMAP_TO_SRC

7

 

IMAGE_DEBUG_TYPE_OMAP_FROM_SRC

8

 

IMAGE_DEBUG_TYPE_BORLAND

9

 

If Debug Type is set to IMAGE_DEBUG_TYPE_FPO, the debug raw data is an array in which each member describes the stack frame of a function. Not every function in the image file need have FPO information defined for it, even though debug type is FPO. Those functions that do not have FPO information are assumed to have normal stack frames. The format for FPO information is defined as follows:

 
 #define FRAME_FPO   0 #define FRAME_TRAP  1 #define FRAME_TSS   2 typedef struct _FPO_DATA {     DWORD       ulOffStart;            // offset 1st byte of function code     DWORD       cbProcSize;            // # bytes in function     DWORD       cdwLocals;             // # bytes in locals/4     WORD        cdwParams;             // # bytes in params/4     WORD        cbProlog : 8;          // # bytes in prolog     WORD        cbRegs   : 3;          // # regs saved     WORD        fHasSEH  : 1;          // TRUE if SEH in func     WORD        fUseBP   : 1;          // TRUE if EBP has been allocated     WORD        reserved : 1;          // reserved for future use     WORD        cbFrame  : 2;          // frame type } FPO_DATA; 
6.1.3 .debug$F (Object Only)

The data in this section has been superceded in Visual C++ version 7.0 and above by a more extensive set of data that is emitted into a .debug$S subsection. Please see the Visual C++ 8.0 Debugging Information specification for details. There are cases where this FPO data in .debug$F still needs to be used, such as from hand-written assembler code.

Object files can contain .debug$F sections whose contents are one or more FPO_DATA records (Frame Pointer Omission information). See "IMAGE_DEBUG_TYPE_FPO" in table above.

The linker recognizes these .debug$F records. If debug information is being generated, the linker sorts the FPO_DATA records by procedure RVA, and generates a debug directory entry for them.

The compiler should not generate FPO records for procedures that have a standard frame format.

6.1.4 .debug$S (Object Only)

This section contains CV7 symbolic information: a stream of CV7 symbol records as described in the CV7 spec.

6.1.5 .debug$P (Object Only)

This section contains CV7 precompiled type information: a stream of CV type records as described by the CV spec. These are shared types between all of the objects that were compiled using the precompiled header that was generated with this object.

6.1.6 .debug$T (Object Only)

This section contains CV7 type information: a stream of CV7 type records as described in the CV7 spec.

6.1.7 Linker Support for Microsoft Debug Information

To support debug information, the linker:

Gathers all relevant debug data from the .debug$F, debug$S, .debug$P, and .debug$T sections.

Processes that data along with the linker-generated debugging information into the .PDB file, and creates a debug directory entry to refer to it.

6.2 The .drectve Section (Object Only)

A section is a "directive" section if it has the IMAGE_SCN_LNK_INFO flag set in the section header. By convention, such a section also has the name .drectve. The linker removes a .drectve section after processing the information, so the section does not appear in the image file being linked. Note that a section marked with IMAGE_SCN_LNK_INFO that is not named .drectve is ignored and discarded by the linker.

A .drectve section consists of a string of text which can be encoded as ANSI or UTF-8. If the UTF-8 BOM (Byte Order Marker, a three byte prefix, 0xEF, 0xBB, 0xBF) is not present, the directive string is interpreted as ANSI. This string is a series of linker options (each option containing hyphen, option name, and any appropriate attribute) separated by spaces. The .drectve section must not have relocations or line numbers.

6.3 The .edata Section (Image Only)

The export data section, named .edata, contains information about symbols that other images can access through dynamic linking. Exports are generally found in DLLs, but DLLs can import symbols as well.

An overview of the general structure of the export section is described below. The tables described are generally contiguous in the file and present in the order shown (though this is not strictly required). Only the Directory Table and Address Table are necessary for exporting symbols as ordinals. (An ordinal is an export accessed directly as an Export Address Table index.) The Name Pointer Table, Ordinal Table, and Export Name Table all exist to support use of export names.

Table Name

Description

Export Directory Table

A table with just one row (unlike the debug directory). This table indicates the locations and sizes of the other export tables.

Export Address Table

An array of RVAs of exported symbols. These are the actual addresses of the exported functions and data within the executable code and data sections. Other image files can import a symbol by using an index to this table (an ordinal) or, optionally, by using the public name that corresponds to the ordinal if one is defined.

Name Pointer Table

Array of pointers to the public export names, sorted in ascending order.

Ordinal Table

Array of the ordinals that correspond to members of the Name Pointer Table. The correspondence is by position; therefore, the Name Pointer Table and the Ordinal Table must have the same number of members. Each ordinal is an index into the Export Address Table.

Export Name Table

A series of null-terminated ASCII strings. Members of the Name Pointer Table point into this area. These names are the public names through which the symbols are imported and exported; they do not necessarily have to be the same as the private names used within the image file.

When another image file imports a symbol by name, the Name Pointer Table is searched for a matching string. If one is found, the associated ordinal is then determined by looking at the corresponding member in the Ordinal Table (that is, the member of the Ordinal Table with the same index as the string pointer found in the Name Pointer Table). The resulting ordinal is an index into the Export Address Table, which gives the actual location of the desired symbol. Every export symbol can be accessed by an ordinal.

Direct use of an ordinal is therefore more efficient, because it avoids the need to search the Name Pointer Table for a matching string. However, use of an export name is more mnemonic and does not require the user to know the table index for the symbol.

6.3.1 Export Directory Table

The export information begins with the Export Directory Table, which describes the remainder of the export information. The Export Directory Table contains address information that is used to resolve fix-up references to the entry points within this image.

Offset

Size

Field

Description

0

4

Export Flags

A reserved field, set to zero for now.

4

4

Time/Date Stamp

Time and date the export data was created.

8

2

Major Version

Major version number. The major/minor version number can be set by the user.

10

2

Minor Version

Minor version number.

12

4

Name RVA

Address of the ASCII string containing the name of the DLL. Relative to image base.

16

4

Ordinal Base

Starting ordinal number for exports in this image. This field specifies the starting ordinal number for the Export Address Table. Usually set to 1.

20

4

Address Table Entries

Number of entries in the Export Address Table.

24

4

Number of Name Pointers

Number of entries in the Name Pointer Table (also the number of entries in the Ordinal Table).

28

4

Export Address Table RVA

Address of the Export Address Table, relative to the image base.

32

4

Name Pointer RVA

Address of the Export Name Pointer Table, relative to the image base. The table size is given by Number of Name Pointers.

36

4

Ordinal Table RVA

Address of the Ordinal Table, relative to the image base.

6.3.2 Export Address Table

The Export Address Table contains the address of exported entry points and exported data and absolutes. An ordinal number is used as an index into the Export Address Table.

Each entry in the Export Address Table is a field that uses one of two formats, as shown in the following table. If the address specified is not within the export section (as defined by the address and length indicated in the Optional Header), the field is an Export RVA: an actual address in code or data. Otherwise, the field is a Forwarder RVA, which names a symbol in another DLL.

Offset

Size

Field

Description

0

4

Export RVA

Address of the exported symbol when loaded into memory, relative to the image base. For example, the address of an exported function.

0

4

Forwarder RVA

Pointer to a null-terminated ASCII string in the export section, giving the DLL name and the name of the export (for example, "MYDLL..expfunc") or the DLL name and an export (for example, "MYDLL.#27").

A Forwarder RVA exports a definition from some other image, making it appear as if it were being exported by the current image. Thus the symbol is simultaneously imported and exported.

For example, in KERNEL32.DLL in Windows 2000, the export named "HeapAlloc" is forwarded to the string "NTDLL.RtlAllocateHeap". This allows applications to use the Windows 2000-specific module "NTDLL.DLL" without actually containing import references to it. The application's import table references only "KERNEL32.DLL." Therefore, the application is not specific to Windows and can run on any Win32 system.

6.3.3 Export Name Pointer Table

The Export Name Pointer Table is an array of addresses (RVAs) into the Export Name Table. The pointers are 32 bits each and are relative to the Image Base. The pointers are ordered lexically to allow binary searches.

An export name is defined only if the Export Name Pointer Table contains a pointer to it.

6.3.4 Export Ordinal Table

The Export Ordinal Table is an array of 16-bit indexes into the Export Address Table. The ordinals are biased by the Ordinal Base field of the Export Directory Table. In other words, the Ordinal Base must be subtracted from the ordinals to obtain true indexes into the Export Address Table.

The Export Name Pointer Table and the Export Ordinal Table form two parallel arrays, separated to allow natural field alignment. These two tables, in effect, operate as one table, in which the Export Name Pointer "column" points to a public (exported) name, and the Export Ordinal "column" gives the corresponding ordinal for that public name. A member of the Export Name Pointer Table and a member of the Export Ordinal Table are associated by having the same position (index) in their respective arrays.

Thus, when the Export Name Pointer Table is searched and a matching string is found at position i, the algorithm for finding the symbol's address is:

 
 i = Search_ExportNamePointerTable (ExportName); ordinal = ExportOrdinalTable [i]; SymbolRVA = ExportAddressTable [ordinal - OrdinalBase]; 
6.3.5 Export Name Table

The Export Name Table contains the actual string data pointed to by the Export Name Pointer Table. The strings in this table are public names that can be used by other images to import the symbols; these public export names are not necessarily the same as the (private) symbol names that the symbols have in their own image file and source code, although they can be.

Every exported symbol has an ordinal value, which is just the index into the Export Address Table (plus the Ordinal Base value). Use of export names, however, is optional. Some, all, or none of the exported symbols can have export names. For those exported symbols that do have export names, corresponding entries in the Export Name Pointer Table and Export Ordinal Table work together to associate each name with an ordinal.

The structure of the Export Name Table is a series of ASCII strings, of variable length, each null terminated.

6.4 The .idata Section

All image files that import symbols, including virtually all .EXE files, have an .idata section. A typical file layout for the import information follows:

Figure A-3. Typical Import Section Layout

graphics/ap01fig03.gif

6.4.1 Import Directory Table

The import information begins with the Import Directory Table, which describes the remainder of the import information. The Import Directory Table contains address information that is used to resolve fix-up references to the entry points within a DLL image. The Import Directory Table consists of an array of Import Directory Entries, one entry for each DLL the image references. The last directory entry is empty (filled with null values), which indicates the end of the directory table.

Each Import Directory entry has the following format:

Offset

Size

Field

Description

0

4

Import Lookup Table RVA (Characteristics)

Relative virtual address of the Import Lookup Table; this table contains a name or ordinal for each import. (The name "Characteristics" is used in WINNT.H but is no longer descriptive of this field.)

4

4

Time/Date Stamp

Set to zero until bound; then this field is set to the time/data stamp of the DLL.

8

4

Fowarder Chain

Index of first forwarder reference.

12

4

Name RVA

Address of ASCII string containing the DLL name. This address is relative to the image base.

16

4

Import Address Table RVA (Thunk Table)

Relative virtual address of the Import Address Table: this table is identical in contents to the Import Lookup Table until the image is bound.

6.4.2 Import Lookup Table

An Import Lookup Table is an array of 32-bit numbers for PE32, 64-bit for PE32+. Each entry uses the bit-field format (described below) in which bit 31 (63) is the most significant bit. The collection of these entries describes all imports from the image to a given DLL. The last entry is set to zero (NULL) to indicate end of the table.

Bit(s)

Size

Bit Field

Description

31 / 63

1

Ordinal/Name Flag

If bit is set, import by ordinal. Otherwise, import by name. Bit is masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.

30 0 / 62 0

31 / 63

Ordinal Number

Ordinal/Name Flag is 1: import by ordinal. This field is a 31-bit (63-bit) ordinal number.

30 0 / 62 0

31 / 63

Hint/Name Table RVA

Ordinal/Name Flag is 0: import by name. This field is a 31-bit (63-bit) address of a Hint/Name Table entry, relative to image base.

In a PE32 image, the lower 31 bits can be masked as 0x7FFFFFFF. In either case, the resulting number is a 32-bit integer or pointer in which the high bit is always zero (zero extension to 32 bits). Similarly for a PE32+ image, the lower 63 bits can be masked as 0x7FFFFFFFFFFFFFFF.

6.4.3 Hint/Name Table

One Hint/Name Table suffices for the entire import section. Each entry in the Hint/Name Table has the following format:

Offset

Size

Field

Description

0

2

Hint

Index into the Export Name Pointer Table. A match is attempted first with this value. If it fails, a binary search is performed on the DLL's Export Name Pointer Table.

2

variable

Name

ASCII string containing name to import. This is the string that must be matched to the public name in the DLL. This string is case sensitive and terminated by a null byte.

*

0 or 1

Pad

A trailing zero pad byte appears after the trailing null byte, if necessary, to align the next entry on an even boundary.

6.4.4 Import Address Table

The structure and content of the Import Address Table are identical to that of the Import Lookup Table, until the file is bound. During binding, the entries in the Import Address Table are overwritten with the 32-bit (or 64-bit for PE32+) addresses of the symbols being imported: these addresses are the actual memory addresses of the symbols (although technically, they are still called "virtual addresses"). The processing of binding is typically performed by the loader.

6.5 The .pdata Section

The .pdata section contains an array of function table entries used for exception handling and is pointed to by the exception table entry in the image data directory. The entries must be sorted according to the function addresses (the first field in each structure) before being emitted into the final image. The target platform determines which of the three variations described below is used.

For 32-bit MIPS images the following structure is used:

Offset

Size

Field

Description

0

4

Begin Address

Virtual address of the corresponding function.

4

4

End Address

Virtual address of the end of the function.

8

4

Exception Handler

Pointer to the exception handler to be executed.

12

4

Handler Data

Pointer to additional information to be passed to the handler.

16

4

Prolog End Address

Virtual address of the end of the function's prolog.

For the ARM, PowerPC, SH3 and SH4 WindowsCE platforms, this function table entry format is used:

Offset

Size

Field

Description

0

4

Begin Address

Virtual address of the corresponding function.

4

8 bits

Prolog Length

Number of instructions in the function's prolog.

4

22 bits

Function Length

Number of instructions in the function.

4

1 bit

32-bit Flag

Set if the function is comprised of 32-bit instructions, cleared for a 16-bit function.

4

1 bit

Exception Flag

Set if an exception handler exists for the function.

Finally, for IA64 the pdata entry format is as follows:

Offset

Size

Field

Description

0

4

Begin Address

Relative virtual address of the corresponding function.

4

4

End Address

Relative virtual address of the end of the function.

8

4

Unwind Information

Relative virtual address of the unwind information.

6.6 The .reloc Section (Image Only)

The Fix-Up Table contains entries for all fixups in the image. The Total Fix-Up Data Size in the Optional Header is the number of bytes in the fixup table. The fixup table is broken into blocks of fixups. Each block represents the fixups for a 4K page. Each block must start on a 32-bit boundary.

Fixups that are resolved by the linker do not need to be processed by the loader, unless the load image can't be loaded at the Image Base specified in the PE Header.

6.6.1 Fixup Block

Each fixup block starts with the following structure:

Offset

Size

Field

Description

0

4

Page RVA

The image base plus the page RVA is added to each offset to create the virtual address of where the fixup needs to be applied.

4

4

Block Size

Total number of bytes in the fixup block, including the Page RVA and Block Size fields, as well as the Type/Offset fields that follow.

The Block Size field is then followed by any number of Type/Offset entries. Each entry is a word (2 bytes) and has the following structure:

Offset

Size

Field

Description

0

4 bits

Type

Stored in high 4 bits of word. Value indicating which type of fixup is to be applied. These fixups are described in "Fixup Types."

0

12 bits

Offset

Stored in remaining 12 bits of word. Offset from starting address specified in the Page RVA field for the block. This offset specifies where the fixup is to be applied.

To apply a fixup, the difference is calculated between the preferred base address, and the base where the image is actually loaded. If the image is loaded at its preferred base, the delta would be zero, and thus the fixups would not have to be applied.

6.6.2 Fixup Types

Constant

Value

Description

IMAGE_REL_BASED_ABSOLUTE

0

The fixup is skipped. This type can be used to pad a block.

IMAGE_REL_BASED_HIGH

1

The fixup adds the high 16 bits of the delta to the 16-bit field at Offset. The 16-bit field represents the high value of a 32-bit word.

IMAGE_REL_BASED_LOW

2

The fixup adds the low 16 bits of the delta to the 16-bit field at Offset. The 16-bit field represents the low half of a 32-bit word.

IMAGE_REL_BASED_HIGHLOW

3

The fixup applies the delta to the 32-bit field at Offset.

IMAGE_REL_BASED_HIGHADJ

4

The fixup adds the high 16 bits of the delta to the 16-bit field at Offset. The 16-bit field represents the high value of a 32-bit word. The low 16 bits of the 32-bit value are stored in the 16 bit word that follows this base relocation. This means that this base relocation occupies two slots.

IMAGE_REL_BASED_MIPS_JMPADDR

5

Fixup applies to a MIPS jump instruction.

 

6

Reserved for future use.

 

7

Reserved for future use.

IMAGE_REL_BASED_MIPS_JMPADDR16

9

Fixup applies to a MIPS16 jump instruction.

IMAGE_REL_BASED_DIR64

10

This fixup applies the delta to the 64-bit field at Offset.

6.7 The .tls Section

The .tls section provides direct PE/COFF support for static Thread Local Storage (TLS). TLS is a special storage class supported by Windows, in which a data object is not an automatic (stack) variable, yet it is local to each individual thread that runs the code. Thus, each thread can maintain a different value for a variable declared using TLS.

Note that any amount of TLS data can be supported by using the API calls TlsAlloc, TlsFree, TlsSetValue, and TlsGetValue. The PE/COFF implementation is an alternative approach to using the API, and it has the advantage of being simpler from the high-level-language programmer's point of view. This implementation enables TLS data to be defined and initialized in a manner similar to ordinary static variables in a program. For example, in Microsoft Visual C++, a static TLS variable can be defined as follows, without using the Windows API:

 
 __declspec (thread) int tlsFlag = 1; 

To support this programming construct, the PE/COFF .tls section specifies the following information: initialization data, callback routines for per-thread initialization and termination, and the TLS index, explained in the following discussion.

NOTE

Statically declared TLS data objects can be used only in statically loaded image files. This fact makes it unreliable to use static TLS data in a DLL unless you know that the DLL, or anything statically linked with it, will never be loaded dynamically with the LoadLibrary API function.


Executable code accesses a static TLS data object through the following steps:

  1. At link time, the linker sets the Address of Index field of the TLS Directory. This field points to a location where the program will expect to receive the TLS index.

    The Microsoft run-time library facilitates this process by defining a memory image of the TLS Directory and giving it the special name "__tls_used" (Intel x86 platforms) or "_tls_used" (other platforms). The linker looks for this memory image and uses the data there to create the TLS Directory. Other compilers that support TLS and work with the Microsoft linker must use this same technique.

  2. When a thread is created, the loader communicates the address of the thread's TLS array by placing the address of the Thread Environment Block (TEB) in the FS register. A pointer to the TLS array is at the offset of 0x2C from the beginning of TEB. This behavior is Intel x86 specific.

  3. The loader assigns the value of the TLS index to the place indicated by the Address of Index field.

  4. The executable code retrieves the TLS index and also the location of the TLS array.

  5. The code uses the TLS index and the TLS array location (multiplying the index by four and using it as an offset to the array) to get the address of the TLS data area for the given program and module. Each thread has its own TLS data area, but this is transparent to the program, which doesn't need to know how data is allocated for individual threads.

  6. An individual TLS data object is accessed as some fixed offset into the TLS data area.

The TLS array is an array of addresses that the system maintains for each thread. Each address in this array gives the location of TLS data for a given module (.EXE or DLL) within the program. The TLS index indicates which member of the array to use. The index is a number (meaningful only to the system) that identifies the module.

6.7.1 The TLS Directory

The TLS Directory has the following format:

Offset (PE32/PE32+)

Size (PE32/PE32+)

Field

Description

0

4/8

Raw Data Start VA (Virtual Address)

Starting address of the TLS template. The template is a block of data used to initialize TLS data. The system copies all this data each time a thread is created, so it must not be corrupted. Note that this address is not an RVA; it is an address for which there should be a base relocation in the .reloc section.

4/8

4/8

Raw Data End VA

Address of the last byte of the TLS, except for the zero fill. As with the Raw Data Start VA, this is a virtual address, not an RVA.

8/16

4/8

Address of Index

Location to receive the TLS index, which the loader assigns. This location is in an ordinary data section, so it can be given a symbolic name accessible to the program.

12/24

4/8

Address of Callbacks

Pointer to an array of TLS callback functions. The array is null-terminated, so if there is no callback function supported, this field points to four bytes set to zero. The prototype for these functions is given below, in "TLS Callback Functions."

16/32

4

Size of Zero Fill

The size in bytes of the template, beyond the initialized data delimited by Raw Data Start VA and Raw Data End VA. The total template size should be the same as the total size of TLS data in the image file. The zero fill is the amount of data that comes after the initialized nonzero data.

20/36

4

Characteristics

Reserved for possible future use by TLS flags.

6.7.2 TLS Callback Functions

The program can provide one or more TLS callback functions (though Microsoft compilers do not currently use this feature) to support additional initialization and termination for TLS data objects. A typical reason to use such a callback function would be to call constructors and destructors for objects.

Although there is typically no more than one callback function, a callback is implemented as an array to make it possible to add additional callback functions if desired. If there is more than one callback function, each function is called in the order its address appears in the array. A null pointer terminates the array. It is perfectly valid to have an empty list (no callback supported), in which case the callback array has exactly one member a null pointer.

The prototype for a callback function (pointed to by a pointer of type PIMAGE_TLS_CALLBACK) has the same parameters as a DLL entry-point function:

 
 typedef VOID (NTAPI *PIMAGE_TLS_CALLBACK) ( PVOID DllHandle, DWORD Reason, PVOID Reserved     ); 

The Reserved parameter should be left set to 0. The Reason parameter can take the following values:

Setting

Value

Description

DLL_PROCESS_ATTACH

1

New process has started, including the first thread.

DLL_THREAD_ATTACH

2

New thread has been created (this notification sent for all but the first thread).

DLL_THREAD_DETACH

3

Thread is about to be terminated (this notification sent for all but the first thread).

DLL_PROCESS_DETACH

0

Process is about to terminate, including the original thread.

6.8 The Load Config Structure (Image Only)

The load_config structure was formerly used in very limited cases in the NT operating system itself to describe various features too difficult or large to describe in the file header or optional header of the image. Current versions of the Visual C++ Linker and Windows XP and above have a new version of this structure for x86 32-bit that includes the SafeSEH (Safe Structured Exception Handler) technology. This provides a list of safe SE Handlers that is used during exception dispatching by the operating system. If the handler address resides in an image's virtual address range and is marked as SAFESEH aware (see IMAGE_DLLCHARACTERISTICS_NO_SEH above), then the handler must be in the list of known, safe handlers for that image, otherwise the operating system will terminate the application. This helps prevent the "x86 exception handler hijacking" exploit that has been used in the past to take control of the operating system.

The Microsoft Linker will automatically provide a default load_config structure to include the SafeSEH data. If the user code already provides a load_config structure, it must include the new SafeSEH fields, otherwise, the linker cannot include the SafeSEH data, and hence, the image will not be marked as containing SafeSEH.

6.8.1 Load Config Directory

The data directory entry for pre-SafeSEH load_config structures needs to specify a particular size of the load_config structure, as the OS loader always expects it to be a certain value. In that regard, the size is really a version check only. For Windows XP and earlier compatibility and x86 images that must run on Windows XP and earlier, the size must be 64.

6.8.2 Load Config Layout

The Load Config structure has the following layout for 32- and 64-bit PE files:

Offset (PE32/PE32+)

Size (PE32/PE32+)

Field

Description

0

4

Size

The actual size of the structure, inclusive. May differ from the Size given in the data directory for Windows XP and earlier compatibility.

4

4

TimeDateStamp

Reserved, must be zero.

8

2

MajorVersion

Reserved, must be zero.

10

2

MinorVersion

Reserved, must be zero.

12

4

GlobalFlagsClear

Which global loader flags to clear for this process as the loader starts the process.

16

4

GlobalFlagsSet

Which global loader flags to set for this process as the loader starts the process.

20

4

CriticalSectionDefaultTimeout

Default timeout value to use for this process's critical sections that are abandoned.

24

4/8

DeCommitFreeBlockThreshold

 

28/32

4/8

DeCommitTotalFreeThreshold

 

32/40

4/8

LockPrefixTable

[x86 only] VA of a list of addresses where the LOCK prefix is used so that they can be replaced with NOP on single processor machines.

36/48

4/8

MaximumAllocationSize

 

40/56

4/8

VirtualMemoryThreshold

 

44/72

4

ProcessHeapFlags

 

48/64

4/8

ProcessAffinityMask

 

52/76

2

CSDVersion

Service pack version identifier.

54/78

2

Reserved

Must be zero.

56/80

4/8

EditList

VA.

60/88

4/8

SecurityCookie

 

64/96

4/8

SEHandlerTable

[x86 only] VA of the sorted table of RVAs of each valid, unique SE Handler in the image.

68/104

4/8

SEHandlerCount

[x86 only] Count of unique handlers in the table.

Note that the fields ProcessHeapFlags and ProcessAffinityMask are swapped between the 32- and 64-bit versions. This was done to keep the 64-bit fields aligned properly.

6.9 The .rsrc Section

Resources are indexed by a multiple level binary-sorted tree structure. The general design can incorporate 2**31 levels. By convention, however, Windows uses three levels:

Type

Name

Language

A series of Resource Directory Tables relate all the levels in the following way: each directory table is followed by a series of directory entries, which give the name or ID for that level (Type, Name, or Language level) and an address of either a data description or another directory table. If a data description is pointed to, then the data is a leaf in the tree. If another directory table is pointed to, then that table lists directory entries at the next level down.

A leaf's Type, Name, and Language IDs are determined by the path taken, through directory tables, to reach the leaf. The first table determines Type ID, the second table (pointed to by the directory entry in the first table) determines Name ID, and the third table determines Language ID.

The general structure of the .rsrc section is:

Data

Description

Resource Directory Tables (and Resource Directory Entries)

A series of tables, one for each group of nodes in the tree. All top-level (Type) nodes are listed in the first table. Entries in this table point to second-level tables. Each second-level tree has the same Type identifier but different Name identifiers. Third-level trees have the same Type and Name identifiers but different Language identifiers.

Each individual table is immediately followed by directory entries, in which each entry has: 1) a name or numeric identifier, and 2) a pointer to a data description or a table at the next lower level.

Resource Directory Strings

Two-byte-aligned Unicode strings, which serve as string data pointed to by directory entries.

Resource Data Description

An array of records, pointed to by tables, which describe the actual size and location of the resource data. These records are the leaves in the resource-description tree.

Resource Data

Raw data of the resource section. The size and location information in the Resource Data Descriptions delimit the individual regions of resource data.

6.9.1 Resource Directory Table

Each Resource Directory Table has the following format. This data structure should be considered the heading of a table, because the table actually consists of directory entries (see next section) as well as this structure:

Offset

Size

Field

Description

0

4

Characteristics

Resource flags, reserved for future use; currently set to zero.

4

4

Time/Date Stamp

Time the resource data was created by the resource compiler.

8

2

Major Version

Major version number, set by the user.

10

2

Minor Version

Minor version number.

12

2

Number of Name Entries

Number of directory entries, immediately following the table, that use strings to identify Type, Name, or Language (depending on the level of the table).

14

2

Number of ID Entries

Number of directory entries, immediately following the Name entries, that use numeric identifiers for Type, Name, or Language.

6.9.2 Resource Directory Entries

The directory entries make up the rows of a table. Each Resource Directory Entry has the following format. Note that whether the entry is a Name or ID entry is indicated by the Resource Directory Table, which indicates how many Name and ID entries follow it (remember that all the Name entries precede all the ID entries for the table). All entries for the table are sorted in ascending order: the Name entries by case-insensitive string, and the ID entries by numeric value.

Offset

Size

Field

Description

0

4

Name RVA

Address of string that gives the Type, Name, or Language identifier, depending on level of table.

0

4

Integer ID

32-bit integer that identifies Type, Name, or Language.

4

4

Data Entry RVA

High bit 0. Address of a Resource Data Entry (a leaf).

4

4

Subdirectory RVA

High bit 1. Lower 31 bits are the address of another Resource Directory Table (the next level down).

6.9.3 Resource Directory String

The Resource Directory String area consists of Unicode strings, which are word aligned. These strings are stored together after the last Resource Directory Entry and before the first Resource Data Entry. This minimizes the impact of these variable length strings on the alignment of the fixed-size directory entries. Each Resource Directory String has the following format:

Offset

Size

Field

Description

0

2

Length

Size of string, not including length field itself.

2

variable

Unicode String

Variable-length Unicode string data, word aligned.

6.9.4 Resource Data Entry

Each Resource Data Entry describes an actual unit of raw data in the Resource Data area, and has the following format:

Offset

Size

Field

Description

0

4

Data RVA

Address of a unit of resource data in the Resource Data area.

4

4

Size

Size, in bytes, of the resource data pointed to by the Data RVA field.

8

4

Codepage

Code page used to decode code point values within the resource data. Typically, the code page would be the Unicode code page.

12

4

Reserved (must be set to 0)

6.9.5 Resource Example

The resource example shows the PE/COFF representation of the following resource data:

 
 TypeId#    NameId#     Language ID   Resource Data     1          1           0            00010001     1          1           1            10010001     1          2           0            00010002     1          3           0            00010003     2          1           0            00020001     2          2           0            00020002     2          3           0            00020003     2          4           0            00020004     9          1           0            00090001     9          9           0            00090009     9          9           1            10090009     9          9           2            20090009 

When this data is encoded, a dump of the PE/COFF Resource Directory results in the following output:

 
 Offset  Data 0000:   00000000 00000000 00000000 00030000  (3 entries in this directory) 0010:   00000001 80000028    (TypeId #1, Subdirectory at offset 0x28) 0018:   00000002 80000050    (TypeId #2, Subdirectory at offset 0x50) 0020:   00000009 80000080    (TypeId #9, Subdirectory at offset 0x80) 0028:   00000000 00000000 00000000 00030000  (3 entries in this directory) 0038:   00000001 800000A0    (NameId #1, Subdirectory at offset 0xA0) 0040:   00000002 00000108    (NameId #2, data desc at offset 0x108) 0048:   00000003 00000118    (NameId #3, data desc at offset 0x118) 0050:   00000000 00000000 00000000 00040000  (4 entries in this directory) 0060:   00000001 00000128    (NameId #1, data desc at offset 0x128) 0068:   00000002 00000138    (NameId #2, data desc at offset 0x138) 0070:   00000003 00000148    (NameId #3, data desc at offset 0x148) 0078:   00000004 00000158    (NameId #4, data desc at offset 0x158) 0080:   00000000 00000000 00000000 00020000  (2 entries in this directory) 0090:   00000001 00000168    (NameId #1, data desc at offset 0x168) 0098:   00000009 800000C0    (NameId #9, Subdirectory at offset 0xC0) 00A0:   00000000 00000000 00000000 00020000  (2 entries in this directory) 00B0:   00000000 000000E8    (Language ID 0, data desc at offset 0xE8 00B8:   00000001 000000F8    (Language ID 1, data desc at offset 0xF8 00C0:   00000000 00000000 00000000 00030000  (3 entries in this directory) 00D0:   00000001 00000178    (Language ID 0, data desc at offset 0x178 00D8:   00000001 00000188    (Language ID 1, data desc at offset 0x188 00E0:   00000001 00000198    (Language ID 2, data desc at offset 0x198 00E8:   000001A8(At offset 0x1A8, for TypeId #1, NameId #1, Language id #0         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 00F8:   000001AC(At offset 0x1AC, for TypeId #1, NameId #1, Language id #1         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0108:   000001B0(At offset 0x1B0, for TypeId #1, NameId #2,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0118:   000001B4(At offset 0x1B4, for TypeId #1, NameId #3,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0128:   000001B8(At offset 0x1B8, for TypeId #2, NameId #1,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0138:   000001BC(At offset 0x1BC, for TypeId #2, NameId #2,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0148:   000001C0(At offset 0x1C0, for TypeId #2, NameId #3,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0158:   000001C4(At offset 0x1C4, for TypeId #2, NameId #4,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0168:   000001C8(At offset 0x1C8, for TypeId #9, NameId #1,         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0178:   000001CC(At offset 0x1CC, for TypeId #9, NameId #9, Language id #0         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0188:   000001D0(At offset 0x1D0, for TypeId #9, NameId #9, Language id #1         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 0198:   000001D4(At offset 0x1D4, for TypeId #9, NameId #9, Language id #2         00000004(4 bytes of data)         00000000(codepage)         00000000(reserved) 

The raw data for the resources follows:

 
 01A8:   00010001 01AC:   10010001 01B0:   00010002 01B4:   00010003 01B8:   00020001 01BC:   00020002 01C0:   00020003 01C4:   00020004 01C8:   00090001 01CC:   00090009 01D0:   10090009 01D4:   20090009 

6.10 The .cormeta Section (Object Only)

Common Language Runtime (clr) metadata is stored in this section and is used as an indicator that the object file contains managed code. The format of the metadata is not documented, but can be handed to the clr interfaces for handling metadata.



The Common Language Infrastructure Annotated Standard (Microsoft. NET Development Series)
The Common Language Infrastructure Annotated Standard (Microsoft. NET Development Series)
ISBN: N/A
EAN: N/A
Year: 2002
Pages: 121

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