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.
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 SectionThe .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:
6.1.2 Debug TypeThe following values are defined for the Debug Type field of the debug directory:
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 InformationTo support debug information, the linker:
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.
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 TableThe 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.
6.3.2 Export Address TableThe 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.
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 TableThe 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 TableThe 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 TableThe 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 SectionAll 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 Layout6.4.1 Import Directory TableThe 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:
6.4.2 Import Lookup TableAn 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.
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 TableOne Hint/Name Table suffices for the entire import section. Each entry in the Hint/Name Table has the following format:
6.4.4 Import Address TableThe 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 SectionThe .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:
For the ARM, PowerPC, SH3 and SH4 WindowsCE platforms, this function table entry format is used:
Finally, for IA64 the pdata entry format is as follows:
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 BlockEach fixup block starts with the following structure:
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:
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
6.7 The .tls SectionThe .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:
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 DirectoryThe TLS Directory has the following format:
6.7.2 TLS Callback FunctionsThe 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:
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 DirectoryThe 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 LayoutThe Load Config structure has the following layout for 32- and 64-bit PE files:
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 SectionResources 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:
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:
6.9.1 Resource Directory TableEach 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:
6.9.2 Resource Directory EntriesThe 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.
6.9.3 Resource Directory StringThe 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:
6.9.4 Resource Data EntryEach Resource Data Entry describes an actual unit of raw data in the Resource Data area, and has the following format:
6.9.5 Resource ExampleThe 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. |