Jump to content

LX - Linear eXecutable Module Format Description: Difference between revisions

From EDM2
Ak120 (talk | contribs)
Ak120 (talk | contribs)
mNo edit summary
 
(20 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation'''
{{IBM-Reprint}}


'''Note:''' Check this (possible) newer version at: [[IBM OS2 16-32-BIT Object Module Format (OMF) and Linear Executablet Module Format (LX) - lx386]]
'''Note:''' Check this (possible) newer version at: [[IBM OS/2 16/32-bit Object Module Format (OMF) and Linear eXecutable Module Format (LX)]] - lx386


Date: June 3, 1992
Date: June 3, 1992


''Figure 1. 32-bit Linear EXE File Layout''
''Figure 1. 32-bit Linear EXE File Layout''
       00h +------------------+  <--+
       00h +------------------+  <--+
           | DOS 2 Compatible |    |
           | DOS 2 Compatible |    |
Line 93: Line 92:


''Figure 2. 32-bit Linear EXE Header''
''Figure 2. 32-bit Linear EXE Header''
           +-----+-----+-----+-----+-----+-----+-----+-----+
           +-----+-----+-----+-----+-----+-----+-----+-----+
       00h | "L"  "X" |B-ORD|W-ORD|    FORMAT LEVEL      |
       00h | "L"  "X" |B-ORD|W-ORD|    FORMAT LEVEL      |
Line 142: Line 140:
Note: The OBJECT ITER PAGES OFF must either be 0 or set to the same value as DATA PAGES OFFSET in OS/2 2.0. Ie., iterated pages are required to be in the same section of the file as regular pages.
Note: The OBJECT ITER PAGES OFF must either be 0 or set to the same value as DATA PAGES OFFSET in OS/2 2.0. Ie., iterated pages are required to be in the same section of the file as regular pages.


Note: Table offsets in the Linear EXE Header may be set to zero to indicate that the table does not exist in the EXE file and it's size is zero.
Note: Table offsets in the Linear EXE Header may be set to zero to indicate that the table does not exist in the EXE file and its size is zero.


;"L" "X" = DW Signature word.
;"L" "X" = DW Signature word.
:The signature word is used by the loader to identify the EXE file as a valid 32-bit Linear Executable Module Format. "L" is low order byte. "X" is high order byte.
:The signature word is used by the loader to identify the EXE file as a valid 32-bit Linear Executable Module Format. "L" is low order byte. "X" is high order byte.


;B-ORD = DB Byte Ordering.
;B-ORD = DB Byte Ordering.
Line 158: Line 156:


;Format Level = DD Linear EXE Format Level.
;Format Level = DD Linear EXE Format Level.
:The Linear EXE Format Level is set to 0 for the initial version of the 32-bit linear EXE format. Each incompatible change to the linear EXE format must increment this value. This allows the system to recognized future EXE file versions so that an appropriate error message may be displayed if an attempt is made to load them.
:The Linear EXE Format Level is set to 0 for the initial version of the 32-bit linear EXE format. Each incompatible change to the linear EXE format must increment this value. This allows the system to recognized future EXE file versions so that an appropriate error message may be displayed if an attempt is made to load them.


;CPU Type = DW Module CPU Type.
;CPU Type = DW Module CPU Type.
Line 182: Line 180:
::00000002h = Reserved for system use.
::00000002h = Reserved for system use.
::00000004h = Per-Process Library Initialization.
::00000004h = Per-Process Library Initialization.
:::The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Initialization is assumed. Setting this bit for an EXE file is invalid.
:::The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Initialization is assumed. Setting this bit for an EXE file is invalid.
::00000008h = Reserved for system use.
::00000008h = Reserved for system use.
::00000010h = Internal fixups for the module have been applied.
::00000010h = Internal fixups for the module have been applied.
:::The setting of this bit in a Linear Executable Module indicates that each object of the module has a preferred load address specified in the Object Table Reloc Base Addr. If the module's objects can not be loaded at these preferred addresses, then the relocation records that have been retained in the file data will be applied.
:::The setting of this bit in a Linear Executable Module indicates that each object of the module has a preferred load address specified in the Object Table Reloc Base Addr. If the module's objects can not be loaded at these preferred addresses, then the relocation records that have been retained in the file data will be applied.
::00000020h = External fixups for the module have been applied.
::00000020h = External fixups for the module have been applied.
::00000040h = Reserved for system use.
::00000040h = Reserved for system use.
Line 208: Line 206:
:::The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Termination is assumed. Setting this bit for an EXE file is invalid.
:::The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Termination is assumed. Setting this bit for an EXE file is invalid.


;MODULE # PAGES = DD Number of pages in module.
;MODULE # PAGES = DD Number of pages in module.
:This field specifies the number of pages physically contained in this module. In other words, pages containing either enumerated or iterated data, or zero-fill pages that have relocations, not invalid or zero-fill pages implied by the Virtual Size in the Object Table being larger than the number of pages actually in the linear EXE file. These pages are contained in the 'preload pages', 'demand load pages' and 'iterated data pages' sections of the linear EXE module. This is used to determine the size of the page information tables in the linear EXE module.
:This field specifies the number of pages physically contained in this module. In other words, pages containing either enumerated or iterated data, or zero-fill pages that have relocations, not invalid or zero-fill pages implied by the Virtual Size in the Object Table being larger than the number of pages actually in the linear EXE file. These pages are contained in the 'preload pages', 'demand load pages' and 'iterated data pages' sections of the linear EXE module. This is used to determine the size of the page information tables in the linear EXE module.


;EIP OBJECT # = DD The Object number to which the Entry Address is relative.
;EIP OBJECT # = DD The Object number to which the Entry Address is relative.
:This specifies the object to which the Entry Address is relative. This must be a nonzero value for a program module to be correctly loaded. A zero value for a library module indicates that no library entry routine exists. If this value is zero, then both the Per-process Library Initialization bit and the Per-process Library Termination bit must be clear in the module flags, or else the loader will fail to load the module. Further, if the Per-process Library Termination bit is set, then the object to which this field refers must be a 32-bit object (i.e., the Big/Default bit must be set in the object flags; see below).
:This specifies the object to which the Entry Address is relative. This must be a nonzero value for a program module to be correctly loaded. A zero value for a library module indicates that no library entry routine exists. If this value is zero, then both the Per-process Library Initialization bit and the Per-process Library Termination bit must be clear in the module flags, or else the loader will fail to load the module. Further, if the Per-process Library Termination bit is set, then the object to which this field refers must be a 32-bit object (i.e., the Big/Default bit must be set in the object flags; see below).


;EIP = DD Entry Address of module.
;EIP = DD Entry Address of module.
:The Entry Address is the starting address for program modules and the library initialization and Library termination address for library modules.
:The Entry Address is the starting address for program modules and the library initialization and Library termination address for library modules.


;ESP OBJECT # = DD The Object number to which the ESP is relative.
;ESP OBJECT # = DD The Object number to which the ESP is relative.
        This specifies the object to which the starting ESP
:This specifies the object to which the starting ESP is relative. This must be a nonzero value for a program module to be correctly loaded. This field is ignored for a library module.
        is relative. This must be a nonzero value for a
        program module to be correctly loaded. This field
        is ignored for a library module.
 
    ESP = DD  Starting stack address of module.
        The  ESP defines the starting stack  pointer address
        for program modules.  A zero  value  in  this  field
        indicates  that  the  stack  pointer  is  to  be
        initialized  to the  highest  address/offset in  the
        object.  This field is ignored for a library module.


    PAGE SIZE = DD The size of one page for this system.
;ESP = DD Starting stack address of module.
        This  field  specifies  the page size  used  by the
:The ESP defines the starting stack pointer address for program modules. A zero value in this field indicates that the stack pointer is to be initialized to the highest address/offset in the object. This field is ignored for a library module.
        linear EXE  format and the  system. For the initial
        version of this linear  EXE format the page  size is
        4Kbytes. (The 4K page size  is specified by a value
        of 4096 in this field.)


    PAGE OFFSET  SHIFT = DD The shift left  bits  for page
;PAGE SIZE = DD The size of one page for this system.
    offsets.
:This field specifies the page size used by the linear EXE format and the system. For the initial version of this linear EXE format the page size is 4Kbytes. (The 4K page size is specified by a value of 4096 in this field.)
        This field gives the number  of bit  positions  to
        shift left when interpreting  the Object Page Table
        entries' page  offset  field. This  determines  the
        alignment  of the page information in the file. For
        example, a value of 4 in this field would align all
        pages in the  Data Pages and Iterated Pages sections
        on 16  byte  (paragraph)  boundaries. A Page Offset
        Shift of 9 would align all pages on a 512 byte (disk
        sector) basis.  The default  value for this field is
        12 (decimal), which give a 4096 byte alignment.  All
        other offsets are byte aligned.


    FIXUP  SECTION  SIZE  = DD Total  size  of the fixup
;PAGE OFFSET SHIFT = DD The shift left bits for page offsets.
    information in bytes.
:This field gives the number of bit positions to shift left when interpreting the Object Page Table entries' page offset field. This determines the alignment of the page information in the file. For example, a value of 4 in this field would align all pages in the Data Pages and Iterated Pages sections on 16 byte (paragraph) boundaries. A Page Offset Shift of 9 would align all pages on a 512 byte (disk sector) basis. The default value for this field is 12 (decimal), which give a 4096 byte alignment. All other offsets are byte aligned.
        This includes the following 4 tables:


            - Fixup Page Table
;FIXUP SECTION SIZE = DD Total size of the fixup information in bytes.
            - Fixup Record Table
:This includes the following 4 tables:
            - Import Module name Table
:* Fixup Page Table
            - Import Procedure Name Table
:* Fixup Record Table
:* Import Module name Table
:* Import Procedure Name Table


    FIXUP SECTION CHECKSUM   =   DD   Checksum for fixup
;FIXUP SECTION CHECKSUM = DD Checksum for fixup information.
    information.
:This is a cryptographic checksum covering all of the fixup information. The checksum for the fixup information is kept separate because the fixup data is not always loaded into main memory with the 'loader section'. If the checksum feature is not implemented, then the linker will set these fields to zero.
        This is a cryptographic checksum covering all of the
        fixup information. The checksum   for the fixup
        information is kept separate because the fixup data
        is not always loaded into main memory with the
        'loader section'. If the checksum feature is not
        implemented, then the linker will set these fields
        to zero.


    LOADER SECTION SIZE = DD Size of memory resident
;LOADER SECTION SIZE = DD Size of memory resident tables.
    tables.
:This is the total size in bytes of the tables required to be memory resident for the module, while the module is in use. This total size includes all tables from the Object Table down to and including the Per-Page Checksum Table.
        This is the total size in bytes of the tables
        required to be memory resident for the module, while
        the module is in use. This total size includes all
        tables from the Object Table down to and including
        the Per-Page Checksum Table.


    LOADER SECTION CHECKSUM = DD Checksum   for loader
;LOADER SECTION CHECKSUM = DD Checksum for loader section.
    section.
:This is a cryptographic checksum covering all of the loader section information. If the checksum feature is not implemented, then the linker will set these fields to zero.
        This is a cryptographic checksum covering all of the
        loader section information. If the checksum feature
        is not implemented, then the linker will set these
        fields to zero.


    OBJECT TABLE OFF = DD Object Table offset.
;OBJECT TABLE OFF = DD Object Table offset.
        This offset is relative to the beginning of the
:This offset is relative to the beginning of the linear EXE header.
        linear EXE header.


    # OBJECTS IN MODULE = DD Object Table Count.
# OBJECTS IN MODULE = DD Object Table Count.
         This defines the number of entries in Object Table.
         This defines the number of entries in Object Table.


    OBJECT PAGE TABLE OFFSET = DD Object Page Table offset
  OBJECT PAGE TABLE OFFSET = DD Object Page Table offset
         This offset is relative to the beginning of the
         This offset is relative to the beginning of the
         linear EXE header.
         linear EXE header.


    OBJECT ITER PAGES OFF = DD Object Iterated Pages
  OBJECT ITER PAGES OFF = DD Object Iterated Pages offset.
    offset.
         This offset is relative to the beginning of the EXE
         This offset is relative to the beginning of the EXE
         file.
         file.


     RESOURCE TABLE OFF = DD Resource Table offset.
     RESOURCE TABLE OFF = DD Resource Table offset.
         This offset is relative to the beginning of the
         This offset is relative to the beginning of the
         linear EXE header.
         linear EXE header.


     # RESOURCE TABLE ENTRIES = DD Number of entries in
     # RESOURCE TABLE ENTRIES = DD Number of entries in
     Resource Table.
     Resource Table.


     RESIDENT NAME TBL OFF = DD Resident Name Table offset.
     RESIDENT NAME TBL OFF = DD Resident Name Table offset.
         This offset is relative to the beginning of the
         This offset is relative to the beginning of the
         linear EXE header.
         linear EXE header.


Line 349: Line 305:
     PER-PAGE CHECKSUM  OFF  =  DD  Per-Page  Checksum  Table
     PER-PAGE CHECKSUM  OFF  =  DD  Per-Page  Checksum  Table
     offset.
     offset.
         This offset is relative to the beginning of the
         This offset is relative to the beginning of the
         linear EXE header.
         linear EXE header.


     DATA PAGES OFFSET = DD   Data Pages Offset.
     DATA PAGES OFFSET = DD Data Pages Offset.
         This offset is relative to the beginning of the EXE
         This offset is relative to the beginning of the EXE
         file.
         file.


Line 361: Line 317:
     reasons.
     reasons.


     NON-RES NAME TBL OFF = DD Non-Resident Name Table
     NON-RES NAME TBL OFF = DD Non-Resident Name Table
     offset.
     offset.
         This offset is relative to the beginning of the EXE
         This offset is relative to the beginning of the EXE
         file.
         file.


Line 399: Line 355:


       HEAPSIZE = DD Heap size added to the Auto DS Object.
       HEAPSIZE = DD Heap size added to the Auto DS Object.
         The heap size is the number of bytes added to the
         The heap size is the number of bytes added to the
         Auto Data Segment by the loader. This field is
         Auto Data Segment by the loader. This field is
         supported for 16-bit compatibility only and is not
         supported for 16-bit compatibility only and is not
         used by 32-bit modules.
         used by 32-bit modules.


==Program (EXE) startup registers and Library entry registers==
==Program (EXE) startup registers and Library entry registers==
Program startup registers are defined as follows.
Program startup registers are defined as follows.
:EIP = Starting program entry address.
:ESP = Top of stack address.
:CS = Code selector for base of linear address space.
:DS =  ES  = SS = Data selector for base of linear address space.
:FS =  Data selector of base of Thread Information Block (TIB).
:GS = 0.
:EAX = EBX = 0.
:ECX = EDX = 0.
:ESI = EDI = 0.
:EBP = 0.
:[ESP+0] = Return address to routine which calls DosExit(1,EAX).
:[ESP+4] = Module handle for program module.
:[ESP+8] = Reserved.
:[ESP+12] = Environment data object address.
:[ESP+16] = Command line linear address in environment data object.


        EIP = Starting program entry address.
Library initialization registers are defined as follows.
 
:EIP = Library entry address.
        ESP = Top of stack address.
:ESP = User program stack.
 
:CS = Code selector for base of linear address space.
        CS = Code selector for base of linear address space.
:DS = ES = SS = Data selector for base of linear address space.
 
        DS =  ES  = SS = Data  selector  for  base of linear
        address space.
 
        FS =  Data selector  of  base of Thread  Information
        Block (TIB).
 
        GS = 0.
 
        EAX = EBX = 0.
 
        ECX = EDX = 0.
 
        ESI = EDI = 0.
 
        EBP = 0.
 
        [ESP+0] =  Return  address to  routine  which  calls
        DosExit(1,EAX).
 
        [ESP+4] = Module handle for program module.
 
        [ESP+8] = Reserved.
 
        [ESP+12] = Environment data object address.
 
        [ESP+16]  =  Command  line  linear  address  in
        environment data object.
 
 
    Library initialization registers are defined as follows.
 
        EIP = Library entry address.
 
        ESP = User program stack.
 
        CS = Code selector for base of linear address space.
 
        DS = ES = SS = Data selector for base of linear
        address space.
 
        Note that a  32-bit Protected Memory Library  module
        will be  given  a  GDT  selector in  the  DS  and ES
        registers (PROTDS)  that  addresses the  full linear
        address  space  available  to  a  application.  This
        selector  should  be  saved  by  the  initialization
        routine.  Non-Protected  Memory Library modules will
        receive a selector (FLATDS) that  addresses the same
        amount of linear address space as an application's
        .EXE can.
 
        FS  = Data selector  of base  of  Thread Information
        Block (TIB).
 
        GS = 0.
 
        EAX = EBX = 0.
 
        ECX = EDX = 0.
 
        ESI = EDI = 0.
 
        EBP = 0.
 
        [ESP+0] = Return address to system, (EAX)  =  return
        code.
 
        [ESP+4] = Module handle for library module.
 
        [ESP+8] = 0 (Initialization)
 
    Note that a  32-bit  library may specify  that its entry
    address is  in  a 16-bit code object.  In this case, the
    entry registers are the same  as for  entry to a library
    using the Segmented  EXE format.  These  are  documented
    elsewhere.  This  means  that  a  16-bit  library may be
    relinked to take advantage of the benefits of the Linear
    EXE format (notably, efficient paging).
 
 
    Library termination registers are defined as follows.
 
        EIP = Library entry address.
 
        ESP = User program stack.
 
        CS = Code selector for base of linear address space.
 
        DS  =  ES  = SS  = Data  selector for base of linear
        address space.
 
        FS  =  Data  selector of base of  Thread Information
        Block (TIB).
 
        GS = 0.
 
        EAX = EBX = 0.
 
        ECX = EDX = 0.


        ESI = EDI = 0.
Note that a 32-bit Protected Memory Library module will be given a GDT selector in the DS and ES registers (PROTDS) that addresses the full linear address space available to a application. This selector should be saved by the initialization routine. Non-Protected Memory Library modules will receive a selector (FLATDS) that addresses the same amount of linear address space as an application's .EXE can.


        EBP = 0.
:FS = Data selector of base of Thread Information Block (TIB).
:GS = 0.
:EAX = EBX = 0.
:ECX = EDX = 0.
:ESI = EDI = 0.
:EBP = 0.
:[ESP+0] = Return address to system, (EAX) = return code.
:[ESP+4] = Module handle for library module.
:[ESP+8] = 0 (Initialization)


        [ESP+0] = Return address to system.
Note that a 32-bit library may specify that its entry address is in a 16-bit code object. In this case, the entry registers are the same as for entry to a library using the Segmented EXE format. These are documented elsewhere. This means that a 16-bit library may be relinked to take advantage of the benefits of the Linear EXE format (notably, efficient paging).


        [ESP+4] = Module handle for library module.
Library termination registers are defined as follows.
:EIP = Library entry address.
:ESP = User program stack.
:CS = Code selector for base of linear address space.
:DS = ES = SS = Data selector for base of linear address space.
:FS = Data selector of base of Thread Information Block (TIB).
:GS = 0.
:EAX = EBX = 0.
:ECX = EDX = 0.
:ESI = EDI = 0.
:EBP = 0.
:[ESP+0] = Return address to system.
:[ESP+4] = Module handle for library module.
:[ESP+8] = 1 (Termination)


        [ESP+8] = 1 (Termination)
Note that Library termination is not allowed for libraries with 16-bit entries.
 
Note that Library termination is not allowed for libraries with 16-bit entries.


==Object Table==
==Object Table==
The number of entries in the Object Table is given by the # Objects in Module field in the linear EXE header. Entries in the Object Table are numbered starting from one.
The number of entries in the Object Table is given by the # Objects in Module field in the linear EXE header. Entries in the Object Table are numbered starting from one.


Each Object Table entry has the following format:
Each Object Table entry has the following format:
    +-----+-----+-----+-----+-----+-----+-----+-----+
00h |    VIRTUAL SIZE      |    RELOC BASE ADDR    |
    +-----+-----+-----+-----+-----+-----+-----+-----+
08h |    OBJECT FLAGS      |    PAGE TABLE INDEX  |
    +-----+-----+-----+-----+-----+-----+-----+-----+
10h |  # PAGE TABLE ENTRIES |      RESERVED        |
    +-----+-----+-----+-----+-----+-----+-----+-----+
;VIRTUAL SIZE = DD  Virtual memory size.
This is the size of the object that will be allocated when the object is loaded. The object's virtual size (rounded up to the page size value) must be greater than or equal to the total size of the pages in the EXE file for the object. This memory size must also be large enough to contain all of the iterated data and uninitialized data in the EXE file.


          +-----+-----+-----+-----+-----+-----+-----+-----+
;RELOC BASE ADDR = DD Relocation Base Address.
      00h |    VIRTUAL SIZE      |    RELOC BASE ADDR    |
The relocation base address the object is currently relocated to. If the internal relocation fixups for the module have been removed, this is the address the object will be allocated at by the loader.
          +-----+-----+-----+-----+-----+-----+-----+-----+
      08h |    OBJECT FLAGS      |    PAGE TABLE INDEX  |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      10h |  # PAGE TABLE ENTRIES |      RESERVED        |
          +-----+-----+-----+-----+-----+-----+-----+-----+
 
    VIRTUAL SIZE = DD  Virtual memory size.
        This  is  the  size  of  the  object  that  will  be
        allocated  when the object is loaded.  The  object's
        virtual  size (rounded  up to  the page  size value)
        must be  greater than or equal to the total  size of
        the  pages  in the  EXE  file  for the object.  This
        memory size must also be large enough to contain all
        of the iterated data and uninitialized  data in  the
        EXE file.
 
    RELOC BASE ADDR = DD Relocation Base Address.
        The relocation base address the object is currently
        relocated to. If the internal relocation fixups for
        the module have been removed, this is the address
        the object will be allocated at by the loader.
 
    OBJECT FLAGS = DW  Flag bits for the object.
        The object flag bits have the following definitions.
 
            0001h = Readable Object.
            0002h = Writable Object.
            0004h = Executable Object.
                The readable,  writable and executable flags
                provide    support    for    all    possible
                protections.  In systems where  all of these
                protections are not  supported,  the  loader
                will  be  responsible  for  making  the
                appropriate protection match for the system.
 
            0008h = Resource Object.
            0010h = Discardable Object.
            0020h = Object is Shared.
            0040h = Object has Preload Pages.
            0080h = Object has Invalid Pages.
            0100h = Object has Zero Filled Pages.
            0200h = Object is Resident (valid for VDDs, PDDs
            only).
            0300h = Object is Resident  &  Contiguous (VDDs,
            PDDs only).
            0400h  =  Object is  Resident  & 'long-lockable'
            (VDDs, PDDs only).
            0800h = Reserved for system use.
            1000h = 16:16 Alias Required (80x86 Specific).
            2000h  =  Big/Default  Bit  Setting  (80x86
            Specific).
                The 'big/default'  bit , for data  segments,
                controls the setting of the Big  bit  in the
                segment descriptor.  (The Big bit, or B-bit,
                determines whether ESP or SP is used  as the
                stack pointer.)  For code segments, this bit
                controls the setting of the  Default  bit in
                the segment descriptor.  (The  Default  bit,
                or  D-bit, determines  whether  the  default
                word  size  is 32-bits or 16-bits.  It  also
                affects  the    interpretation    of    the
                instruction stream.)


            4000h = Object is conforming for code (80x86
;OBJECT FLAGS = DW  Flag bits for the object.
            Specific).
The object flag bits have the following definitions.
            8000h = Object I/O privilege   level (80x86
:0001h = Readable Object.
            Specific).
:0002h = Writable Object.
                Only used for 16:16 Alias Objects.
:0004h = Executable Object.
The readable, writable and executable flags provide support for all possible protections. In systems where all of these protections are not supported, the loader will be responsible for making the appropriate protection match for the system.
:0008h = Resource Object.
:0010h = Discardable Object.
:0020h = Object is Shared.
:0040h = Object has Preload Pages.
:0080h = Object has Invalid Pages.
:0100h = Object has Zero Filled Pages.
:0200h = Object is Resident (valid for VDDs, PDDs only).
:0300h = Object is Resident & Contiguous (VDDs, PDDs only).
:0400h = Object is Resident & 'long-lockable' (VDDs, PDDs only).
:0800h = Reserved for system use.
:1000h = 16:16 Alias Required (80x86 Specific).
:2000h = Big/Default Bit Setting (80x86 Specific).
The 'big/default' bit, for data segments, controls the setting of the Big bit in the segment descriptor. (The Big bit, or B-bit, determines whether ESP or SP is used as the stack pointer.) For code segments, this bit controls the setting of the Default bit in the segment descriptor. (The Default bit, or D-bit, determines whether the default word size is 32-bits or 16-bits. It also affects the interpretation of the instruction stream.)
:4000h = Object is conforming for code (80x86 Specific).
:8000h = Object I/O privilege level (80x86 Specific). Only used for 16:16 Alias Objects.


    PAGE TABLE INDEX = DD  Object Page Table Index.
;PAGE TABLE INDEX = DD  Object Page Table Index.
        This specifies the number of the first object page
This specifies the number of the first object page table entry for this object. The object page table specifies where in the EXE file a page can be found for a given object and specifies per-page attributes.
        table entry for this object. The object page table
        specifies where in the EXE file a page can be found
        for   a   given   object   and   specifies per-page
        attributes.


        The object table entries are ordered by logical page
The object table entries are ordered by logical page in the object table. In other words the object table entries are sorted based on the object page table index value.
        in the object table. In other words the object
        table entries are sorted based on the object page
        table index value.


     # PAGE TABLE ENTRIES = DD  # of object page table
     # PAGE TABLE ENTRIES = DD  # of object page table
     entries for this object.
     entries for this object.
         Any logical pages at the end of an object that do
         Any logical pages at the end of an object that do
         not have an   entry   in the object page table
         not have an entry in the object page table
         associated with them are handled as zero filled or
         associated with them are handled as zero filled or
         invalid pages by the loader.
         invalid pages by the loader.


         When the last logical pages of an object are not
         When the last logical pages of an object are not
         specified with an object page table entry, they are
         specified with an object page table entry, they are
         treated as either zero filled pages or invalid pages
         treated as either zero filled pages or invalid pages
         based on the last entry in the object page table for
         based on the last entry in the object page table for
         that object. If the last entry was neither a zero
         that object. If the last entry was neither a zero
         filled or invalid page, then the additional pages
         filled or invalid page, then the additional pages
         are treated as zero filled pages.
         are treated as zero filled pages.


    RESERVED = DD  Reserved for future use. Must be set to
RESERVED = DD  Reserved for future use. Must be set to zero.
    zero.


==Object Page Table==
==Object Page Table==
The Object page table provides information about a logical
The Object page table provides information about a logical page in an object. A logical page may be an enumerated page, a pseudo page or an iterated page. The structure of the object page table in conjunction with the structure of the object table allows for efficient access of a page when a page fault occurs, while still allowing the physical page data to be located in the preload page, demand load page or iterated data page sections in the linear EXE module. The logical page entries in the Object Page Table are numbered starting from one. The Object Page Table is parallel to the Fixup Page Table as they are both indexed by the logical page number.
page in an object. A logical page may be an enumerated
page, a pseudo page or an iterated page. The structure of
the object page table in conjunction with the structure of
the object table allows for efficient access of a page when
a page fault occurs, while still allowing the physical page
data to be located in the preload page, demand load page or
iterated data page sections in the linear EXE module. The
logical page entries in the Object Page Table are numbered
starting from one. The Object Page Table is parallel to the
Fixup Page Table as they are both indexed by the logical
page number.


Each Object Page Table entry has the following format:
Each Object Page Table entry has the following format:
    63                    32 31      16 15        0
    +-----+-----+-----+-----+-----+-----+-----+-----+
00h |    PAGE DATA OFFSET  | DATA SIZE |  FLAGS  |
    +-----+-----+-----+-----+-----+-----+-----+-----+


          63                    32 31      16 15        0
;PAGE DATA OFFSET = DD:Offset to the page data in the EXE file.
          +-----+-----+-----+-----+-----+-----+-----+-----+
This field, when bit shifted left by the PAGE OFFSET SHIFT from the module header, specifies the offset from the beginning of the Preload Page section of the physical page data in the EXE file that corresponds to this logical page entry. The page data may reside in the Preload Pages, Demand Load Pages or the Iterated Data Pages sections.
      00h |    PAGE DATA OFFSET   | DATA SIZE |  FLAGS  |
          +-----+-----+-----+-----+-----+-----+-----+-----+


    PAGE DATA OFFSET = DD  Offset  to  the page  data in the
If the FLAGS field specifies that this is a zero-Filled page then the PAGE DATA OFFSET field
    EXE file.
will contain a 0.
        This field, when bit shifted left by the PAGE OFFSET
        SHIFT from the  module header, specifies the offset
        from  the beginning of  the Preload Page section  of
        the  physical  page  data  in  the  EXE  file  that
        corresponds to this logical  page  entry.  The  page
        data  may  reside in the Preload Pages, Demand Load
        Pages or the Iterated Data Pages sections.


        If the FLAGS field specifies that  this  is  a
If the logical page is specified as an iterated data page, as indicated by the FLAGS field, then this field specifies the offset into the Iterated Data Pages section.
        zero-Filled page  then the PAGE DATA  OFFSET  field
        will contain a 0.


        If the logical page is specified as an iterated data
The logical page number (Object Page Table index), is used to index the Fixup Page Table to find any fixups associated with the logical page.
        page,  as  indicated  by the FLAGS field, then  this
        field specifies the offset into the  Iterated  Data
        Pages section.


        The logical page number (Object Page Table index),
;DATA SIZE = DW
        is  used  to index  the Fixup Page Table to find any
:Number of bytes of data for this page.
        fixups associated with the logical page.
This field specifies the actual number of bytes that represent the page in the file. If the PAGE SIZE field from the module header is greater than the value of this field and the FLAGS field indicates a Legal Physical Page, the remaining bytes are to be filled with zeros. If the FLAGS field indicates an Iterated Data Page, the iterated data records will completely fill out the remainder.


 
;FLAGS = DW
    DATA SIZE = DW Number of bytes of data for this page.
:Attributes specifying characteristics of this logical page.
        This field specifies the actual number of bytes that
The bit definitions for this word field follow,
        represent the page in  the  file.  If  the PAGE SIZE
:00h = Legal Physical Page in the module (Offset from Preload Page Section).
        field  from the  module header is greater  than  the
:01h = Iterated Data Page (Offset from Iterated Data Pages Section).
        value of this  field and the FLAGS field indicates a
:02h = Invalid Page (zero).
        Legal Physical  Page,  the remaining bytes are to be
:03h = Zero Filled Page (zero).
        filled with zeros.  If  the FLAGS field indicates an
:04h = Range of Pages.
        Iterated  Data Page,  the iterated data records will
        completely fill out the remainder.
 
 
    FLAGS =  DW  Attributes specifying characteristics of
    this logical page.
        The bit definitions for this word field follow,
 
            00h = Legal Physical Page in the module (Offset
            from Preload Page Section).
            01h = Iterated Data Page (Offset from Iterated
            Data Pages Section).
            02h = Invalid Page (zero).
            03h = Zero Filled Page (zero).
            04h = Range of Pages.


==Resource Table==
==Resource Table==
The resource table is an array of resource table entries.
The resource table is an array of resource table entries. Each resource table entry contains a type ID and name ID. These entries are used to locate resource objects contained in the Object table. The number of entries in the resource table is defined by the Resource Table Count located in the linear EXE header. More than one resource may be contained within a single object. Resource table entries are in a sorted order, (ascending, by Resource Name ID within the Resource Type ID). This allows the DosGetResource API function to use a binary search when looking up a resource in a 32-bit module instead of the linear search being used
Each resource table entry contains a type ID and name ID.
in the current 16-bit module.
These entries are used to locate resource objects contained
in the Object table. The number of entries in the resource
table is defined by the Resource Table Count located in the
linear EXE header. More than one resource may be contained
within a single object. Resource table entries are in a
sorted order, (ascending, by Resource Name ID within the
Resource Type ID). This allows the DosGetResource API
function to use a binary search when looking up a resource
in a 32-bit module instead of the linear search being used
in the current 16-bit module.


Each resource entry has the following format:
Each resource entry has the following format:
    +-----+-----+-----+-----+
00h |  TYPE ID  |  NAME ID  |
    +-----+-----+-----+-----+
04h |    RESOURCE SIZE    |
    +-----+-----+-----+-----+-----+-----+
08h |  OBJECT  |        OFFSET        |
    +-----+-----+-----+-----+-----+-----+


          +-----+-----+-----+-----+
;TYPE ID = DW:Resource type ID.
      00h |  TYPE ID  |  NAME ID  |
:The type of resources are:
          +-----+-----+-----+-----+
::BTMP = Bitmap
      04h |    RESOURCE SIZE    |
::EMSG = Error message string
          +-----+-----+-----+-----+-----+-----+
::FONT = Fonts
      08h |  OBJECT  |        OFFSET        |
;NAME ID = DW:An ID used as a name for the resource when referred to.
          +-----+-----+-----+-----+-----+-----+
;RESOURCE SIZE = DD:The number of bytes the resource consists of.
 
;OBJECT = DW:The number of the object which contains the resource.
 
;OFFSET = DD:The offset within the specified object where the resource begins.
    TYPE ID = DW Resource type ID.
        The type of resources are:
 
            BTMP = Bitmap
            EMSG = Error message string
            FONT = Fonts
 
    NAME ID = DW An ID used as a name for the resource when
    referred to.
 
    RESOURCE SIZE = DD The number of bytes the resource
    consists of.
 
    OBJECT = DW The number of the object which contains the
    resource.
 
    OFFSET = DD The offset within the specified object
    where the resource begins.


==Resident or Non-resident Name Table Entry==
==Resident or Non-resident Name Table Entry==
The resident and non-resident name tables define the ASCII names and ordinal numbers for exported entries in the module. In addition the first entry in the resident name table contains the module name. These tables are used to translate a procedure name string into an ordinal number by searching for a matching name string. The ordinal number is used to locate the entry point information in the entry table.
The resident and non-resident name tables define the ASCII names and ordinal numbers for exported entries in the module. In addition the first entry in the resident name table contains the module name. These tables are used to translate a procedure name string into an ordinal number by searching for a matching name string. The ordinal number is used to locate the entry point information in the entry table.


The resident name table is kept resident in system memory while the module is loaded. It is intended to contain the exported entry point names that are frequently dynamicaly linked to by name. Non-resident names are not kept in memory and are read from the EXE file when a dynamic link reference is made. Exported entry point names that are infrequently dynamicaly linked to by name or are commonly referenced by ordinal number should be placed in the non-resident name table. The trade off made for references by name is performance vs memory usage.
The resident name table is kept resident in system memory while the module is loaded. It is intended to contain the exported entry point names that are frequently dynamically linked to by name. Non-resident names are not kept in memory and are read from the EXE file when a dynamic link reference is made. Exported entry point names that are infrequently dynamically linked to by name or are commonly referenced by ordinal number should be placed in the non-resident name table. The trade off made for references by name is performance vs memory usage.


Import references by name require these tables to be searched to obtain the entry point ordinal number. Import references by ordinal number provide the fastest lookup since the search of these tables is not required.
Import references by name require these tables to be searched to obtain the entry point ordinal number. Import references by ordinal number provide the fastest lookup since the search of these tables is not required.
Line 752: Line 541:


Each name table entry has the following format:
Each name table entry has the following format:
     +-----+-----+-----+-----+    +-----+-----+-----+
     +-----+-----+-----+-----+    +-----+-----+-----+
  00h | LEN |    ASCII STRING  . . .      | ORDINAL # |
  00h | LEN |    ASCII STRING  . . .      | ORDINAL # |
Line 760: Line 548:
:This defines the length of the string in bytes. A zero length indicates there are no more entries in table. The length of each ascii name string is limited to 127 characters.
:This defines the length of the string in bytes. A zero length indicates there are no more entries in table. The length of each ascii name string is limited to 127 characters.


:The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.
:The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.


;ASCII STRING = DB  ASCII String.
;ASCII STRING = DB  ASCII String.
Line 769: Line 557:


==Entry Table==
==Entry Table==
The entry table contains object and offset information that is used to resolve fixup references to the entry points within this module. Not all entry points in the entry table will be exported, some entry points will only be used within the module. An ordinal number is used to index into the entry table. The entry table entries are numbered starting from one.
The entry table contains object and offset information that is used to resolve fixup references to the entry points within this module. Not all entry points in the entry table will be exported, some entry points will only be used within the module. An ordinal number is used to index into the entry table. The entry table entries are numbered starting from one.


The list of entries are compressed into 'bundles', where possible. The entries within each bundle are all the same size. A bundle starts with a count field which indicates the number of entries in the bundle. The count is followed by a type field which identifies the bundle format. This provides both a means for saving space as well as a mechanism for extending the bundle types.
The list of entries are compressed into 'bundles', where possible. The entries within each bundle are all the same size. A bundle starts with a count field which indicates the number of entries in the bundle. The count is followed by a type field which identifies the bundle format. This provides both a means for saving space as well as a mechanism for extending the bundle types.


The type field allows the definition of 256 bundle types.
The type field allows the definition of 256 bundle types. The following bundle types will initially be defined:
The following bundle types will initially be defined:
:Unused Entry.
Unused Entry.
:16-bit Entry.
16-bit Entry.
:286 Call Gate Entry.
286 Call Gate Entry.
:32-bit Entry.
32-bit Entry.
:Forwarder Entry.
Forwarder Entry.
 
The bundled entry table has the following format:
The bundled entry table has the following format:
    +-----+-----+-----+-----+-----+
00h | CNT |TYPE | BUNDLE INFO . . .
    +-----+-----+-----+-----+-----+
;CNT = DB  Number of entries.
:This is the number of entries in this bundle.


          +-----+-----+-----+-----+-----+
A zero value for the number of entries identifies the end of the entry table. There is no further bundle information when the number of entries is zero. In other words the entry table is terminated by a single zero byte.
      00h | CNT |TYPE | BUNDLE INFO . . .
          +-----+-----+-----+-----+-----+
 
 
    CNT = DB  Number of entries.
        This is the number of entries in this bundle.
 
        A zero value for the number of entries identifies
        the end of the entry table. There is no further
        bundle information when the number of entries is
        zero. In other words the entry table is terminated
        by a single zero byte.
 
    TYPE = DB  Bundle type.
        This  defines the  bundle type  which determines the
        contents of the BUNDLE INFO.


            The follow types are defined:
;TYPE = DB  Bundle type.
This defines the bundle type which determines the contents of the BUNDLE INFO.


                00h = Unused Entry.
The follow types are defined:
                01h = 16-bit Entry.
:00h = Unused Entry.
                02h = 286 Call Gate Entry.
:01h = 16-bit Entry.
                03h = 32-bit Entry.
:02h = 286 Call Gate Entry.
                04h = Forwarder Entry.
:03h = 32-bit Entry.
                80h = Parameter Typing Information Present.
:04h = Forwarder Entry.
                    This   bit signifies   that additional
:80h = Parameter Typing Information Present.
                    information is contained in the linear
This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.
                    EXE module and will be used in the
                    future for parameter type checking.


The following is the format for each bundle type:
    +-----+-----+
00h | CNT |TYPE |
    +-----+-----+


    The following is the format for each bundle type:
;CNT = DB  Number of entries.
This is the number of unused entries to skip.


              +-----+-----+
;TYPE = DB  0 (Unused Entry)
          00h | CNT |TYPE |
    +-----+-----+-----+-----+
              +-----+-----+
00h | CNT |TYPE |  OBJECT  |
    +-----+-----+-----+-----+
      04h |FLAGS|  OFFSET  |
          +-----+-----+-----+
      07h | ... |  . . .  |
          +    +    +    +


        CNT = DB  Number of entries.
;CNT = DB  Number of entries.
            This is the number of unused entries to skip.
This is the number of 16-bit entries in this bundle. The flags and offset value are repeated
this number of times.


        TYPE = DB  0 (Unused Entry)
;TYPE = DB  1 (16-bit Entry)
:OBJECT = DW Object number.
::This is the object number for the entries in this bundle.


              +-----+-----+-----+-----+
:FLAGS = DB Entry flags.
          00h | CNT |TYPE |  OBJECT  |
::These are the flags for this entry point. They have the following definition.
              +-----+-----+-----+-----+
:::01h = Exported entry flag.
          04h |FLAGS| OFFSET  |
:::F8h = Parameter word count mask.
              +-----+-----+-----+
          07h | ... . . .  |
              +    +    +    +


:OFFSET = DW  Offset in object.
::This is the offset in the object for the entry point defined at this ordinal number.
    +-----+-----+-----+-----+
00h | CNT |TYPE |  OBJECT  |
    +-----+-----+-----+-----+-----+
04h |FLAGS|  OFFSET  | CALLGATE  |
    +-----+-----+-----+-----+-----+
09h | ... |  . . .  |  . . .  |
    +    +    +    +    +    +


        CNT = DB  Number of entries.
:CNT = DB  Number of entries.
            This is the number of 16-bit  entries in this
::This is the number of 286 call gate entries in this bundle. The flags, callgate, and offset value are repeated this number of times.
            bundle. The flags and offset value are repeated
            this number of times.


        TYPE = DB  1 (16-bit Entry)
:TYPE = DB  2 (286 Call Gate Entry)
::The 286 Call Gate Entry Point type is needed by the loader only if ring 2 segments are to be supported. 286 Call Gate entries contain 2 extra bytes which are used by the loader to store an LDT callgate selector value.


            OBJECT = DW  Object number.
:OBJECT = DW  Object number.
                This is the object number for the entries in
::This is the object number for the entries in this bundle.
                this bundle.


            FLAGS = DB  Entry flags.
:FLAGS = DB  Entry flags.
                These are the flags for this entry point.
::These are the flags for this entry point. They have the following definition.
                They have the following definition.
:::01h = Exported entry flag.
 
:::F8h = Parameter word count mask.
                    01h = Exported entry flag.
                    F8h = Parameter word count mask.
 
            OFFSET = DW  Offset in object.
                This is the  offset  in the  object for  the
                entry point defined at this ordinal number.
 
 
              +-----+-----+-----+-----+
          00h | CNT |TYPE |  OBJECT  |
              +-----+-----+-----+-----+-----+
          04h |FLAGS|  OFFSET  | CALLGATE  |
              +-----+-----+-----+-----+-----+
          09h | ... |  . . .  |  . . .  |
              +    +    +    +    +    +
 
 
        CNT = DB  Number of entries.
            This is  the number of 286  call gate entries in
            this  bundle.  The  flags,  callgate, and offset
            value are repeated this number of times.
 
        TYPE = DB  2 (286 Call Gate Entry)
            The 286 Call Gate Entry  Point type is needed by
            the loader only  if ring  2 segments  are to  be
            supported.  286  Call  Gate  entries  contain  2
            extra bytes  which  are  used by  the  loader to
            store an LDT callgate selector value.
 
        OBJECT = DW  Object number.
            This is the  object  number  for the  entries in
            this bundle.
 
        FLAGS = DB  Entry flags.
            These are the flags  for this entry point.  They
            have the following definition.
 
                01h = Exported entry flag.
                F8h = Parameter word count mask.
 
        OFFSET = DW  Offset in object.
            This is the offset in the object  for  the entry
            point defined at this ordinal number.
 
        CALLGATE = DW  Callgate selector.
            The callgate  selector is a  reserved field used
            by the  loader  to store a  call  gate  selector
            value for references  to  ring  2  entry points.
            When a  ring 3 reference to a ring 2 entry point
            is  made,  the  callgate  selector with  a  zero
            offset is place in the relocation fixup address.
            The  segment  number  and  offset  in segment is
            placed in the LDT callgate.


:OFFSET = DW  Offset in object.
::This is the offset in the object for the entry point defined at this ordinal number.


:CALLGATE = DW  Callgate selector.
::The callgate selector is a reserved field used by the loader to store a call gate selector value for references to ring 2 entry points. When a ring 3 reference to a ring 2 entry point is made, the callgate selector with a zero offset is place in the relocation fixup address. The segment number and offset in segment is placed in the LDT callgate.
               +-----+-----+-----+-----+
               +-----+-----+-----+-----+
           00h | CNT |TYPE |  OBJECT  |
           00h | CNT |TYPE |  OBJECT  |
Line 913: Line 655:
               +    +    +    +    +    +
               +    +    +    +    +    +


        CNT = DB  Number of entries.
:CNT = DB  Number of entries.
            This is the number of 32-bit entries in this
::This is the number of 32-bit entries in this bundle. The flags and offset value are repeated this number of times.
            bundle. The flags and offset value are repeated
            this number of times.


        TYPE = DB  3 (32-bit Entry)
:TYPE = DB  3 (32-bit Entry)
            The 32-bit Entry type will only be defined by
::The 32-bit Entry type will only be defined by the linker when the offset in the object can not be specified by a 16-bit offset.
            the linker when the offset in the object can not
            be specified by a 16-bit offset.


        OBJECT = DW Object number.
:OBJECT = DW Object number.
            This is the object number for the entries in
::This is the object number for the entries in this bundle.
            this bundle.


        FLAGS = DB  Entry flags.
:FLAGS = DB  Entry flags.
            These are the flags for this entry point. They
::These are the flags for this entry point. They have the following definition.
            have the following definition.
:::01h = Exported entry flag.
 
:::F8h = Parameter dword count mask.
                01h = Exported entry flag.
                F8h = Parameter dword count mask.
 
        OFFSET = DD  Offset in object.
            This is  the  offset in the object for the entry
            point defined at this ordinal number.


:OFFSET = DD  Offset in object.
::This is the offset in the object for the entry point defined at this ordinal number.
           +-----+-----+-----+-----+
           +-----+-----+-----+-----+
       00h | CNT |TYPE | RESERVED  |
       00h | CNT |TYPE | RESERVED  |
Line 946: Line 679:
           +    +    +    +    +    +    +    +
           +    +    +    +    +    +    +    +


    CNT = DB  Number of entries.
:CNT = DB  Number of entries.
        This is the number of forwarder entries in this
::This is the number of forwarder entries in this bundle. The FLAGS, MOD ORD#, and OFFSET/ORDNUM values are repeated this number of times.
        bundle. The FLAGS, MOD ORD#, and OFFSET/ORDNUM
        values are repeated this number of times.


    TYPE = DB  4 (Forwarder Entry)
:TYPE = DB  4 (Forwarder Entry)


    RESERVED = DW 0
:RESERVED = DW 0
        This field is reserved for future use.
::This field is reserved for future use.


    FLAGS = DB  Forwarder flags.
:FLAGS = DB  Forwarder flags.
        These are the flags for this entry point. They
:These are the flags for this entry point. They have the following definition.
        have the following definition.
::01h = Import by ordinal.
::F7h = Reserved for future use; should be zero.


            01h = Import by ordinal.
;MOD ORD# = DW Module Ordinal Number
            F7h = Reserved for future use; should be zero.
This is the index into the Import Module Name Table for this forwarder.


    MOD ORD# = DW Module Ordinal Number
;OFFSET/ORDNUM = DD Procedure Name Offset or Import Ordinal Number
        This  is the index into the Import Module Name Table
If the FLAGS field indicates import by ordinal, then this field is the ordinal number into the Entry Table of the target module, otherwise this field is the offset into the Procedure Names Table of the target module.
        for this forwarder.


    OFFSET  /  ORDNUM = DD Procedure  Name Offset  or Import
A Forwarder entry (type = 4) is an entry point whose value is an imported reference. When a load time fixup occurs whose target is a forwarder, the loader obtains the address imported by the forwarder and uses that imported address to resolve the fixup.
    Ordinal Number
        If the FLAGS field indicates import by ordinal, then
        this field  is the  ordinal number  into  the Entry
        Table of the target module, otherwise this  field is
        the offset  into the Procedure Names Table  of  the
        target module.


A Forwarder entry (type  = 4) is  an entry point whose value
A forwarder may refer to an entry point in another module which is itself a forwarder, so there can be a chain of forwarders. The loader will traverse the chain until it finds a non-forwarded entry point which terminates the chain, and use this to resolve the original fixup. Circular chains are detected by the loader and result in a load time error. A maximum of 1024 forwarders is allowed in a chain; more than this results in a load time error.
is an imported  reference.  When  a load  time  fixup occurs
whose target is a forwarder, the  loader obtains the address
imported by the forwarder and uses that imported address to
resolve the fixup.


A forwarder  may refer  to an entry point  in another module
Forwarders are useful for merging and recombining API calls into different sets of libraries, while maintaining compatibility with applications. For example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a single libraries, one could provide entry points for the three libraries that are forwarders pointing to the common implementation.
which  is itself a  forwarder, so there  can be a  chain  of
forwarders.  The  loader  will traverse the chain  until  it
finds a non-forwarded entry point which terminates the chain
,  and  use  this to  resolve  the original fixup.  Circular
chains are detected by the loader  and result in a load time
error.  A  maximum of 1024 forwarders is allowed in a chain;
more than this results in a load time error.
 
Forwarders are useful for merging and recombining API calls
into different sets   of   libraries,   while maintaining
compatibility with applications. For example, if one wanted
to combine MONCALLS, MOUCALLS, and VIOCALLS into a single
libraries, one could provide entry points for the three
libraries that   are forwarders pointing to the common
implementation.


==Module Format Directives Table==
==Module Format Directives Table==
The Module Format Directives Table is an optional table that
The Module Format Directives Table is an optional table that allows additional options to be specified. It also allows for the extension of the linear EXE format by allowing additional tables of information to be added to the linear EXE module without affecting the format of the linear EXE header. Likewise, module format directives provide a place in the linear EXE module for 'temporary tables' of information, such as incremental linking information and statistic information gathered on the module. When there are no module format directives for a linear EXE module, the fields in the linear EXE header referencing the module format directives table are zero.
allows additional options to be specified. It also allows
for the extension of the linear EXE format by allowing
additional tables of information to be added to the linear
EXE module without affecting the format of the linear EXE
header. Likewise, module format directives provide a place
in   the   linear EXE module for 'temporary tables' of
information, such as incremental linking information and
statistic information gathered on the module. When there
are no module format directives for a linear EXE module, the
fields in the linear EXE header referencing the module
format directives table are zero.


Each Module Format Directive Table entry has the following
Each Module Format Directive Table entry has the following format:
format:
    +-----+-----+-----+-----+-----+-----+----+----+
 
00h | DIRECT #  | DATA LEN  |    DATA OFFSET    |
          +-----+-----+-----+-----+-----+-----+----+----+
    +-----+-----+-----+-----+-----+-----+----+----+
      00h | DIRECT #  | DATA LEN  |    DATA OFFSET    |
;DIRECT # = DW  Directive number.
          +-----+-----+-----+-----+-----+-----+----+----+
:The directive number specifies the type of directive defined. This can be used to determine the format of the information in the directive data. The following directive numbers have been defined:
 
::8000h = Resident Flag Mask.
    DIRECT # = DW  Directive number.
:::Directive numbers with this bit set indicate that the directive data is in the resident area and will be kept resident in memory when the module is loaded.
        The directive number specifies the type of directive
::8001h = Verify Record Directive. (Verify record is a resident table.)
        defined. This can be used to determine the format
::0002h = Language Information Directive. (This is a non-resident table.)
        of the information in the directive data. The
::0003h = Co-Processor Required Support Table.
        following directive numbers have been defined:
::0004h = Thread State Initialization Directive.
 
:Additional directives can be added as needed in the future, as long as they do not overlap previously defined directive numbers.
            8000h = Resident Flag Mask.
;DATA LEN = DW Directive data length.
                Directive numbers with this bit set indicate
:This specifies the length in byte of the directive data for this directive number.
                that the directive data is in the resident
;DIRECTIVE OFFSET = DD Directive data offset.
                area and will be kept resident in memory
:This is the offset to the directive data for this directive number. It is relative to beginning of linear EXE header for a resident table, and relative to the beginning of the EXE file for non-resident tables.
                when the module is loaded.
 
            8001h = Verify Record Directive. (Verify record
            is a resident table.)
            0002h = Language Information Directive. (This is
            a non-resident table.)
            0003h = Co-Processor Required Support Table.
            0004h = Thread State Initialization Directive.
 
        Additional directives can be added as needed in the
        future, as long as they do not overlap previously
        defined directive numbers.
 
    DATA LEN = DW Directive data length.
        This specifies the length in byte of the directive
        data for this directive number.
 
    DIRECTIVE OFFSET = DD Directive data offset.
        This is the offset to the directive data for this
        directive number. It is relative to beginning of
        linear EXE header for a resident table, and relative
        to the beginning of the EXE file for non-resident
        tables.


==Verify Record Directive Table==
==Verify Record Directive Table==
The Verify Record Directive Table is an optional table. It
The Verify Record Directive Table is an optional table. It maintains a record of the pages in the EXE file that have been fixed up and written back to the original linear EXE module, along with the module dependencies used to perform these fixups. This table provides an efficient means for verifying the virtual addresses required for the fixed up pages when the module is loaded.
maintains a record of the pages in the EXE file that have
been fixed up and written back to the original linear EXE
module, along with the module dependencies used to perform
these fixups. This table provides an efficient means for
verifying the virtual addresses required for the fixed up
pages when the module is loaded.


Each Verify Record entry has the following format:
Each Verify Record entry has the following format:
    +-----+-----+
00h |# OF ENTRY |
    +-----+-----+-----+-----+-----+-----+
02h | MOD ORD # |  VERSION  | MOD # OBJ |
    +-----+-----+-----+-----+-----+-----+
08h | OBJECT #  | BASE ADDR |  VIRTUAL  |
    +-----+-----+-----+-----+-----+-----+
0Eh |  . . .  |  . . .  |  . . .  |
    +    +    +    +    +    +    +


          +-----+-----+
  # OF ENTRY = DW  Number of module dependencies.
      00h |# OF ENTRY |
         This field specifies how many entries there are in
          +-----+-----+-----+-----+-----+-----+
         the verify record directive table. This is equal to
      02h | MOD ORD # |  VERSION  | MOD # OBJ |
          +-----+-----+-----+-----+-----+-----+
      08h | OBJECT #  | BASE ADDR |  VIRTUAL |
          +-----+-----+-----+-----+-----+-----+
      0Eh |  . . .  |  . . .  |  . . .  |
          +    +    +    +    +    +    +
 
    # OF ENTRY = DW  Number of module dependencies.
         This field specifies how many entries there are in
         the verify record directive table. This is equal to
         the number of modules referenced by this module.
         the number of modules referenced by this module.


     MOD  ORD # = DW  Ordinal index into the Import Module
     MOD  ORD # = DW  Ordinal index into the Import Module
     Name Table.
     Name Table.
         This value is an ordered index in to the Import
         This value is an ordered index in to the Import
         Module Name Table for the referenced module.
         Module Name Table for the referenced module.


     VERSION = DW  Module Version.
     VERSION = DW  Module Version.


         This is the version of the referenced module that
         This is the version of the referenced module that
         the fixups were originally performed. This is used
         the fixups were originally performed. This is used
         to insure the same version of the referenced module
         to insure the same version of the referenced module
         is loaded that was fixed up in this module and
         is loaded that was fixed up in this module and
         therefore   the   fixups are still correct. This
         therefore the fixups are still correct. This
         requires the version number in a module to be
         requires the version number in a module to be
         incremented anytime the entry point offsets change.
         incremented anytime the entry point offsets change.


     MOD # OBJ = DW  Module # of Object Entries.
     MOD # OBJ = DW  Module # of Object Entries.
         This field is used to identify the number of object
         This field is used to identify the number of object
         verify entries that   follow for the referenced
         verify entries that follow for the referenced
         module.
         module.


     OBJECT # = DW  Object # in Module.
     OBJECT # = DW  Object # in Module.
         This field specifies the object number in the
         This field specifies the object number in the
         referenced module that is being verified.
         referenced module that is being verified.


     BASE ADDR = DW  Object load base address.
     BASE ADDR = DW  Object load base address.
         This is the address that the object was loaded at
         This is the address that the object was loaded at
         when the fixups were performed.
         when the fixups were performed.


     VIRTUAL = DW  Object virtual address size.
     VIRTUAL = DW  Object virtual address size.
         This field specifies the total amount of virtual
         This field specifies the total amount of virtual
         memory required for this object.
         memory required for this object.


==Per-Page Checksum==
==Per-Page Checksum==
The Per-Page   Checksum   table   provides   space   for a
The Per-Page Checksum table provides space for a cryptographic checksum for each physical page in the EXE file.
cryptographic checksum for each physical page in the EXE
file.


The checksum table is arranged such that the first entry in
The checksum table is arranged such that the first entry in the table corresponds to the first logical page of code/data in the EXE file (usually a preload page) and the last entry corresponds to the last logical page in the EXE file (usually a iterated data page).
the table corresponds to the first logical page of code/data
                  +-----+-----+-----+-----+
in the EXE file (usually a preload page) and the last entry
Logical Page #1  |        CHECKSUM      |
corresponds to the last logical page in the EXE file
                  +-----+-----+-----+-----+
(usually a iterated data page).
Logical Page #2  |        CHECKSUM      |
                  +-----+-----+-----+-----+
                            . . .
                  +-----+-----+-----+-----+
Logical Page #n  |        CHECKSUM      |
                  +-----+-----+-----+-----+


                    +-----+-----+-----+-----+
  CHECKSUM = DD  Cryptographic checksum.
    Logical Page #1  |        CHECKSUM      |
                    +-----+-----+-----+-----+
    Logical Page #2  |        CHECKSUM      |
                    +-----+-----+-----+-----+
                              . . .
 
                    +-----+-----+-----+-----+
    Logical Page #n  |        CHECKSUM      |
                    +-----+-----+-----+-----+
 
 
    CHECKSUM = DD  Cryptographic checksum.


==Fixup Page Table==
==Fixup Page Table==
The Fixup Page Table provides a simple mapping of a logical
The Fixup Page Table provides a simple mapping of a logical page number to an offset into the Fixup Record Table for that page.
page number to an offset into the Fixup Record Table for
that page.


This table is parallel to the Object Page Table, except that
This table is parallel to the Object Page Table, except that there is one additional entry in this table to indicate the end of the Fixup Record Table.
there is one additional entry in this table to indicate the
end of the Fixup Record Table.
 
The format of each entry is:


The format of each entry is:
                   +-----+-----+-----+-----+
                   +-----+-----+-----+-----+
   Logical Page #1  |  OFFSET FOR PAGE #1  |
   Logical Page #1  |  OFFSET FOR PAGE #1  |
Line 1,160: Line 812:
                                               of fixups for page #n
                                               of fixups for page #n


;OFFSET FOR PAGE # = DD Offset for fixup record for this page.
This field specifies the offset, from the beginning
of the fixup record table, to the first fixup record
for this page.


    OFFSET FOR PAGE # = DD Offset for fixup record for this
;OFF TO END OF FIXUP REC = DD Offset to the end of the fixup records.
    page.
This field specifies the offset following the last
        This field specifies the offset, from the beginning
fixup record in the fixup record table. This is the
        of the fixup record table, to the first fixup record
last entry in the fixup page table.
        for this page.


    OFF TO  END  OF FIXUP REC = DD  Offset to the end of the
The fixup records are kept in order by logical page
    fixup records.
in the fixup record table. This allows the end of
        This field specifies  the offset  following the last
each page's fixup records is defined by the offset
        fixup record in the fixup record table.  This is the
for the next logical page's fixup records. This
        last entry in the fixup page table.
last entry provides support of this mechanism for
 
the last page in the fixup page table.
        The fixup records are kept in order by logical page
        in the fixup record table. This allows the end of
        each page's fixup records is defined by the offset
        for the next logical page's fixup records. This
        last entry provides support of this mechanism for
        the last page in the fixup page table.


==Fixup Record Table==
==Fixup Record Table==
The Fixup Record Table contains entries for all fixups in
The Fixup Record Table contains entries for all fixups in the linear EXE module. The fixup records for a logical page are grouped together and kept in sorted order by logical page number. The fixups for each page are further sorted such that all external fixups and internal selector/pointer fixups come before internal non-selector/non-pointer fixups. This allows the loader to ignore internal fixups if the loader is able to load all objects at the addresses specified in the object table.
the linear EXE module. The fixup records for a logical page
are grouped together and kept in sorted order by logical
page number. The fixups for each page are further sorted
such that all external fixups and internal selector/pointer
fixups come before internal non-selector/non-pointer fixups.
This allows the loader to ignore internal fixups if the
loader is able to load all objects at the addresses
specified in the object table.
 
Each relocation record has the following format:


Each relocation record has the following format:
           +-----+-----+-----+-----+
           +-----+-----+-----+-----+
       00h | SRC |FLAGS|SRCOFF/CNT*|
       00h | SRC |FLAGS|SRCOFF/CNT*|
Line 1,204: Line 844:
         @ These fields are optional.
         @ These fields are optional.


;SRC = DB Source type.
:The source type specifies the size and type of the fixup to be performed on the fixup source. The source type is defined as follows:
:: 0Fh = Source mask.
:: 00h = Byte fixup (8-bits).
:: 01h = (undefined).
:: 02h = 16-bit Selector fixup (16-bits).
:: 03h = 16:16 Pointer fixup (32-bits).
:: 04h = (undefined).
:: 05h = 16-bit Offset fixup (16-bits).
:: 06h = 16:32 Pointer fixup (48-bits).
:: 07h = 32-bit Offset fixup (32-bits).
:: 08h = 32-bit Self-relative offset fixup (32-bits).
:: 10h = Fixup to Alias Flag.
::: When the 'Fixup to Alias' Flag is set, the source fixup refers to the 16:16 alias for the object. This is only valid for source types of 2, 3, and 6. For fixups such as this, the linker and loader will be required to perform additional checks such as ensuring that the target offset for this fixup is less than 64K.
:: 20h = Source List Flag.
::: When the 'Source List' Flag is set, the SRCOFF field is compressed to a byte and contains the number of source offsets, and a list of source offsets follows the end of fixup record (after the optional additive value).


    SRC = DB Source type.
;FLAGS = DB Target Flags.
        The source type specifies the size  and type of the
:The target flags specify how the target information is interpreted. The target flags are defined as follows:
        fixup to  be  performed  on  the  fixup source. The
:: 03h = Fixup target type mask.
        source type is defined as follows:
:: 00h = Internal reference.
 
:: 01h = Imported reference by ordinal.
            0Fh = Source mask.
:: 02h = Imported reference by name.
            00h = Byte fixup (8-bits).
:: 03h = Internal reference via entry table.
            01h = (undefined).
:: 04h = Additive Fixup Flag.
            02h = 16-bit Selector fixup (16-bits).
: When set, an additive value trails the fixup record (before the optional source offset list).
            03h = 16:16 Pointer fixup (32-bits).
:: 08h = Reserved. Must be zero.
            04h = (undefined).
:: 10h = 32-bit Target Offset Flag.
            05h = 16-bit Offset fixup (16-bits).
: When set, the target offset is 32-bits, otherwise it is 16-bits.
            06h = 16:32 Pointer fixup (48-bits).
:: 20h = 32-bit Additive Fixup Flag.
            07h = 32-bit Offset fixup (32-bits).
: When set, the additive value is 32-bits, otherwise it is 16-bits.
            08h  =   32-bit Self-relative  offset  fixup
:: 40h = 16-bit Object Number/Module Ordinal Flag.
            (32-bits).
: When set, the object number or module ordinal number is 16-bits, otherwise it is 8-bits.
            10h = Fixup to Alias Flag.
:: 80h = 8-bit Ordinal Flag.
                When the 'Fixup to Alias' Flag is  set, the
: When set, the ordinal number is 8-bits, otherwise it is 16-bits.
                source fixup refers to  the 16:16  alias for
;SRCOFF = DW/CNT = DB Source offset or source offset list count.
                the  object.  This is only  valid for source
This field contains either an offset or a count depending on the Source List Flag. If the Source List Flag is set, a list of source offsets follows the additive field and this field contains the count of the entries in the source offset list.
                types  of 2, 3, and 6. For  fixups such  as
Otherwise, this is the single source offset for the fixup. Source offsets are relative to the beginning of the page where the fixup is to be made.
                this, the linker and loader will be required
                to  perform  additional  checks  such  as
                ensuring that the  target  offset for  this
                fixup is less than 64K.
 
            20h = Source List Flag.
 
                When  the 'Source ListFlag is set, the
                SRCOFF field is compressed  to  a byte  and
                contains the number of source offsets, and a
                list  of source offsets follows the end of
                fixup  record (after  the optional additive
                value).
 
    FLAGS = DB  Target Flags.
        The target flags specify how the target  information
        is interpreted. The  target flags  are  defined  as
        follows:


            03h = Fixup target type mask.
Note that for fixups that cross page boundaries, a separate fixup record is specified for each page.
            00h = Internal reference.
An offset is still used for the 2nd page but it now becomes a negative offset since the fixup originated on the preceding page. (For example, if only the last one byte of a 32-bit address is on the page to be fixed up, then the offset would have a value of -3.)
            01h = Imported reference by ordinal.
            02h = Imported reference by name.
            03h = Internal reference via entry table.
            04h = Additive Fixup Flag.
                When set, an additive value trails the fixup
                record (before the  optional  source  offset
                list).
 
            08h = Reserved.  Must be zero.
            10h = 32-bit Target Offset Flag.
                When  set, the  target  offset  is  32-bits,
                otherwise it is 16-bits.
 
            20h = 32-bit Additive Fixup Flag.
                When set,  the  additive value  is  32-bits,
                otherwise it is 16-bits.
 
            40h = 16-bit Object Number/Module Ordinal Flag.
                When  set,  the  object  number  or  module
                ordinal number  is 16-bits, otherwise  it is
                8-bits.
 
            80h = 8-bit Ordinal Flag.
                When  set,  the  ordinal number  is  8-bits,
                otherwise it is 16-bits.
 
    SRCOFF =  DW/CNT  = DB  Source  offset  or source offset
    list count.
        This field contains  either  an  offset  or  a count
        depending on the  Source  List Flag.  If the  Source
        List Flag is  set,  a list of source offsets follows
        the additive field and this field contains the count
        of  the  entries  in  the  source  offset  list.
        Otherwise, this is the single source offset for  the
        fixup.  Source offsets are relative to the beginning
        of the page where the fixup is to be made.
 
        Note that for fixups that cross page boundaries, a
        separate fixup record is specified for each page.
        An offset is still used for the 2nd page but it now
        becomes a negative offset since the fixup originated
        on the preceding page. (For example, if only the
        last one byte of a 32-bit address is on the page to
        be fixed up, then the offset would have a value of
        -3.)
 
    TARGET DATA = Target data for fixup.
        The  format of the  TARGET  DATA  is  dependent upon
        target flags.
 
    SRCOFF1 - SRCOFFn = DW[]  Source offset list.
        This list is present if the  Source List Flag is set
        in the Target Flags field.  The number of entries in
        the  source offset list is defined in the SRCOFF/CNT
        field.  The  source  offsets  are  relative  to  the
        beginning of the  page where  the fixups are  to  be
        made.


;TARGET DATA = Target data for fixup.
:The format of the TARGET DATA is dependent upon target flags.
;SRCOFF1 - SRCOFFn = DW[] Source offset list.
This list is present if the Source List Flag is set in the Target Flags field. The number of entries in the source offset list is defined in the SRCOFF/CNT field. The source offsets are relative to the beginning of the page where the fixups are to be made.
               +-----+-----+-----+-----+
               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
           00h | SRC |FLAGS|SRCOFF/CNT*|
Line 1,316: Line 901:
             @ These fields are optional.
             @ These fields are optional.


;OBJECT = D[B|W] Target object number.
This field is an index into the current module's Object Table to specify the target Object. It is a Byte value when the '16-bit Object Number/Module Ordinal Flag' bit in the target flags field is clear and a Word value when the bit is set.


        OBJECT = D[B|W]  Target object number.
;TRGOFF = D[W|D] Target offset.
            This field is an index into the current module's
This field is an offset into the specified target Object. It is not present when the Source Type specifies a 16-bit Selector fixup.
            Object Table to  specify  the target Object.  It
It is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.
            is  a  Byte  value  when  the  '16-bit  Object
            Number/Module Ordinal  Flag' bit  in  the target
            flags field is clear and  a Word  value when the
            bit is set.
 
 
        TRGOFF = D[W|D] Target offset.
            This field is an offset into the specified
            target Object. It is not present when the
            Source Type specifies a 16-bit Selector fixup.
            It is a Word value when the '32-bit Target
            Offset Flag' bit in the target flags field is
            clear and a Dword value when the bit is set.
 
               +-----+-----+-----+-----+
               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
           00h | SRC |FLAGS|SRCOFF/CNT*|
Line 1,344: Line 917:
             * These fields are variable size.
             * These fields are variable size.
             @ These fields are optional.
             @ These fields are optional.
;MOD ORD # = D[B|W] Ordinal index into the Import Module Name Table.
This value is an ordered index in to the Import Module Name Table for the module containing the procedure entry point. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set. The loader
creates a table of pointers with each pointer in the table corresponds to the modules named in
the Import Module Name Table. This value is used by the loader to index into this table created by the loader to locate the referenced module.


;PROCEDURE NAME OFFSET = D[W|D] Offset into the Import Procedure Name Table.
This field is an offset into the Import Procedure Name Table. It is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.
;ADDITIVE = D[W|D] Additive fixup value.
This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).


        MOD ORD # =  D[B|W]  Ordinal  index into the  Import
This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.
        Module Name Table.
            This value  is an ordered index in to the Import
            Module Name Table  for the module containing the
            procedure entry point.  It is a Byte value  when
            the '16-bit  Object Number/Module  Ordinal' Flag
            bit  in the target flags  field is  clear  and a
            Word  value  when  the  bit  is set.  The loader
            creates a table of pointers with each pointer in
            the  table  corresponds to the  modules named in
            the  Import  Module Name Table.  This  value  is
            used  by  the loader  to  index into  this table
            created by the  loader  to locate the referenced
            module.
 
        PROCEDURE NAME  OFFSET  =  D[W|D]  Offset  into  the
        Import Procedure Name Table.
            This  field  is  an  offset  into  the  Import
            Procedure Name Table.  It  is a Word  value when
            the  '32-bit  Target Offset  Flag'  bit  in  the
            target flags field  is clear and  a Dword  value
            when the bit is set.
 
        ADDITIVE = D[W|D]  Additive fixup value.
            This field exists in the fixup  record only when
            the 'Additive  Fixup  Flag'  bit  in  the target
            flags field is set.  When  the  'Additive  Fixup
            Flag' is clear the fixup record does not contain
            this  field  and is immediately followed by  the
            next fixup record (or  by the source offset list
            for this fixup record).
 
            This value is added to the address derived from
            the target entry point. This field is a Word
            value when the '32-bit Additive Flag' bit in the
            target flags field is clear and a Dword value
            when the bit is set.
 
               +-----+-----+-----+-----+
               +-----+-----+-----+-----+
           00h | SRC |FLAGS|SRCOFF/CNT*|
           00h | SRC |FLAGS|SRCOFF/CNT*|
Line 1,394: Line 938:
             * These fields are variable size.
             * These fields are variable size.
             @ These fields are optional.
             @ These fields are optional.
;MOD ORD # = D[B|W] Ordinal index into the Import Module Name Table.
:This value is an ordered index in to the Import Module Name Table for the module containing the procedure entry point. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set. The loader creates a table of pointers with each pointer in the table corresponds to the modules named in the Import Module Name Table. This value is used by the loader to index into this table created by the loader to locate the referenced module.


;IMPORT ORD = D[B|W|D] Imported ordinal number.
:This is the imported procedure's ordinal number. It is a Byte value when the '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.


        MOD ORD  # = D[B|W] Ordinal index  into  the Import
;ADDITIVE = D[W|D] Additive fixup value.
        Module Name Table.
:This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).
            This value is an ordered index  in to the Import
            Module  Name Table for the module containing the
            procedure  entry point.  It is a Byte value when
            the '16-bit Object Number/Module  Ordinal' Flag
            bit in the target flags field is  clear  and  a
            Word  value  when  the  bit  is set. The loader
            creates a table of pointers with each pointer in
            the table  corresponds  to the modules named in
            the  Import Module  Name Table.  This  value  is
            used by the loader  to  index  into  this  table
            created  by the loader to locate the  referenced
            module.


        IMPORT ORD = D[B|W|D]  Imported ordinal number.
:This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.
            This is the imported procedure's ordinal number.
        +-----+-----+-----+-----+
            It is a Byte value when  the '8-bit Ordinal' bit
    00h | SRC |FLAGS|SRCOFF/CNT*|
            in the target flags  field is set.  Otherwise it
        +-----+-----+-----+-----+-----+-----+
            is  a Word value when the '32-bit Target  Offset
03h/04h |  ORD # *  |    ADDITIVE * @      |
            Flag' bit in the target flags field is clear and
        +-----+-----+-----+-----+-----+-----+
            a Dword value when the bit is set.
        | SRCOFF1 @ |  . . .  | SRCOFFn @ |
 
        +-----+-----+----  ----+-----+-----+
        ADDITIVE = D[W|D]  Additive fixup value.
            This field exists in the fixup  record only when
        * These fields are variable size.
            the  'Additive Fixup Flag'  bit  in  the  target
        @ These fields are optional.
            flags field is set.  When  the  'Additive  Fixup
            Flag' is clear the fixup record does not contain
            this field  and  is  immediately followed by the
            next fixup record (or  by the source offset list
            for this fixup record).
 
            This value is added to the address derived from
            the target entry point. This field is a Word
            value when the '32-bit Additive Flag' bit in the
            target flags field is clear and a Dword value
            when the bit is set.
 
              +-----+-----+-----+-----+
          00h | SRC |FLAGS|SRCOFF/CNT*|
              +-----+-----+-----+-----+-----+-----+
      03h/04h |  ORD # *  |    ADDITIVE * @      |
              +-----+-----+-----+-----+-----+-----+
              | SRCOFF1 @ |  . . .  | SRCOFFn @ |
              +-----+-----+----  ----+-----+-----+
 
            * These fields are variable size.
            @ These fields are optional.


        ENTRY # = D[B|W] Ordinal index into the Entry
;ENTRY # = D[B|W] Ordinal index into the Entry Table.
        Table.
This field is an index into the current module's Entry Table to specify the target Object and offset. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set.
            This field is an index into the current module's
            Entry Table to specify the target Object and
            offset. It is a Byte value when the '16-bit
            Object Number/Module Ordinal' Flag bit in the
            target flags field is clear and a Word value
            when the bit is set.


        ADDITIVE = D[W|D] Additive fixup value.
;ADDITIVE = D[W|D] Additive fixup value.
            This field exists in the fixup record only when
This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).
            the 'Additive Fixup Flag' bit in the target
            flags field is set. When the 'Additive Fixup
            Flag' is clear the fixup record does not contain
            this field and is immediately followed by the
            next fixup record (or by the source offset list
            for this fixup record).


            This value is added to the address derived from
This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.
            the target entry point. This field is a Word
            value when the '32-bit Additive Flag' bit in the
            target flags field is clear and a Dword value
            when the bit is set.


==Import Module Name Table==
==Import Module Name Table==
The import module name table defines the module name strings
The import module name table defines the module name strings imported through dynamic link references. These strings are referenced through the imported relocation fixups.
imported through dynamic link references. These strings are
referenced through the imported relocation fixups.


To determine the length of the import module name table
To determine the length of the import module name table subtract the import module name table offset from the import procedure name table offset. These values are located in the linear EXE header. The end of the import module name table is not terminated by a special character, it is followed directly by the import procedure name table.
subtract the import module name table offset from the import
procedure name table offset. These values are located in
the linear EXE header. The end of the import module name
table is not terminated by a special character, it is
followed directly by the import procedure name table.


The strings are CASE SENSITIVE and NOT NULL TERMINATED.
The strings are CASE SENSITIVE and NOT NULL TERMINATED.


Each name table entry has the following format:
Each name table entry has the following format:
 
      +-----+-----+-----+-----+    +-----+
          +-----+-----+-----+-----+    +-----+
  00h | LEN |    ASCII STRING  . . .      |
      00h | LEN |    ASCII STRING  . . .      |
      +-----+-----+-----+-----+    +-----+
          +-----+-----+-----+-----+    +-----+
;LEN = DB String Length.
 
:This defines the length of the string in bytes. The length of each ascii name string is limited to 127 characters.
    LEN = DB String Length.
;ASCII STRING = DB ASCII String.
        This defines the length of the string in bytes. The
:This is a variable length string with it's length defined in bytes by the LEN field. The string is case sensitive and is not null terminated.
        length of each ascii name string is limited to 127
        characters.
 
    ASCII STRING = DB ASCII String.
        This is a variable length string with it's length
        defined in bytes by the LEN field. The string is
        case sensitive and is not null terminated.


==Import Procedure Name Table==
==Import Procedure Name Table==
Line 1,507: Line 991:


Each name table entry has the following format:
Each name table entry has the following format:
     +-----+-----+-----+-----+    +-----+
     +-----+-----+-----+-----+    +-----+
  00h | LEN |    ASCII STRING  . . .      |
  00h | LEN |    ASCII STRING  . . .      |
     +-----+-----+-----+-----+    +-----+
     +-----+-----+-----+-----+    +-----+
 
;LEN = DB String Length.
;LEN = DB String Length.
:This defines the length of the string in bytes. The length of each ascii name string is limited to 127 characters.
:This defines the length of the string in bytes. The length of each ascii name string is limited to 127 characters.


:The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.
:The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.


;ASCII STRING = DB ASCII String.
;ASCII STRING = DB ASCII String.
:This is a variable length string with it's length defined in bytes by the LEN field. The string is case sensitive and is not null terminated.
:This is a variable length string with it's length defined in bytes by the LEN field. The string is case sensitive and is not null terminated.


==Preload Pages==
==Preload Pages==
The Preload Pages section is an optional section in the linear EXE module that coalesces a 'preload page set' into a contiguous section. The preload page set can be defined as
The Preload Pages section is an optional section in the linear EXE module that coalesces a 'preload page set' into a contiguous section. The preload page set can be defined as the set of first used pages in the module. The preload page set can be specified by the application developer or can be derived by a tool that analyzes the programs memory usage while it is running. By grouping the preload page set together, the preload pages can be read from the linear EXE module with one disk read.
the set of first used pages in the module. The preload page set can be specified by the application developer or can be derived by a tool that analyzes the programs memory usage while it is running. By grouping the preload page set together, the preload pages can be read from the linear EXE module with one disk read.


The structure of the preload pages is no different than if they were demand loaded. They are non-iterated pages.
The structure of the preload pages is no different than if they were demand loaded. They are non-iterated pages. Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded.
Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded.


All pages begin on a PAGE OFFSET SHIFT boundary from the base of the preload page section, as specified in the linear EXE header. The pages are ordered by logical page number within this section.
All pages begin on a PAGE OFFSET SHIFT boundary from the base of the preload page section, as specified in the linear EXE header. The pages are ordered by logical page number within this section.


Note: OS/2 2.0 does not respect preload pages. Performance tests showed that better system performance was obtained by not respecting the preload request in the executable file.
Note: OS/2 2.0 does not respect preload pages. Performance tests showed that better system performance was obtained by not respecting the preload request in the executable file.


==Demand Load Pages==
==Demand Load Pages==
The Demand Loaded Pages section contains all the non-iterated pages for a linear EXE module that are not preloaded. When required, the whole page is loaded into memory from the module. The characteristics of each of these pages is specified in the Object Page Table. Every page begins on a PAGE OFFSET SHIFT boundary aligned offset from the demand loaded pages base specified in the linear EXE header. Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded. The pages are ordered by logical page number within this section.
The Demand Loaded Pages section contains all the non-iterated pages for a linear EXE module that are not preloaded. When required, the whole page is loaded into memory from the module. The characteristics of each of these pages is specified in the Object Page Table. Every page begins on a PAGE OFFSET SHIFT boundary aligned offset from the demand loaded pages base specified in the linear EXE header. Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded. The pages are ordered by logical page number within this section.


==Iterated Data Pages==
==Iterated Data Pages==
The Iterated Data Pages section contains all the pages for a
The Iterated Data Pages section contains all the pages for a linear EXE module that are iterated. When required, the set of iteration records are loaded into memory from the module and expanded to reconstitute the page. Every set of iteration records begins on a PAGE OFFSET SHIFT offset from the OBJECT ITER PAGES OFF specified in the linear EXE header. Their sizes are determined by the Object Page Table entries that correspond. The pages are ordered by logical page number within this section.
linear EXE module that are iterated. When required, the set
of iteration records are loaded into memory from the module
and expanded to reconstitute the page. Every   set of
iteration records begins on a PAGE OFFSET SHIFT offset from
the OBJECT ITER PAGES OFF specified in the linear EXE
header. Their sizes are determined by the Object Page Table
entries that correspond. The pages are ordered by logical
page number within this section.


This record structure is used to describe the iterated data for an object on a per-page basis.
This record structure is used to describe the iterated data for an object on a per-page basis.
 
    +-----+-----+-----+-----+
          +-----+-----+-----+-----+
00h |#ITERATIONS|DATA LENGTH|
      00h |#ITERATIONS|DATA LENGTH|
    +-----+-----+-----+-----+-----+
          +-----+-----+-----+-----+-----+
04h |DATA BYTES |  . . .  | ... |
      04h |DATA BYTES |  . . .  | ... |
    +-----+-----+-----+-----+-----+
          +-----+-----+-----+-----+-----+
 
''Figure 19. Object Iterated Data Record (Iteration Record)''
''Figure 19. Object Iterated Data Record (Iteration Record)''


    #ITERATIONS = DW Number of iterations.
;#ITERATIONS = DW Number of iterations.
        This specifies the number of times that the data is
;This specifies the number of times that the data is replicated.
        replicated.


    DATA LENGTH = DW The size of the data pattern in bytes.
;DATA LENGTH = DW The size of the data pattern in bytes.
        This specifies the number of bytes of data of which
:This specifies the number of bytes of data of which the pattern consists. The maximum size is one half of the PAGE SIZE (given in the module header). If a pattern exceeds this value then the data page will not be condensed into iterated data.
        the pattern consists. The maximum size is one half
        of the PAGE SIZE (given in the module header). If a
        pattern exceeds this value then the data page will
        not be condensed into iterated data.


    DATA = DB * DATA LENGTH The Data pattern to be
;DATA = DB * DATA LENGTH The Data pattern to be replicated.
    replicated.
:The next iteration record will immediately follow the last byte of the pattern. The offset of the next iteration record is easily calculated from the offset of this record by adding the DATA LENGTH field and the sizes of the #ITERATIONS and DATA LENGTH fields.
        The next iteration record will immediately follow
        the last byte of the pattern. The offset of the
        next iteration record is easily calculated from the
        offset of this record by adding the DATA LENGTH
        field and the sizes of the #ITERATIONS and DATA
        LENGTH fields.


==Debug Information==
==Debug Information==
The debug information is defined by the debugger and is not controlled by the linear EXE format or linker. The only data defined by the linear EXE format relative to the debug
The debug information is defined by the debugger and is not controlled by the linear EXE format or linker. The only data defined by the linear EXE format relative to the debug information is it's offset in the EXE file and length in bytes as defined in the linear EXE header.
information is it's offset in the EXE file and length in bytes as defined in the linear EXE header.


To support multiple debuggers the first word of the debug information is a type field which determines the format of the debug information.
To support multiple debuggers the first word of the debug information is a type field which determines the format of the debug information.
  00h  01h  02h  03h  04h
  00h  01h  02h  03h  04h
  +-----+-----+-----+-----+-----+-----+-----+-----+
  +-----+-----+-----+-----+-----+-----+-----+-----+
  | 'N' | 'B' | '0' |  n  |  DEBUGGER DATA  . . . .
  | 'N' | 'B' | '0' |  n  |  DEBUGGER DATA  ....
  +-----+-----+-----+-----+-----+-----+-----+-----+
  +-----+-----+-----+-----+-----+-----+-----+-----+
;TYPE = DB DUP 4 Format type.
:This defines the type of debugger data that exists in the remainder of the debug information. The signature consists of a string of four (4) ASCII characters: "NB0" followed by the ASCII
representation for 'n'. The values for 'n' are defined as follows.


    TYPE = DB DUP 4 Format type.
:These format types are defined.
        This defines  the type of debugger data  that exists
::00h = 32-bit CodeView debugger format.
        in  the  remainder of  the  debug  information.  The
::01h = AIX debugger format.
        signature consists  of  a  string  of four (4) ASCII
::02h = 16-bit CodeView debugger format.
        characters:   "NB0"    followed    by  the    ASCII
::04h = 32-bit OS/2 PM debugger (IBM) format.
        representation  for 'n'.  The  values  for  'n'  are
        defined as follows.
 
        These format types are defined.
 
            00h = 32-bit CodeView debugger format.
            01h = AIX debugger format.
            02h = 16-bit CodeView debugger format.
            04h = 32-bit OS/2 PM debugger (IBM) format.


    DEBUGGER DATA = Debugger specific data.
;DEBUGGER DATA = Debugger specific data.
        The format of the debugger data is defined by the
:The format of the debugger data is defined by the debugger that is being used.
        debugger that is being used.
:The values defined for the type field are not enforced by the system. It is the responsibility of the linker or debugging tools to follow the convention for the type field that is defined here.


        The  values  defined  for  the  type  field are  not
[[Category:File formats]]
        enforced by the  system.  It is  the  responsibility
        of  the  linker  or  debugging tools to  follow  the
        convention for the type field that is defined here.

Latest revision as of 09:25, 26 December 2022

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

Note: Check this (possible) newer version at: IBM OS/2 16/32-bit Object Module Format (OMF) and Linear eXecutable Module Format (LX) - lx386

Date: June 3, 1992

Figure 1. 32-bit Linear EXE File Layout

      00h +------------------+  <--+
          | DOS 2 Compatible |     |
          |    EXE Header    |     |
      1Ch +------------------+     |
          |      unused      |     |
          +------------------+     |
      24h |  OEM Identifier  |     |
      26h |  OEM Info        |     |
          |                  |     |-- DOS 2.0 Section
      3Ch |  Offset to       |     |   (Discarded)
          |  Linear EXE      |     |
          |  Header          |     |
      40h +------------------+     |
          |   DOS 2.0 Stub   |     |
          |   Program &      |     |
          |   Reloc. Table   |     |
          +------------------+  <--+
          |                  |
      xxh +------------------+  <--+
          |    Executable    |     |
          |       Info       |     |
          +------------------+     |
          |      Module      |     |
          |       Info       |     |
          +------------------+     |-- Linear Executable
          |  Loader Section  |     |   Module Header
          |       Info       |     |   (Resident)
          +------------------+     |
          |   Table Offset   |     |
          |       Info       |     |
          +------------------+  <--+
          |   Object Table   |     |
          +------------------+     |
          | Object Page Table|     |
          +------------------+     |
          |  Resource Table  |     |
          +------------------+     |
          |  Resident Name   |     |
          |      Table       |     |
          +------------------+     |-- Loader Section
          |   Entry Table    |     |   (Resident)
          +------------------+     |
          |   Module Format  |     |
          | Directives Table |     |
          |    (Optional)    |     |
          +------------------+     |
          |     Resident     |     |
          | Directives Data  |     |
          |    (Optional)    |     |
          |                  |     |
          |  (Verify Record) |     |
          +------------------+     |
          |     Per-Page     |     |
          |     Checksum     |     |
          +------------------+  <--+
          | Fixup Page Table |     |
          +------------------+     |
          |   Fixup Record   |     |
          |       Table      |     |
          +------------------+     |-- Fixup Section
          |   Import Module  |     |   (Optionally Resident)
          |    Name Table    |     |
          +------------------+     |
          | Import Procedure |     |
          |    Name Table    |     |
          +------------------+  <--+
          |   Preload Pages  |     |
          +------------------+     |
          |    Demand Load   |     |
          |       Pages      |     |
          +------------------+     |
          |  Iterated Pages  |     |
          +------------------+     |
          |   Non-Resident   |     |-- (Non-Resident)
          |    Name Table    |     |
          +------------------+     |
          |   Non-Resident   |     |
          | Directives Data  |     |
          |    (Optional)    |     |
          |                  |     |
          |  (To be Defined) |     |
          +------------------+  <--+
          |    Debug Info    |     |-- (Not used by Loader)
          +------------------+  <--+

Figure 2. 32-bit Linear EXE Header

          +-----+-----+-----+-----+-----+-----+-----+-----+
      00h | "L"   "X" |B-ORD|W-ORD|     FORMAT LEVEL      |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      08h | CPU TYPE  |  OS TYPE  |    MODULE VERSION     |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      10h |     MODULE FLAGS      |   MODULE # OF PAGES   |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      18h |     EIP OBJECT #      |          EIP          |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      20h |     ESP OBJECT #      |          ESP          |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      28h |       PAGE SIZE       |   PAGE OFFSET SHIFT   |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      30h |  FIXUP SECTION SIZE   | FIXUP SECTION CHECKSUM|
          +-----+-----+-----+-----+-----+-----+-----+-----+
      38h |  LOADER SECTION SIZE  |LOADER SECTION CHECKSUM|
          +-----+-----+-----+-----+-----+-----+-----+-----+
      40h |    OBJECT TABLE OFF   |  # OBJECTS IN MODULE  |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      48h | OBJECT PAGE TABLE OFF | OBJECT ITER PAGES OFF |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      50h | RESOURCE TABLE OFFSET |#RESOURCE TABLE ENTRIES|
          +-----+-----+-----+-----+-----+-----+-----+-----+
      58h | RESIDENT NAME TBL OFF |   ENTRY TABLE OFFSET  |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      60h | MODULE DIRECTIVES OFF | # MODULE DIRECTIVES   |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      68h | FIXUP PAGE TABLE OFF  |FIXUP RECORD TABLE OFF |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      70h | IMPORT MODULE TBL OFF | # IMPORT MOD ENTRIES  |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      78h |  IMPORT PROC TBL OFF  | PER-PAGE CHECKSUM OFF |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      80h |   DATA PAGES OFFSET   |    #PRELOAD PAGES     |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      88h | NON-RES NAME TBL OFF  | NON-RES NAME TBL LEN  |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      90h | NON-RES NAME TBL CKSM |   AUTO DS OBJECT #    |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      98h |    DEBUG INFO OFF     |    DEBUG INFO LEN     |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      A0h |   #INSTANCE PRELOAD   |   #INSTANCE DEMAND    |
          +-----+-----+-----+-----+-----+-----+-----+-----+
      A8h |       HEAPSIZE        |
          +-----+-----+-----+-----+

Note: The OBJECT ITER PAGES OFF must either be 0 or set to the same value as DATA PAGES OFFSET in OS/2 2.0. Ie., iterated pages are required to be in the same section of the file as regular pages.

Note: Table offsets in the Linear EXE Header may be set to zero to indicate that the table does not exist in the EXE file and its size is zero.

"L" "X" = DW Signature word.
The signature word is used by the loader to identify the EXE file as a valid 32-bit Linear Executable Module Format. "L" is low order byte. "X" is high order byte.
B-ORD = DB Byte Ordering.
This byte specifies the byte ordering for the linear EXE format. The values are:
00H - Little Endian Byte Ordering.
01H - Big Endian Byte Ordering.
W-ORD = DB Word Ordering.
This byte specifies the Word ordering for the linear EXE format. The values are:
00H - Little Endian Word Ordering.
01H - Big Endian Word Ordering.
Format Level = DD Linear EXE Format Level.
The Linear EXE Format Level is set to 0 for the initial version of the 32-bit linear EXE format. Each incompatible change to the linear EXE format must increment this value. This allows the system to recognized future EXE file versions so that an appropriate error message may be displayed if an attempt is made to load them.
CPU Type = DW Module CPU Type.
This field specifies the type of CPU required by this module to run. The values are:
01H - 80286 or upwardly compatible CPU is required to execute this module.
02H - 80386 or upwardly compatible CPU is required to execute this module.
03H - 80486 or upwardly compatible CPU is required to execute this module.
OS Type = DW Module OS Type.
This field specifies the type of Operating system required to run this module. The currently defined values are:
00H - Unknown (any "new-format" OS)
01H - OS/2 (default)
02H - Windows
03H - DOS 4.x
04H - Windows 386
MODULE VERSION = DD Version of the linear EXE module.
This is useful for differentiating between revisions of dynamic linked modules. This value is specified at link time by the user.
MODULE FLAGS = DD Flag bits for the module.
The module flag bits have the following definitions.
00000001h = Reserved for system use.
00000002h = Reserved for system use.
00000004h = Per-Process Library Initialization.
The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Initialization is assumed. Setting this bit for an EXE file is invalid.
00000008h = Reserved for system use.
00000010h = Internal fixups for the module have been applied.
The setting of this bit in a Linear Executable Module indicates that each object of the module has a preferred load address specified in the Object Table Reloc Base Addr. If the module's objects can not be loaded at these preferred addresses, then the relocation records that have been retained in the file data will be applied.
00000020h = External fixups for the module have been applied.
00000040h = Reserved for system use.
00000080h = Reserved for system use.
00000100h = Incompatible with PM windowing.
00000200h = Compatible with PM windowing.
00000300h = Uses PM windowing API.
00000400h = Reserved for system use.
00000800h = Reserved for system use.
00001000h = Reserved for system use.
00002000h = Module is not loadable.
When the 'Module is not loadable' flag is set, it indicates that either errors were detected at link time or that the module is being incrementally linked and therefore can't be loaded.
00004000h = Reserved for system use.
00038000h = Module type mask.
00000000h = Program module.
A module can not contain dynamic links to other modules that have the 'program module' type.
00008000h = Library module.
00018000h = Protected Memory Library module.
00020000h = Physical Device Driver module.
00028000h = Virtual Device Driver module.
40000000h = Per-process Library Termination.
The setting of this bit requires the EIP Object # and EIP fields to have valid values. If the EIP Object # and EIP fields are valid and this bit is NOT set, then Global Library Termination is assumed. Setting this bit for an EXE file is invalid.
MODULE # PAGES = DD Number of pages in module.
This field specifies the number of pages physically contained in this module. In other words, pages containing either enumerated or iterated data, or zero-fill pages that have relocations, not invalid or zero-fill pages implied by the Virtual Size in the Object Table being larger than the number of pages actually in the linear EXE file. These pages are contained in the 'preload pages', 'demand load pages' and 'iterated data pages' sections of the linear EXE module. This is used to determine the size of the page information tables in the linear EXE module.
EIP OBJECT # = DD The Object number to which the Entry Address is relative.
This specifies the object to which the Entry Address is relative. This must be a nonzero value for a program module to be correctly loaded. A zero value for a library module indicates that no library entry routine exists. If this value is zero, then both the Per-process Library Initialization bit and the Per-process Library Termination bit must be clear in the module flags, or else the loader will fail to load the module. Further, if the Per-process Library Termination bit is set, then the object to which this field refers must be a 32-bit object (i.e., the Big/Default bit must be set in the object flags; see below).
EIP = DD Entry Address of module.
The Entry Address is the starting address for program modules and the library initialization and Library termination address for library modules.
ESP OBJECT # = DD The Object number to which the ESP is relative.
This specifies the object to which the starting ESP is relative. This must be a nonzero value for a program module to be correctly loaded. This field is ignored for a library module.
ESP = DD Starting stack address of module.
The ESP defines the starting stack pointer address for program modules. A zero value in this field indicates that the stack pointer is to be initialized to the highest address/offset in the object. This field is ignored for a library module.
PAGE SIZE = DD The size of one page for this system.
This field specifies the page size used by the linear EXE format and the system. For the initial version of this linear EXE format the page size is 4Kbytes. (The 4K page size is specified by a value of 4096 in this field.)
PAGE OFFSET SHIFT = DD The shift left bits for page offsets.
This field gives the number of bit positions to shift left when interpreting the Object Page Table entries' page offset field. This determines the alignment of the page information in the file. For example, a value of 4 in this field would align all pages in the Data Pages and Iterated Pages sections on 16 byte (paragraph) boundaries. A Page Offset Shift of 9 would align all pages on a 512 byte (disk sector) basis. The default value for this field is 12 (decimal), which give a 4096 byte alignment. All other offsets are byte aligned.
FIXUP SECTION SIZE = DD Total size of the fixup information in bytes.
This includes the following 4 tables:
  • Fixup Page Table
  • Fixup Record Table
  • Import Module name Table
  • Import Procedure Name Table
FIXUP SECTION CHECKSUM = DD Checksum for fixup information.
This is a cryptographic checksum covering all of the fixup information. The checksum for the fixup information is kept separate because the fixup data is not always loaded into main memory with the 'loader section'. If the checksum feature is not implemented, then the linker will set these fields to zero.
LOADER SECTION SIZE = DD Size of memory resident tables.
This is the total size in bytes of the tables required to be memory resident for the module, while the module is in use. This total size includes all tables from the Object Table down to and including the Per-Page Checksum Table.
LOADER SECTION CHECKSUM = DD Checksum for loader section.
This is a cryptographic checksum covering all of the loader section information. If the checksum feature is not implemented, then the linker will set these fields to zero.
OBJECT TABLE OFF = DD Object Table offset.
This offset is relative to the beginning of the linear EXE header.
# OBJECTS IN MODULE = DD Object Table Count.
        This defines the number of entries in Object Table.
  OBJECT PAGE TABLE OFFSET = DD Object Page Table offset
        This offset is relative to the beginning of the
        linear EXE header.
  OBJECT ITER PAGES OFF = DD Object Iterated Pages offset.
        This offset is relative to the beginning of the EXE
        file.
    RESOURCE TABLE OFF = DD Resource Table offset.
        This offset is relative to the beginning of the
        linear EXE header.
    # RESOURCE TABLE ENTRIES = DD Number of entries in
    Resource Table.
    RESIDENT NAME TBL OFF = DD Resident Name Table offset.
        This offset is relative to the beginning of the
        linear EXE header.
    ENTRY TBL OFF = DD  Entry Table offset.
        This  offset  is  relative  to the beginning of  the
        linear EXE header.
    MODULE DIRECTIVES  OFF  =  DD  Module  Format Directives
    Table offset.
        This  offset  is  relative  to  the beginning of the
        linear EXE header.
    #  MODULE  DIRECTIVES  =  DD  Number  of  Module  Format
    Directives in the Table.
        This field specifies the number  of  entries in  the
        Module Format Directives Table.
    FIXUP PAGE TABLE OFF = DD  Fixup Page Table offset.
        This  offset  is  relative to the  beginning of  the
        linear EXE header.
    FIXUP RECORD TABLE OFF = DD  Fixup Record Table Offset
        This  offset is relative to  the  beginning  of  the
        linear EXE header.
    IMPORT  MODULE  TBL  OFF = DD  Import  Module Name Table
    offset.
        This  offset is relative  to  the  beginning of  the
        linear EXE header.
    # IMPORT MOD ENTRIES = DD  The  number of entries in the
    Import Module Name Table.
    IMPORT PROC TBL OFF  =  DD  Import Procedure  Name Table
    offset.
        This offset  is relative  to  the  beginning of  the
        linear EXE header.
    PER-PAGE CHECKSUM  OFF  =  DD  Per-Page  Checksum  Table
    offset.
        This offset is relative to the beginning of the
        linear EXE header.
    DATA PAGES OFFSET = DD  Data Pages Offset.
        This offset is relative to the beginning of the EXE
        file.
    # PRELOAD PAGES = DD  Number  of  Preload pages for this
    module. Note that OS/2 2.0 does not respect the preload
    of pages as specified in the executable file for performance
    reasons.
    NON-RES NAME TBL OFF = DD Non-Resident Name Table
    offset.
        This offset is relative to the beginning of the EXE
        file.
    NON-RES  NAME  TBL  LEN = DD  Number  of  bytes  in  the
    Non-resident name table.
    NON-RES  NAME TBL CKSM  =  DD  Non-Resident  Name  Table
    Checksum.
        This is a cryptographic checksum of the Non-Resident
        Name Table.
    AUTO  DS OBJECT  #  =  DD  The Auto Data  Segment Object
    number.
        This is the object number for  the Auto Data Segment
        used by 16-bit modules.  This field is supported for
        16-bit compatibility only and is not used by  32-bit
        modules.
    DEBUG INFO OFF = DD  Debug Information offset.
        This offset  is relative  to  the  beginning  of the
        linear EXE header.
    DEBUG INFO LEN = DD  Debug Information length.
        The length of the debug information in bytes.
     #  INSTANCE  PRELOAD  = DD Instance  pages  in  preload
    section.
        The  number  of instance  data pages  found  in  the
        preload section.
     #  INSTANCE  DEMAND  =  DD  Instance  pages  in  demand
    section.
        The  number  of instance  data pages  found  in  the
        demand section.
     HEAPSIZE = DD Heap size added to the Auto DS Object.
        The heap size is the number of bytes added to the
        Auto Data Segment by the loader. This field is
        supported for 16-bit compatibility only and is not
        used by 32-bit modules.

Program (EXE) startup registers and Library entry registers

Program startup registers are defined as follows.

EIP = Starting program entry address.
ESP = Top of stack address.
CS = Code selector for base of linear address space.
DS = ES = SS = Data selector for base of linear address space.
FS = Data selector of base of Thread Information Block (TIB).
GS = 0.
EAX = EBX = 0.
ECX = EDX = 0.
ESI = EDI = 0.
EBP = 0.
[ESP+0] = Return address to routine which calls DosExit(1,EAX).
[ESP+4] = Module handle for program module.
[ESP+8] = Reserved.
[ESP+12] = Environment data object address.
[ESP+16] = Command line linear address in environment data object.

Library initialization registers are defined as follows.

EIP = Library entry address.
ESP = User program stack.
CS = Code selector for base of linear address space.
DS = ES = SS = Data selector for base of linear address space.

Note that a 32-bit Protected Memory Library module will be given a GDT selector in the DS and ES registers (PROTDS) that addresses the full linear address space available to a application. This selector should be saved by the initialization routine. Non-Protected Memory Library modules will receive a selector (FLATDS) that addresses the same amount of linear address space as an application's .EXE can.

FS = Data selector of base of Thread Information Block (TIB).
GS = 0.
EAX = EBX = 0.
ECX = EDX = 0.
ESI = EDI = 0.
EBP = 0.
[ESP+0] = Return address to system, (EAX) = return code.
[ESP+4] = Module handle for library module.
[ESP+8] = 0 (Initialization)

Note that a 32-bit library may specify that its entry address is in a 16-bit code object. In this case, the entry registers are the same as for entry to a library using the Segmented EXE format. These are documented elsewhere. This means that a 16-bit library may be relinked to take advantage of the benefits of the Linear EXE format (notably, efficient paging).

Library termination registers are defined as follows.

EIP = Library entry address.
ESP = User program stack.
CS = Code selector for base of linear address space.
DS = ES = SS = Data selector for base of linear address space.
FS = Data selector of base of Thread Information Block (TIB).
GS = 0.
EAX = EBX = 0.
ECX = EDX = 0.
ESI = EDI = 0.
EBP = 0.
[ESP+0] = Return address to system.
[ESP+4] = Module handle for library module.
[ESP+8] = 1 (Termination)

Note that Library termination is not allowed for libraries with 16-bit entries.

Object Table

The number of entries in the Object Table is given by the # Objects in Module field in the linear EXE header. Entries in the Object Table are numbered starting from one.

Each Object Table entry has the following format:

    +-----+-----+-----+-----+-----+-----+-----+-----+
00h |     VIRTUAL SIZE      |    RELOC BASE ADDR    |
    +-----+-----+-----+-----+-----+-----+-----+-----+
08h |     OBJECT FLAGS      |    PAGE TABLE INDEX   |
    +-----+-----+-----+-----+-----+-----+-----+-----+
10h |  # PAGE TABLE ENTRIES |       RESERVED        |
    +-----+-----+-----+-----+-----+-----+-----+-----+
VIRTUAL SIZE = DD Virtual memory size.

This is the size of the object that will be allocated when the object is loaded. The object's virtual size (rounded up to the page size value) must be greater than or equal to the total size of the pages in the EXE file for the object. This memory size must also be large enough to contain all of the iterated data and uninitialized data in the EXE file.

RELOC BASE ADDR = DD Relocation Base Address.

The relocation base address the object is currently relocated to. If the internal relocation fixups for the module have been removed, this is the address the object will be allocated at by the loader.

OBJECT FLAGS = DW Flag bits for the object.

The object flag bits have the following definitions.

0001h = Readable Object.
0002h = Writable Object.
0004h = Executable Object.

The readable, writable and executable flags provide support for all possible protections. In systems where all of these protections are not supported, the loader will be responsible for making the appropriate protection match for the system.

0008h = Resource Object.
0010h = Discardable Object.
0020h = Object is Shared.
0040h = Object has Preload Pages.
0080h = Object has Invalid Pages.
0100h = Object has Zero Filled Pages.
0200h = Object is Resident (valid for VDDs, PDDs only).
0300h = Object is Resident & Contiguous (VDDs, PDDs only).
0400h = Object is Resident & 'long-lockable' (VDDs, PDDs only).
0800h = Reserved for system use.
1000h = 16:16 Alias Required (80x86 Specific).
2000h = Big/Default Bit Setting (80x86 Specific).

The 'big/default' bit, for data segments, controls the setting of the Big bit in the segment descriptor. (The Big bit, or B-bit, determines whether ESP or SP is used as the stack pointer.) For code segments, this bit controls the setting of the Default bit in the segment descriptor. (The Default bit, or D-bit, determines whether the default word size is 32-bits or 16-bits. It also affects the interpretation of the instruction stream.)

4000h = Object is conforming for code (80x86 Specific).
8000h = Object I/O privilege level (80x86 Specific). Only used for 16:16 Alias Objects.
PAGE TABLE INDEX = DD Object Page Table Index.

This specifies the number of the first object page table entry for this object. The object page table specifies where in the EXE file a page can be found for a given object and specifies per-page attributes.

The object table entries are ordered by logical page in the object table. In other words the object table entries are sorted based on the object page table index value.

    # PAGE TABLE ENTRIES = DD  # of object page table
    entries for this object.
        Any logical pages at the end of an object that do
        not have an entry in the object page table
        associated with them are handled as zero filled or
        invalid pages by the loader.
        When the last logical pages of an object are not
        specified with an object page table entry, they are
        treated as either zero filled pages or invalid pages
        based on the last entry in the object page table for
        that object. If the last entry was neither a zero
        filled or invalid page, then the additional pages
        are treated as zero filled pages.
RESERVED = DD  Reserved for future use. Must be set to zero.

Object Page Table

The Object page table provides information about a logical page in an object. A logical page may be an enumerated page, a pseudo page or an iterated page. The structure of the object page table in conjunction with the structure of the object table allows for efficient access of a page when a page fault occurs, while still allowing the physical page data to be located in the preload page, demand load page or iterated data page sections in the linear EXE module. The logical page entries in the Object Page Table are numbered starting from one. The Object Page Table is parallel to the Fixup Page Table as they are both indexed by the logical page number.

Each Object Page Table entry has the following format:

   63                     32 31       16 15         0
    +-----+-----+-----+-----+-----+-----+-----+-----+
00h |    PAGE DATA OFFSET   | DATA SIZE |   FLAGS   |
    +-----+-----+-----+-----+-----+-----+-----+-----+
PAGE DATA OFFSET = DD
Offset to the page data in the EXE file.

This field, when bit shifted left by the PAGE OFFSET SHIFT from the module header, specifies the offset from the beginning of the Preload Page section of the physical page data in the EXE file that corresponds to this logical page entry. The page data may reside in the Preload Pages, Demand Load Pages or the Iterated Data Pages sections.

If the FLAGS field specifies that this is a zero-Filled page then the PAGE DATA OFFSET field will contain a 0.

If the logical page is specified as an iterated data page, as indicated by the FLAGS field, then this field specifies the offset into the Iterated Data Pages section.

The logical page number (Object Page Table index), is used to index the Fixup Page Table to find any fixups associated with the logical page.

DATA SIZE = DW
Number of bytes of data for this page.

This field specifies the actual number of bytes that represent the page in the file. If the PAGE SIZE field from the module header is greater than the value of this field and the FLAGS field indicates a Legal Physical Page, the remaining bytes are to be filled with zeros. If the FLAGS field indicates an Iterated Data Page, the iterated data records will completely fill out the remainder.

FLAGS = DW
Attributes specifying characteristics of this logical page.

The bit definitions for this word field follow,

00h = Legal Physical Page in the module (Offset from Preload Page Section).
01h = Iterated Data Page (Offset from Iterated Data Pages Section).
02h = Invalid Page (zero).
03h = Zero Filled Page (zero).
04h = Range of Pages.

Resource Table

The resource table is an array of resource table entries. Each resource table entry contains a type ID and name ID. These entries are used to locate resource objects contained in the Object table. The number of entries in the resource table is defined by the Resource Table Count located in the linear EXE header. More than one resource may be contained within a single object. Resource table entries are in a sorted order, (ascending, by Resource Name ID within the Resource Type ID). This allows the DosGetResource API function to use a binary search when looking up a resource in a 32-bit module instead of the linear search being used in the current 16-bit module.

Each resource entry has the following format:

    +-----+-----+-----+-----+
00h |  TYPE ID  |  NAME ID  |
    +-----+-----+-----+-----+
04h |     RESOURCE SIZE     |
    +-----+-----+-----+-----+-----+-----+
08h |   OBJECT  |        OFFSET         |
    +-----+-----+-----+-----+-----+-----+
TYPE ID = DW
Resource type ID.
The type of resources are:
BTMP = Bitmap
EMSG = Error message string
FONT = Fonts
NAME ID = DW
An ID used as a name for the resource when referred to.
RESOURCE SIZE = DD
The number of bytes the resource consists of.
OBJECT = DW
The number of the object which contains the resource.
OFFSET = DD
The offset within the specified object where the resource begins.

Resident or Non-resident Name Table Entry

The resident and non-resident name tables define the ASCII names and ordinal numbers for exported entries in the module. In addition the first entry in the resident name table contains the module name. These tables are used to translate a procedure name string into an ordinal number by searching for a matching name string. The ordinal number is used to locate the entry point information in the entry table.

The resident name table is kept resident in system memory while the module is loaded. It is intended to contain the exported entry point names that are frequently dynamically linked to by name. Non-resident names are not kept in memory and are read from the EXE file when a dynamic link reference is made. Exported entry point names that are infrequently dynamically linked to by name or are commonly referenced by ordinal number should be placed in the non-resident name table. The trade off made for references by name is performance vs memory usage.

Import references by name require these tables to be searched to obtain the entry point ordinal number. Import references by ordinal number provide the fastest lookup since the search of these tables is not required.

The strings are CASE SENSITIVE and are NOT NULL TERMINATED.

Each name table entry has the following format:

    +-----+-----+-----+-----+     +-----+-----+-----+
00h | LEN |    ASCII STRING  . . .      | ORDINAL # |
    +-----+-----+-----+-----+     +-----+-----+-----+
LEN = DB String Length.
This defines the length of the string in bytes. A zero length indicates there are no more entries in table. The length of each ascii name string is limited to 127 characters.
The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.
ASCII STRING = DB ASCII String.
This is a variable length string with it's length defined in bytes by the LEN field. The string is case case sensitive and is not null terminated.
ORDINAL # = DW Ordinal number.
The ordinal number in an ordered index into the entry table for this entry point.

Entry Table

The entry table contains object and offset information that is used to resolve fixup references to the entry points within this module. Not all entry points in the entry table will be exported, some entry points will only be used within the module. An ordinal number is used to index into the entry table. The entry table entries are numbered starting from one.

The list of entries are compressed into 'bundles', where possible. The entries within each bundle are all the same size. A bundle starts with a count field which indicates the number of entries in the bundle. The count is followed by a type field which identifies the bundle format. This provides both a means for saving space as well as a mechanism for extending the bundle types.

The type field allows the definition of 256 bundle types. The following bundle types will initially be defined:

Unused Entry.
16-bit Entry.
286 Call Gate Entry.
32-bit Entry.
Forwarder Entry.

The bundled entry table has the following format:

    +-----+-----+-----+-----+-----+
00h | CNT |TYPE | BUNDLE INFO . . .
    +-----+-----+-----+-----+-----+
CNT = DB Number of entries.
This is the number of entries in this bundle.

A zero value for the number of entries identifies the end of the entry table. There is no further bundle information when the number of entries is zero. In other words the entry table is terminated by a single zero byte.

TYPE = DB Bundle type.

This defines the bundle type which determines the contents of the BUNDLE INFO.

The follow types are defined:

00h = Unused Entry.
01h = 16-bit Entry.
02h = 286 Call Gate Entry.
03h = 32-bit Entry.
04h = Forwarder Entry.
80h = Parameter Typing Information Present.

This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.

The following is the format for each bundle type:

    +-----+-----+
00h | CNT |TYPE |
    +-----+-----+
CNT = DB Number of entries.

This is the number of unused entries to skip.

TYPE = DB 0 (Unused Entry)
    +-----+-----+-----+-----+
00h | CNT |TYPE |   OBJECT  |
    +-----+-----+-----+-----+
      04h |FLAGS|  OFFSET   |
          +-----+-----+-----+
      07h | ... |   . . .   |
          +     +     +     +
CNT = DB Number of entries.

This is the number of 16-bit entries in this bundle. The flags and offset value are repeated this number of times.

TYPE = DB 1 (16-bit Entry)
OBJECT = DW Object number.
This is the object number for the entries in this bundle.
FLAGS = DB Entry flags.
These are the flags for this entry point. They have the following definition.
01h = Exported entry flag.
F8h = Parameter word count mask.
OFFSET = DW Offset in object.
This is the offset in the object for the entry point defined at this ordinal number.
    +-----+-----+-----+-----+
00h | CNT |TYPE |   OBJECT  |
    +-----+-----+-----+-----+-----+
04h |FLAGS|  OFFSET   | CALLGATE  |
    +-----+-----+-----+-----+-----+
09h | ... |   . . .   |   . . .   |
    +     +     +     +     +     +
CNT = DB Number of entries.
This is the number of 286 call gate entries in this bundle. The flags, callgate, and offset value are repeated this number of times.
TYPE = DB 2 (286 Call Gate Entry)
The 286 Call Gate Entry Point type is needed by the loader only if ring 2 segments are to be supported. 286 Call Gate entries contain 2 extra bytes which are used by the loader to store an LDT callgate selector value.
OBJECT = DW Object number.
This is the object number for the entries in this bundle.
FLAGS = DB Entry flags.
These are the flags for this entry point. They have the following definition.
01h = Exported entry flag.
F8h = Parameter word count mask.
OFFSET = DW Offset in object.
This is the offset in the object for the entry point defined at this ordinal number.
CALLGATE = DW Callgate selector.
The callgate selector is a reserved field used by the loader to store a call gate selector value for references to ring 2 entry points. When a ring 3 reference to a ring 2 entry point is made, the callgate selector with a zero offset is place in the relocation fixup address. The segment number and offset in segment is placed in the LDT callgate.
              +-----+-----+-----+-----+
          00h | CNT |TYPE |   OBJECT  |
              +-----+-----+-----+-----+-----+
          04h |FLAGS|        OFFSET         |
              +-----+-----+-----+-----+-----+
          09h | ... |         . . .         |
              +     +     +     +     +     +
CNT = DB Number of entries.
This is the number of 32-bit entries in this bundle. The flags and offset value are repeated this number of times.
TYPE = DB 3 (32-bit Entry)
The 32-bit Entry type will only be defined by the linker when the offset in the object can not be specified by a 16-bit offset.
OBJECT = DW Object number.
This is the object number for the entries in this bundle.
FLAGS = DB Entry flags.
These are the flags for this entry point. They have the following definition.
01h = Exported entry flag.
F8h = Parameter dword count mask.
OFFSET = DD Offset in object.
This is the offset in the object for the entry point defined at this ordinal number.
          +-----+-----+-----+-----+
      00h | CNT |TYPE | RESERVED  |
          +-----+-----+-----+-----+-----+-----+-----+
      04h |FLAGS| MOD ORD#  | OFFSET / ORDNUM       |
          +-----+-----+-----+-----+-----+-----+-----+
      09h | ... |    ...    |          ...          |
          +     +     +     +     +     +     +     +
CNT = DB Number of entries.
This is the number of forwarder entries in this bundle. The FLAGS, MOD ORD#, and OFFSET/ORDNUM values are repeated this number of times.
TYPE = DB 4 (Forwarder Entry)
RESERVED = DW 0
This field is reserved for future use.
FLAGS = DB Forwarder flags.
These are the flags for this entry point. They have the following definition.
01h = Import by ordinal.
F7h = Reserved for future use; should be zero.
MOD ORD# = DW Module Ordinal Number

This is the index into the Import Module Name Table for this forwarder.

OFFSET/ORDNUM = DD Procedure Name Offset or Import Ordinal Number

If the FLAGS field indicates import by ordinal, then this field is the ordinal number into the Entry Table of the target module, otherwise this field is the offset into the Procedure Names Table of the target module.

A Forwarder entry (type = 4) is an entry point whose value is an imported reference. When a load time fixup occurs whose target is a forwarder, the loader obtains the address imported by the forwarder and uses that imported address to resolve the fixup.

A forwarder may refer to an entry point in another module which is itself a forwarder, so there can be a chain of forwarders. The loader will traverse the chain until it finds a non-forwarded entry point which terminates the chain, and use this to resolve the original fixup. Circular chains are detected by the loader and result in a load time error. A maximum of 1024 forwarders is allowed in a chain; more than this results in a load time error.

Forwarders are useful for merging and recombining API calls into different sets of libraries, while maintaining compatibility with applications. For example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a single libraries, one could provide entry points for the three libraries that are forwarders pointing to the common implementation.

Module Format Directives Table

The Module Format Directives Table is an optional table that allows additional options to be specified. It also allows for the extension of the linear EXE format by allowing additional tables of information to be added to the linear EXE module without affecting the format of the linear EXE header. Likewise, module format directives provide a place in the linear EXE module for 'temporary tables' of information, such as incremental linking information and statistic information gathered on the module. When there are no module format directives for a linear EXE module, the fields in the linear EXE header referencing the module format directives table are zero.

Each Module Format Directive Table entry has the following format:

    +-----+-----+-----+-----+-----+-----+----+----+
00h | DIRECT #  | DATA LEN  |     DATA OFFSET     |
    +-----+-----+-----+-----+-----+-----+----+----+
DIRECT # = DW Directive number.
The directive number specifies the type of directive defined. This can be used to determine the format of the information in the directive data. The following directive numbers have been defined:
8000h = Resident Flag Mask.
Directive numbers with this bit set indicate that the directive data is in the resident area and will be kept resident in memory when the module is loaded.
8001h = Verify Record Directive. (Verify record is a resident table.)
0002h = Language Information Directive. (This is a non-resident table.)
0003h = Co-Processor Required Support Table.
0004h = Thread State Initialization Directive.
Additional directives can be added as needed in the future, as long as they do not overlap previously defined directive numbers.
DATA LEN = DW Directive data length.
This specifies the length in byte of the directive data for this directive number.
DIRECTIVE OFFSET = DD Directive data offset.
This is the offset to the directive data for this directive number. It is relative to beginning of linear EXE header for a resident table, and relative to the beginning of the EXE file for non-resident tables.

Verify Record Directive Table

The Verify Record Directive Table is an optional table. It maintains a record of the pages in the EXE file that have been fixed up and written back to the original linear EXE module, along with the module dependencies used to perform these fixups. This table provides an efficient means for verifying the virtual addresses required for the fixed up pages when the module is loaded.

Each Verify Record entry has the following format:

    +-----+-----+
00h |# OF ENTRY |
    +-----+-----+-----+-----+-----+-----+
02h | MOD ORD # |  VERSION  | MOD # OBJ |
    +-----+-----+-----+-----+-----+-----+
08h | OBJECT #  | BASE ADDR |  VIRTUAL  |
    +-----+-----+-----+-----+-----+-----+
0Eh |   . . .   |   . . .   |   . . .   |
    +     +     +     +     +     +     +
# OF ENTRY = DW  Number of module dependencies.
        This field specifies how many entries there are in
        the verify record directive table. This is equal to
        the number of modules referenced by this module.
    MOD  ORD # = DW  Ordinal index into the Import Module
    Name Table.
        This value is an ordered index in to the Import
        Module Name Table for the referenced module.
    VERSION = DW  Module Version.
        This is the version of the referenced module that
        the fixups were originally performed. This is used
        to insure the same version of the referenced module
        is loaded that was fixed up in this module and
        therefore the fixups are still correct. This
        requires the version number in a module to be
        incremented anytime the entry point offsets change.
    MOD # OBJ = DW  Module # of Object Entries.
        This field is used to identify the number of object
        verify entries that follow for the referenced
        module.
    OBJECT # = DW  Object # in Module.
        This field specifies the object number in the
        referenced module that is being verified.
    BASE ADDR = DW  Object load base address.
        This is the address that the object was loaded at
        when the fixups were performed.
    VIRTUAL = DW  Object virtual address size.
        This field specifies the total amount of virtual
        memory required for this object.

Per-Page Checksum

The Per-Page Checksum table provides space for a cryptographic checksum for each physical page in the EXE file.

The checksum table is arranged such that the first entry in the table corresponds to the first logical page of code/data in the EXE file (usually a preload page) and the last entry corresponds to the last logical page in the EXE file (usually a iterated data page).

                 +-----+-----+-----+-----+
Logical Page #1  |        CHECKSUM       |
                 +-----+-----+-----+-----+
Logical Page #2  |        CHECKSUM       |
                 +-----+-----+-----+-----+
                           . . .

                 +-----+-----+-----+-----+
Logical Page #n  |        CHECKSUM       |
                 +-----+-----+-----+-----+
  CHECKSUM = DD  Cryptographic checksum.

Fixup Page Table

The Fixup Page Table provides a simple mapping of a logical page number to an offset into the Fixup Record Table for that page.

This table is parallel to the Object Page Table, except that there is one additional entry in this table to indicate the end of the Fixup Record Table.

The format of each entry is:

                  +-----+-----+-----+-----+
 Logical Page #1  |  OFFSET FOR PAGE #1   |
                  +-----+-----+-----+-----+
 Logical Page #2  |  OFFSET FOR PAGE #2   |
                  +-----+-----+-----+-----+
                            . . .
                  +-----+-----+-----+-----+
 Logical Page #n  |  OFFSET FOR PAGE #n   |
                  +-----+-----+-----+-----+
                  |OFF TO END OF FIXUP REC|   This is equal to:
                  +-----+-----+-----+-----+   Offset for page #n + Size
                                              of fixups for page #n
OFFSET FOR PAGE # = DD Offset for fixup record for this page.

This field specifies the offset, from the beginning of the fixup record table, to the first fixup record for this page.

OFF TO END OF FIXUP REC = DD Offset to the end of the fixup records.

This field specifies the offset following the last fixup record in the fixup record table. This is the last entry in the fixup page table.

The fixup records are kept in order by logical page in the fixup record table. This allows the end of each page's fixup records is defined by the offset for the next logical page's fixup records. This last entry provides support of this mechanism for the last page in the fixup page table.

Fixup Record Table

The Fixup Record Table contains entries for all fixups in the linear EXE module. The fixup records for a logical page are grouped together and kept in sorted order by logical page number. The fixups for each page are further sorted such that all external fixups and internal selector/pointer fixups come before internal non-selector/non-pointer fixups. This allows the loader to ignore internal fixups if the loader is able to load all objects at the addresses specified in the object table.

Each relocation record has the following format:

          +-----+-----+-----+-----+
      00h | SRC |FLAGS|SRCOFF/CNT*|
          +-----+-----+-----+-----+-----+-----+
  03h/04h |           TARGET DATA *           |
          +-----+-----+-----+-----+-----+-----+
          | SRCOFF1 @ |   . . .   | SRCOFFn @ |
          +-----+-----+----   ----+-----+-----+
        * These fields are variable size.
        @ These fields are optional.
SRC = DB Source type.
The source type specifies the size and type of the fixup to be performed on the fixup source. The source type is defined as follows:
0Fh = Source mask.
00h = Byte fixup (8-bits).
01h = (undefined).
02h = 16-bit Selector fixup (16-bits).
03h = 16:16 Pointer fixup (32-bits).
04h = (undefined).
05h = 16-bit Offset fixup (16-bits).
06h = 16:32 Pointer fixup (48-bits).
07h = 32-bit Offset fixup (32-bits).
08h = 32-bit Self-relative offset fixup (32-bits).
10h = Fixup to Alias Flag.
When the 'Fixup to Alias' Flag is set, the source fixup refers to the 16:16 alias for the object. This is only valid for source types of 2, 3, and 6. For fixups such as this, the linker and loader will be required to perform additional checks such as ensuring that the target offset for this fixup is less than 64K.
20h = Source List Flag.
When the 'Source List' Flag is set, the SRCOFF field is compressed to a byte and contains the number of source offsets, and a list of source offsets follows the end of fixup record (after the optional additive value).
FLAGS = DB Target Flags.
The target flags specify how the target information is interpreted. The target flags are defined as follows:
03h = Fixup target type mask.
00h = Internal reference.
01h = Imported reference by ordinal.
02h = Imported reference by name.
03h = Internal reference via entry table.
04h = Additive Fixup Flag.
When set, an additive value trails the fixup record (before the optional source offset list).
08h = Reserved. Must be zero.
10h = 32-bit Target Offset Flag.
When set, the target offset is 32-bits, otherwise it is 16-bits.
20h = 32-bit Additive Fixup Flag.
When set, the additive value is 32-bits, otherwise it is 16-bits.
40h = 16-bit Object Number/Module Ordinal Flag.
When set, the object number or module ordinal number is 16-bits, otherwise it is 8-bits.
80h = 8-bit Ordinal Flag.
When set, the ordinal number is 8-bits, otherwise it is 16-bits.
SRCOFF = DW/CNT = DB Source offset or source offset list count.

This field contains either an offset or a count depending on the Source List Flag. If the Source List Flag is set, a list of source offsets follows the additive field and this field contains the count of the entries in the source offset list. Otherwise, this is the single source offset for the fixup. Source offsets are relative to the beginning of the page where the fixup is to be made.

Note that for fixups that cross page boundaries, a separate fixup record is specified for each page. An offset is still used for the 2nd page but it now becomes a negative offset since the fixup originated on the preceding page. (For example, if only the last one byte of a 32-bit address is on the page to be fixed up, then the offset would have a value of -3.)

TARGET DATA = Target data for fixup.
The format of the TARGET DATA is dependent upon target flags.
SRCOFF1 - SRCOFFn = DW[] Source offset list.

This list is present if the Source List Flag is set in the Target Flags field. The number of entries in the source offset list is defined in the SRCOFF/CNT field. The source offsets are relative to the beginning of the page where the fixups are to be made.

              +-----+-----+-----+-----+
          00h | SRC |FLAGS|SRCOFF/CNT*|
              +-----+-----+-----+-----+-----+-----+
      03h/04h |  OBJECT * |        TRGOFF * @     |
              +-----+-----+-----+-----+-----+-----+
              | SRCOFF1 @ |   . . .   | SRCOFFn @ |
              +-----+-----+----   ----+-----+-----+
            * These fields are variable size.
            @ These fields are optional.
OBJECT = D[B|W] Target object number.

This field is an index into the current module's Object Table to specify the target Object. It is a Byte value when the '16-bit Object Number/Module Ordinal Flag' bit in the target flags field is clear and a Word value when the bit is set.

TRGOFF = D[W|D] Target offset.

This field is an offset into the specified target Object. It is not present when the Source Type specifies a 16-bit Selector fixup. It is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.

              +-----+-----+-----+-----+
          00h | SRC |FLAGS|SRCOFF/CNT*|
              +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
      03h/04h | MOD ORD# *| PROCEDURE NAME OFFSET*|     ADDITIVE * @      |
              +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
              | SRCOFF1 @ |   . . .   | SRCOFFn @ |
              +-----+-----+----   ----+-----+-----+
            * These fields are variable size.
            @ These fields are optional.
MOD ORD # = D[B|W] Ordinal index into the Import Module Name Table.

This value is an ordered index in to the Import Module Name Table for the module containing the procedure entry point. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set. The loader creates a table of pointers with each pointer in the table corresponds to the modules named in the Import Module Name Table. This value is used by the loader to index into this table created by the loader to locate the referenced module.

PROCEDURE NAME OFFSET = D[W|D] Offset into the Import Procedure Name Table.

This field is an offset into the Import Procedure Name Table. It is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.

ADDITIVE = D[W|D] Additive fixup value.

This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).

This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.

              +-----+-----+-----+-----+
          00h | SRC |FLAGS|SRCOFF/CNT*|
              +-----+-----+-----+-----+-----+-----+-----+-----+
      03h/04h | MOD ORD# *|IMPORT ORD*|     ADDITIVE * @      |
              +-----+-----+-----+-----+-----+-----+-----+-----+
              | SRCOFF1 @ |   . . .   | SRCOFFn @ |
              +-----+-----+----   ----+-----+-----+
            * These fields are variable size.
            @ These fields are optional.
MOD ORD # = D[B|W] Ordinal index into the Import Module Name Table.
This value is an ordered index in to the Import Module Name Table for the module containing the procedure entry point. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set. The loader creates a table of pointers with each pointer in the table corresponds to the modules named in the Import Module Name Table. This value is used by the loader to index into this table created by the loader to locate the referenced module.
IMPORT ORD = D[B|W|D] Imported ordinal number.
This is the imported procedure's ordinal number. It is a Byte value when the '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value when the '32-bit Target Offset Flag' bit in the target flags field is clear and a Dword value when the bit is set.
ADDITIVE = D[W|D] Additive fixup value.
This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).
This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.
        +-----+-----+-----+-----+
    00h | SRC |FLAGS|SRCOFF/CNT*|
        +-----+-----+-----+-----+-----+-----+
03h/04h |  ORD # *  |     ADDITIVE * @      |
        +-----+-----+-----+-----+-----+-----+
        | SRCOFF1 @ |   . . .   | SRCOFFn @ |
        +-----+-----+----   ----+-----+-----+

        * These fields are variable size.
        @ These fields are optional.
ENTRY # = D[B|W] Ordinal index into the Entry Table.

This field is an index into the current module's Entry Table to specify the target Object and offset. It is a Byte value when the '16-bit Object Number/Module Ordinal' Flag bit in the target flags field is clear and a Word value when the bit is set.

ADDITIVE = D[W|D] Additive fixup value.

This field exists in the fixup record only when the 'Additive Fixup Flag' bit in the target flags field is set. When the 'Additive Fixup Flag' is clear the fixup record does not contain this field and is immediately followed by the next fixup record (or by the source offset list for this fixup record).

This value is added to the address derived from the target entry point. This field is a Word value when the '32-bit Additive Flag' bit in the target flags field is clear and a Dword value when the bit is set.

Import Module Name Table

The import module name table defines the module name strings imported through dynamic link references. These strings are referenced through the imported relocation fixups.

To determine the length of the import module name table subtract the import module name table offset from the import procedure name table offset. These values are located in the linear EXE header. The end of the import module name table is not terminated by a special character, it is followed directly by the import procedure name table.

The strings are CASE SENSITIVE and NOT NULL TERMINATED.

Each name table entry has the following format:

      +-----+-----+-----+-----+     +-----+
  00h | LEN |    ASCII STRING  . . .      |
      +-----+-----+-----+-----+     +-----+
LEN = DB String Length.
This defines the length of the string in bytes. The length of each ascii name string is limited to 127 characters.
ASCII STRING = DB ASCII String.
This is a variable length string with it's length defined in bytes by the LEN field. The string is case sensitive and is not null terminated.

Import Procedure Name Table

The import procedure name table defines the procedure name strings imported by this module through dynamic link references. These strings are referenced through the imported relocation fixups.

To determine the length of the import procedure name table add the fixup section size to the fixup page table offset, this computes the offset to the end of the fixup section, then subtract the import procedure name table offset. These values are located in the linear EXE header. The import procedure name table is followed by the data pages section. Since the data pages section is aligned on a 'page size' boundary, padded space may exist between the last import name string and the first page in the data pages section. If this padded space exists it will be zero filled.

The strings are CASE SENSITIVE and NOT NULL TERMINATED.

Each name table entry has the following format:

    +-----+-----+-----+-----+     +-----+
00h | LEN |    ASCII STRING  . . .      |
    +-----+-----+-----+-----+     +-----+
LEN = DB String Length.
This defines the length of the string in bytes. The length of each ascii name string is limited to 127 characters.
The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit signifies that additional information is contained in the linear EXE module and will be used in the future for parameter type checking.
ASCII STRING = DB ASCII String.
This is a variable length string with it's length defined in bytes by the LEN field. The string is case sensitive and is not null terminated.

Preload Pages

The Preload Pages section is an optional section in the linear EXE module that coalesces a 'preload page set' into a contiguous section. The preload page set can be defined as the set of first used pages in the module. The preload page set can be specified by the application developer or can be derived by a tool that analyzes the programs memory usage while it is running. By grouping the preload page set together, the preload pages can be read from the linear EXE module with one disk read.

The structure of the preload pages is no different than if they were demand loaded. They are non-iterated pages. Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded.

All pages begin on a PAGE OFFSET SHIFT boundary from the base of the preload page section, as specified in the linear EXE header. The pages are ordered by logical page number within this section.

Note: OS/2 2.0 does not respect preload pages. Performance tests showed that better system performance was obtained by not respecting the preload request in the executable file.

Demand Load Pages

The Demand Loaded Pages section contains all the non-iterated pages for a linear EXE module that are not preloaded. When required, the whole page is loaded into memory from the module. The characteristics of each of these pages is specified in the Object Page Table. Every page begins on a PAGE OFFSET SHIFT boundary aligned offset from the demand loaded pages base specified in the linear EXE header. Their sizes are determined by the Object Page Table entries that correspond. If the specified size is less than the PAGE SIZE field given in the linear EXE module header the remainder of the page is filled with zeros when loaded. The pages are ordered by logical page number within this section.

Iterated Data Pages

The Iterated Data Pages section contains all the pages for a linear EXE module that are iterated. When required, the set of iteration records are loaded into memory from the module and expanded to reconstitute the page. Every set of iteration records begins on a PAGE OFFSET SHIFT offset from the OBJECT ITER PAGES OFF specified in the linear EXE header. Their sizes are determined by the Object Page Table entries that correspond. The pages are ordered by logical page number within this section.

This record structure is used to describe the iterated data for an object on a per-page basis.

    +-----+-----+-----+-----+
00h |#ITERATIONS|DATA LENGTH|
    +-----+-----+-----+-----+-----+
04h |DATA BYTES |   . . .   | ... |
    +-----+-----+-----+-----+-----+

Figure 19. Object Iterated Data Record (Iteration Record)

  1. ITERATIONS = DW Number of iterations.
This specifies the number of times that the data is replicated.
DATA LENGTH = DW The size of the data pattern in bytes.
This specifies the number of bytes of data of which the pattern consists. The maximum size is one half of the PAGE SIZE (given in the module header). If a pattern exceeds this value then the data page will not be condensed into iterated data.
DATA = DB * DATA LENGTH The Data pattern to be replicated.
The next iteration record will immediately follow the last byte of the pattern. The offset of the next iteration record is easily calculated from the offset of this record by adding the DATA LENGTH field and the sizes of the #ITERATIONS and DATA LENGTH fields.

Debug Information

The debug information is defined by the debugger and is not controlled by the linear EXE format or linker. The only data defined by the linear EXE format relative to the debug information is it's offset in the EXE file and length in bytes as defined in the linear EXE header.

To support multiple debuggers the first word of the debug information is a type field which determines the format of the debug information.

00h   01h   02h   03h   04h
+-----+-----+-----+-----+-----+-----+-----+-----+
| 'N' | 'B' | '0' |  n  |   DEBUGGER DATA  ....
+-----+-----+-----+-----+-----+-----+-----+-----+
TYPE = DB DUP 4 Format type.
This defines the type of debugger data that exists in the remainder of the debug information. The signature consists of a string of four (4) ASCII characters: "NB0" followed by the ASCII

representation for 'n'. The values for 'n' are defined as follows.

These format types are defined.
00h = 32-bit CodeView debugger format.
01h = AIX debugger format.
02h = 16-bit CodeView debugger format.
04h = 32-bit OS/2 PM debugger (IBM) format.
DEBUGGER DATA = Debugger specific data.
The format of the debugger data is defined by the debugger that is being used.
The values defined for the type field are not enforced by the system. It is the responsibility of the linker or debugging tools to follow the convention for the type field that is defined here.