Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

OMF Linker Notes

The following are a series of extracts from the OMF specifciation regarding linking OMF modules.

Resolution of EXTDEF Records

Resolution of an external reference is by name match (case sensitive) and symbol type match. The
search looks for a matching name in the following sequence:

1. Searches PUBDEF and COMDEF records.
2. If linking a segmented executable, searches imported names (IMPDEF).
3. If linking a segmented executable and not a DLL, searches for an exported name (EXPDEF) with the same
name—a self-imported alias.
4. Searches for the symbol name among undefined symbols. If the reference is to a weak extern, the default
resolution is used. If the reference is to a strong extern, it's an undefined external, and the linker generates
an error.

Notes About Handling FIXUPP Records

FIXUPP records are used to fix references in the immediately preceding LEDATA, LIDATA, or
COMDAT record.

The Frame field is the translator's way of telling the linker the contents of the segment register used for
the reference; the TARGET is the item being referenced whose address was not completely resolved
by the translator. In protected mode, the only legal segment register values are selectors; every
segment and group of segments is mapped through some selector and addressed by an offset within
the underlying memory defined by that selector.

The FIXUPP Target index maps onto multiple groups of standard and extended OMF records. The documentation not very clear on this, but it it means to map this onto the set of "External Symbols" as defined in the "Order of Records" section:

External Symbols

Ordered by occurrence of EXTDEF, COMDEF, LEXTDEF, and LCOMDEF
records and symbols within each. Referenced as an external name index
(in FIXUP subrecords).

What this leaves out is that the "order of occurrence" also includes CEXTDEF records, which is implied (but not explicitly stated) by the CEXTDEF section:

(CEXTDEF)
This record serves the same purpose as the EXTDEF record described earlier.

Also, the FIXUPP destination address for the actual fixup location is calculated from the start of the last LIDATA, LEDATA or COMDAT record, followed by the FIXUPP offset (10bit) field.

The documentation for the FIXUP Subrecord contains a block diagram for the record that is incorrect. The illustration shows that "Fix Data", "Frame Datum" and "Target Datum" are all conditional. The "<conditional>" markings for these are all shifted to the left one place - "Target Displacement" is optional instead of "Fix Data". This is backed up in the documentation that follows the diagram.

COMDEF linking notes

If a public or exported symbol with the same name is found in another module to which this module is
bound or linked, certain linkers will give the error "symbol defined more than once.“

Communal variables cannot be resolved to dynamic links (that is, imported symbols).

COMDAT Resolution via CEXTDEF

A CEXTDEF can precede the COMDAT to which it will be resolved. In this case, the location of the
COMDAT is not known at the time the CEXTDEF is seen.

This record is produced when a FIXUPP record refers to a COMDAT symbol.

Resolution of Weak Externs (COMENT subrecord WKEXT)

There are two ways to cancel the "weakness" of a weak extern; both result in the extern becoming a
"strong" extern (the same as an EXTDEF). They are:
 * If a PUBDEF for the weak extern is linked in
 * If an EXTDEF for the weak extern is found in another module (including libraries)

If a weak extern becomes strong, then it must be resolved with a matching PUBDEF, just like a regular
EXTDEF. If a weak extern has not become strong by the end of the linking process, then the default
resolution is used.

If two weak externs for the same symbol in different modules have differing default resolutions, many
linkers will emit a warning.

Weak externs do not query libraries for resolution; if an extern is still weak when libraries are searched,
it stays weak and gets the default resolution. However, if a library module is linked in for other reasons
(say, to resolve strong externs) and there are EXTDEFs for symbols that were weak, the symbols
become strong.

The extern indicies used to resolve WKEXT records uses the same scheme as the FIXUPP records (CEXTDEF, EXTERN, COMDAT).