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.
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. |
The Export Address Table contains the address of exported entry points and exported data and absolutes. An ordinal number is used to index the Export Address Table, after subtracting the value of the Ordinal Base field to get a true, zero-based index. (Thus, if the Ordinal Base is set to 1, a common value, an ordinal of 6 is the same as a zero-based index of 5.)
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 NT, the export named “HeapAlloc” is forwarded to the string “NTDLL.RtlAllocateHeap”. This allows applications to use the Windows NT-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 NT and can run on any Win32 system.
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.
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];
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.