A fixup is a place in a page that the loader must patch: with the address of something in another object, which depends on where the objects are loaded, or with the address of a procedure imported from another module. Fixups are kept per page, so that the loader can patch each page as it reads it. Two tables in the fixup section hold them: the fixup page table and the fixup records.
Fixup page table
At the header’s fixup page table offset (0x68, from the start of the LE
header) there is one 32-bit offset for each page, and one more at the end: the number
of pages plus 1 entries. Each is an offset into the fixup record table. The records of
page p (from 1) run from entry p − 1 to entry p, so a
page whose two entries are equal has no fixups, and the last entry is the size of the
fixup record table.
000001E4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001F4 1C 00 00 00 1C 00 00 00 5A 00 00 00 A6 00 00 00
…
00000234 2D 06 00 00 49 06 00 00 50 06 00 00 5A 06 00 00
0x1C, page 5 has none, page 6’s run from 0x1C to 0x5A, and 0x65A bytes of records in allFixup records
The fixup record table is at the header’s offset 0x6C. A record is
built from these parts, in order:
| Size | Field | Meaning |
|---|---|---|
| 1 | Source | The kind of value to patch, and whether a source list follows. |
| 1 | Flags | The kind of target, and the sizes of the fields that follow. |
| 2 or 1 | Source offset, or count | The offset in the page of the place to patch, a signed 16-bit number; or, when the source byte has 0x20, the 8-bit number of source offsets in the list at the end. |
| varies | Target | What to patch it with. |
| 0, 2 or 4 | Additive value | Present when the flags have 0x04: a value added to the target, 32-bit when the flags have 0x20. |
| 2 × count | Source list | With the source list bit: the 16-bit offsets in the page of each place to patch. |
A value that crosses into the next page gets a record in each page; the record in the second page has a negative source offset. The explorer splits the records by page, shows every field, and uses the imported targets to label the code.
Source types
| Source byte | Meaning |
|---|---|
0x00 | A byte. |
0x02 | A 16-bit selector. |
0x03 | A 16:16 pointer: a 16-bit offset and a selector. |
0x05 | A 16-bit offset. |
0x06 | A 16:32 pointer: a 32-bit offset and a selector. |
0x07 | A 32-bit offset. |
0x08 | A 32-bit offset relative to the place itself, as in a near call or jmp. |
0x10 bit | A fixup to a 16:16 alias. |
0x20 bit | A source list follows the target. |
The type is the low four bits; 1 and 4 are undefined.
Target flags
| Bits | Meaning |
|---|---|
0x03 | The target type: 0 internal reference, 1 imported by ordinal, 2 imported by name, 3 internal reference through the entry table. |
0x04 | An additive value is present. |
0x08 | Internal chaining, in Open Watcom’s name; IBM’s 1992 text calls it reserved. |
0x10 | The target offset (or ordinal, or procedure name offset) is 32 bits, not 16. |
0x20 | The additive value is 32 bits, not 16. |
0x40 | The object number or module ordinal is 16 bits, not 8. |
0x80 | The import ordinal is 8 bits. |
Targets
| Target type | Target data |
|---|---|
| 0, internal | The object number, 1 or 2 bytes, then the offset in it, 2 or 4 bytes. A 16-bit selector fixup has no offset. |
| 1, by ordinal | The module ordinal in the import module table, 1 or 2 bytes, then the procedure’s ordinal, 1, 2 or 4 bytes. |
| 2, by name | The module ordinal, 1 or 2 bytes, then the offset of the procedure’s name in the import procedure table, 2 or 4 bytes. |
| 3, through the entry table | An ordinal in this module’s entry table, 1 or 2 bytes. |
Worked examples
00000244 07 00 98 00 01 5C 09 07 00 88 00 01 D7 21 07 00
Source 0x07, a 32-bit offset; flags 0, an internal reference with an
8-bit object number and a 16-bit offset; source offset 0x0098 in the page;
object 1, offset 0x095C. Page 4 is the fourth 512-byte page of object 1, so
the loader writes the address of object 1 + 0x095C into the 32-bit value
at 0x600 + 0x98 = 0x698 in object 1.
0000026E 27 00 02 01 60 06 43 01 92 01
Source 0x27, a 32-bit offset with a source list; flags 0; a count of 2;
object 1, offset 0x0660; then the two places in the page,
0x0143 and 0x0192. One record patches both.