A0H OR A1H LEDATA--LOGICAL ENUMERATED DATA RECORD
=================================================

Description
-----------

This record provides contiguous binary data--executable code or
program data--that is part of a program segment. The data is
eventually copied into the program's executable binary image by the
linker.

The data bytes may be subject to relocation or fixing up as determined
by the presence of a subsequent FIXUPP record, but otherwise they
require no expansion when mapped to memory at run time.

History
-------

Record type A1H is new for LINK386; it has an Enumerated Data Offset
field of 32 bits rather than 16 bits.

Record Format
-------------
   
   1      2       1 or 2   2 or 4      <from Record Length>  1
   A0     Record  Segment  Enumerated  Data                  Checksum
   or A1  Length  Index    Data        Bytes                 
                           Offset

Segment Index Field
-------------------

The Segment Index field must be nonzero and is the index of a
previously defined SEGDEF record. This is the segment into which the
data in this LEDATA record is to be placed.

Enumerated Data Offset Field
----------------------------

The Enumerated Data Offset field is either a 2- or 4-byte field
(depending on the record type) that determines the offset at which the
first data byte is to be placed relative to the start of the SEGDEF
segment. Successive data bytes occupy successively higher locations.

Data Bytes Field
----------------

The maximum number of data bytes is 1024, so that a FIXUPP Location
field, which is 10 bits, can reference any of these data bytes. The
number of data bytes is computed from the Record Length field minus 5,
minus the size of the Segment Index field (1 or 2 bytes).
  
  NOTES
  
  Record type A1H has the offset stored as a 32-bit value. Record type
  A0H encodes the offset value as a 16-bit numeric field (zero-
  extended if applied to a Use32 segment).
  
  If an LEDATA record requires a fixup, a FIXUPP record must
  immediately follow the LEDATA record.
  
  Code for functions is output in LEDATA records currently. The
  segment for code is usually named _TEXT (or module_TEXT, depending
  on the memory model), unless #pragma alloc_text is used to specify a
  different code segment for the specified functions.
  
  For instantiated functions in C++, code will simply be output in
  COMDAT records that refer to the function and identify the
  function's segment.
  
  Data, usually generated by initialized variables (global or static),
  is output in LEDATA/LIDATA records referring to either a data
  segment or, possibly, a segment created for a based variable.

Examples
--------

The following LEDATA record contains a simple text string:

      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F   
 0000 A0 13 00 02 00 00 48 65 6C 6C 6F 2C 20 77 6F 72......Hello, wor
 0010 6C 64 0D 0A 24 A8                              ld..$.

Byte 00H contains 0A0H, which identifies this as an LEDATA record.

Bytes 01-02H contain 0013H, the length of the remainder of the record.

Byte 03H (the Segment Index field) contains 02H, a reference to the
second SEGDEF record in the object module.

Bytes 04-05H (the Enumerated Data Offset field) contain 0000H. This is
the offset, from the base of the segment indicated by the Segment
Index field, at which the data in the Data Bytes field will be placed
when the program is linked. Of course, this offset is subject to
relocation by the linker because the segment declared in the specified
SEGDEF record may be relocatable and may be combined with other
segments declared in other object modules.

Bytes 06-14H (the Data Bytes field) contain the actual data.

Byte 15H contains the Checksum field, 0A8H.


A2H OR A3H LIDATA--LOGICAL ITERATED DATA RECORD
===============================================

Description
-----------

Like the LEDATA record, the LIDATA record contains binary data--
executable code or program data. The data in an LIDATA record,
however, is specified as a repeating pattern (iterated), rather than
by explicit enumeration.

The data in an LIDATA record can be modified by the linker if the
LIDATA record is followed by a FIXUPP record, although this is not
recommended.

History
-------

Record type A3H is new for LINK386; it has Iterated Data Offset and
Repeat Count fields of 32 bits rather than 16 bits.

Record Format
-------------

   1    2       1 or 2  2 or 4    <from Record Length>  1
   A2   Record  Segment Iterated  Data                  Checksum
   or   Length  Index   Data      Block                 
   A3                   Offset                          
                                  <-----------repeated----------->
   
Segment Index and Interated Data Offset Fields
----------------------------------------------

The Segment Index and Iterated Data Offset fields (2 or 4 bytes) are
the same as for an LEDATA record. The index must be nonzero. This
indicates the segment and offset at which the data in this LIDATA
record is to be placed when the program is loaded.

Data Block Field
----------------

The data blocks have the following form:
                       
   2 or 4    2         <from Block Count>
   Repeat    Block     Content
   Count     Count     

Repeat Count Field
------------------

The Repeat Count field is a 16-bit or 32-bit value that determines the
number of times the Content field is to be repeated. The Repeat Count
field is 32 bits only if the record type is A3H.
  
  Conflict: The PharLap OMF uses a 16-bit Repeat Count field, even in
  32-bit records.

Block Count Field
-----------------

The Block Count field is a 16-bit word whose value determines the
interpretation of the Content field, as follows:

   0      Indicates that the Content field that follows is a 1-byte
          count value followed by count data bytes. The data bytes
          will be mapped to memory, repeated as many times as are
          specified in the Repeat Count field.
          
   != 0   Indicates that the Content field that follows is composed
          of one or more Data Block fields. The value in the Block
          Count field specifies the number of Data Block fields
          (recursive definition).
          
  
  NOTES
  
  The Microsoft C Compiler generates LIDATA records for initialized
  data. For example:
   
      static int a[100] = { 1, };
  
  A FIXUPP record may occur after the LIDATA record; however, the
  fixup is applied before the iterated data block is expanded. It is a
  translator error for a fixup to reference any of the Count fields.

Example 1
---------
   
      02 00 02 00 03 00 00 00 02 40 41 02 00 00 00 02 50 51

is an iterated data block with 16-bit repeat counts that expands to:

      40 41 40 41 40 41 50 51 50 51 40 41 40 41 40 41 50 51 50 51

Here, the outer data block has a repeat count of 2 and a block count
of 2 (which means to repeat twice the result of expanding the two
inner data blocks). The first inner data block has repeat count = 3,
block count = 0. The content is 2 bytes of data (40 41); the repeat
count expands the data to a string of 6 bytes. The second (and last)
inner data block has a repeat count = 2, block count = 0, content 2
bytes of data (50 51). This expands to 4 bytes, which is concatenated
with the 6 bytes from the first inner data block. The resulting 10
bytes are then expanded by 2 (the repeat count of the outer data
block) to form the 20-byte sequence illustrated.

Example 2
---------

This sample LIDATA record corresponds to the following assembler
statement, which declares a 10-element array containing the strings
ALPHA and BETA:
   
   db   10 dup('ALPHA','BETA')

The LIDATA record is
   
      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0000  A2 1B 00 01 00 00 0A 00 02 00 01 00 00 00 05 41 ...............A
0010  4C 50 48 41 01 00 00 00 04 42 45 54 41 A9       LPHA.....BETA.

Byte 00H contains 0A2H, identifying this as an LIDATA record.

Bytes 01-02H contain 1BH, the length of the remainder of the record.

Byte 03H (the Segment Index field) contains 01H, a reference to the
first SEGDEF record in this object module, indicating that the data
declared in this LIDATA record is to be placed into the segment
described by the first SEGDEF record.

Bytes 04-05H (the Iterated Data Offset field) contain 0000H, so the
data in this LIDATA record is to be located at offset 0000H in the
segment designated by the segment.

Bytes 06-1CH represent an iterated data block:

 - Bytes 06-07H contain the repeat count, 000AH, which indicates that
   the Content field of this iterated data block is to be repeated 10
   times.

 - Bytes 08-09H (the block count for this iterated data block) contain
   0002H, which indicates that the Content field of this iterated data
   block (bytes 0A-1CH) contains two nested iterated data block fields
   (bytes 0A-13H and bytes 14-1CH).

 - Bytes 0A-0BH contain 0001H, the repeat count for the first nested
   iterated data block. Bytes 0C-0DH contain 0000H, indicating that
   the Content field of this nested iterated data block contains data
   rather than more nested iterated data blocks. The Content field
   (bytes 0E-13H) contains the data; byte 0EH contains 05H, the number
   of subsequent data bytes; and bytes 0F-13H contain the actual data
   (the string ALPHA).

 - Bytes 14-1CH represent the second nested iterated data block, which
   has a format similar to that of the block in bytes 0A-13H. This
   second nested iterated data block represents the 4-byte string
   BETA.

 - Byte 1DH is the Checksum field, 0A9H.


B0H COMDEF--COMMUNAL NAMES DEFINITION RECORD
============================================

Description
-----------

The COMDEF record is a Microsoft extension to the basic set of 8086
object record types. It declares a list of one or more communal
variables (uninitialized static data, or data that may match
initialized static data in another compilation unit).

The size of such a variable is the maximum size defined in any module
naming the variable as communal or public. The placement of communal
variables is determined by the data type using established conventions
(noted below).

History
-------

The COMDEF record is recognized by versions 3.5 and later of LINK.

Record Format
-------------

  1  2      1      <String Length> 1 or 2 1    1 or 2 1 <from Data Type>    
  B0 Record String Communal        Type   Data Communal Checksum
     Length Length Name            Index  Type Length          
            <----------------repeated------------------>
             
Communal Name Field
-------------------

The name is in <count, char> string format, and the name may be null.
NEAR and FAR communals from different object files are matched at bind
or link time if their names agree; the variable's size is the maximum
of the sizes specified (subject to some constraints, as documented
below).

Type Index Field
----------------

This field encodes symbol information; it is parsed as an index field
(1 or 2 bytes) and is not inspected by current linkers. This field is
now used by CodeView instead of for its original purpose.

Data Type and Communal Length Fields

The Data Type field indicates the contents of the Communal Length
field. All Data Type values for NEAR data indicate that the Communal
Length field has only one numeric value: the amount of memory to be
allocated for the communal variable. All Data Type values for FAR data
indicate that the Communal Length field has two numeric values: the
first is the number of elements, and the second is the element size.

The Data Type field is one of the following hexadecimal values:

   61H   FAR data; the length is specified as the number of the
         elements followed by the element size in bytes
         
   62H   NEAR data; the length is specified as the number of bytes

The Communal Length field is a single numeric field or a pair of
numeric fields (as specified by the Data Type field), encoded as
follows:

                   Number    
   Value Range     of Bytes   Allocation
   ----------------------------------------------------------------
   0 through 128       1      This byte contains the value
  
   0 to 64K-1          3      First byte is 81H, followed by a 16-bit
                              word whose value is used

   0 to 16 MB-1        4      First byte is 84H, followed by a 3-byte
                              value

   -2 GB-1 to 2 GB-1   5      First byte is 88H, followed by a 4-byte
                              value

Groups of Communal Name, Type Index, Data Type, and Communal Length
fields can be repeated so that more than one communal variable can be
declared in the same COMDEF record.
  
  NOTES
  
  If a public or exported symbol with the same name is found in
  another module to which this module is bound or linked, LINK gives
  the error "symbol defined more than once."
  
  Communal variables cannot be resolved to dynamic links (that is,
  imported symbols).
  
  The records are ordered by occurrence, together with the items named
  in EXTDEF and LEXTDEF records (for reference in FIXUP subrecords).
  
  In older versions of the linker, any object module that contains
  COMDEF records is required to also contain one COMENT record with
  the comment class 0A1H, indicating that Microsoft extensions to the
  Intel object record specification are included in the object module.
  This COMENT record is no longer required; current versions of the
  linker always interpret COMDEF records.

Examples
--------

The following COMDEF record was generated by Microsoft C Compiler
version 4.0 for these public variable declarations:

   int   var;                   /* 2-byte integer */
   char  var2[32768];           /* 32768-byte array */
   char  far var3[10][2][20];   /* 400-byte array */

The COMDEF record is:

         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0000 B0 20 00 04 5F 66 6F 6F 00 62 02 05 5F 66 6F 6F  . .._var.b.._var
0010 32 00 62 81 00 80 05 5F 66 6F 6F 33 00 61 81 90  2.b...._var3.a..
0020 01 01 99                                         ...

Byte 00H contains 0B0H, indicating that this is a COMDEF record.

Bytes 01-02H contain 0020H, the length of the remainder of the record.

Bytes 03-0AH, 0B-15H, and 16-21H represent three declarations for the
communal variables var, var2, and var3. The C compiler prepends an
underscore to each of the names declared in the source code, so the
symbols represented in this COMDEF record are _var, _var2, and _var3.

Byte 03H contains 04H, the length of the first Communal Name field in
this record. Bytes 04-07H contain the name itself (_var). Byte 08H
(the Type Index field) contains 00H, as required. Byte 09H (the Data
Type field) contains 62H, indicating that this is a NEAR variable.
Byte 0AH (the Communal Length field) contains 02H, the size of the
variable in bytes.

Byte 0BH contains 05H, the length of the second Communal Name field.
Bytes 0C-10H contain the name _var2. Byte 11H is the Type Index field,
which again contains 00H, as required. Byte 12H (the Data Type field)
contains 62H, indicating that _var2 is a NEAR variable.

Bytes 13-15H (the Communal Length field) contain the size in bytes of
the variable. The first byte of the Communal Length field (byte 13H)
is 81H, indicating that the size is represented in the subsequent two
bytes of data--bytes 14-15H, which contain the value 8000H.

Bytes 16-1BH represent the Communal Name field for _var3, the third
communal variable declared in this record. Byte 1CH (the Type Index
field) again contains 00H as required. Byte 1DH (the Data Type field)
contains 61H, indicating that this is a FAR variable. This means the
Communal Length field is formatted as a Number of Elements field
(bytes 1E-20H, which contain the value 0190H) and an Element Size
field (byte 21H, which contains 01H). The total size of this communal
variable is thus 190H times 1, or 400 bytes.

Byte 22H contains the Checksum field, 99H.


B2H OR B3H BAKPAT--BACKPATCH RECORD
===================================

Description
-----------

This record is for backpatches to LOCATIONs that cannot be
conveniently handled by a FIXUPP record at reference time (for
example, forward references in a one-pass compiler). It is essentially
a specialized fixup.

History
-------

Record type B2H is a Microsoft extension that was added for QuickC
version 1.0. Record type B3H is the 32-bit equivalent: the Offset and
Value fields are 32 bits rather than 16 bits.

Record Format
-------------

  1     2       1 or 2   1         2 or 4     2 or 4    1
  B2    Record  Segment  Location  Offset     Value     Checksum
  or B3 Length  Index    Type                         
  
                                   <-----repeated----->
                            
Segment Index Field
-------------------

Segment index to which all "backpatch" FIXUPP records are to be
applied. Note that, in contrast to FIXUPP records, these records do
not need to follow the data record to be fixed up. Hence, the segment
to which the backpatch applies must be specified explicitly.

Location Type Field
-------------------

Type of LOCATION to be patched; the only valid values are:
   
   0    8-bit low-order byte
   1    16-bit offset
   2    32-bit offset, record type B3H only (not supported yet)

Offset and Value Fields
-----------------------

These fields are 32 bits for record type B3H, and 16 bits for B2H.

The Offset field specifies the LOCATION to be patched (as an offset
into the SEGDEF record whose index is Segment Index).

The associated Value field is added to the LOCATION being patched
(unsigned addition, ignoring overflow). The Value field is a fixed
length (16 bits or 32 bits, depending on the record type) to make
object-module processing easier.
  
  NOTE: BAKPAT records can occur anywhere in the object module
  following the SEGDEF record to which they refer. They do not have to
  immediately follow the appropriate LEDATA record as FIXUPP records
  do.
  
  These records are buffered by the linker in Pass 2 until the end of
  the module, after the linker applies all other FIXUPP records. LINK
  then processes these records as fixups.

Examples
--------

For example, to generate a self-relative address whose TARGET is a
forward reference (JZ forwardlabel), the translator can insert the
negative offset of the next instruction (-*) from the start of the
SEGDEF record, followed by an additive backpatch (meaning that the
backpatch is added to the original value and the sum replaces the
original value) whose Value is the offset of the TARGET of the jump,
which is done last.


B4H OR B5H LEXTDEF--LOCAL EXTERNAL NAMES DEFINITION RECORD
==========================================================

Description
-----------

This record is identical in form to the EXTDEF record described
earlier. However, the symbols named in this record are not visible
outside the module in which they are defined.

History
-------

This record was a Microsoft extension for C 5.0. There is no semantic
difference between the B4H and B5H types.

Record Format
-------------

   1    2        1       <String Length>  1 or 2  1
   B4   Record   String  External         Type    Checksum
   B5   Length   Length  Name String      Index   
                 <--------------repeated------->
  
  NOTE: These records are associated with LPUBDEF and LCOMDEF records
  and ordered with the EXTDEF records by occurrence, so that they may
  be referenced by an external name index for fixups.
  
  The name string, when stored in LINK's internal data structures, is
  encoded with spaces and digits at the beginning of the name.

Examples
--------

This record type is produced in C from static functions, such as:
   
   static int var() { }


B6H OR B7H LPUBDEF--LOCAL PUBLIC NAMES DEFINITION RECORD
========================================================

Description
-----------

This record is identical in form to the PUBDEF record described
earlier. However, the symbols named in this record are not visible
outside the module in which they are defined.

History
-------

This record was a Microsoft extension for C 5.0. Record type B7H is
new for LINK386: the Local Offset field is 32 bits rather than 16
bits.

Record Format
-------------
   1  2       1 or 2 1 or 2 2      1      <String  2 or 4 1 or 2 1
                                           Length>  
   B6 Record  Base   Base    Base   String Local   Local   Type  Checksum
   or Length  Group  Segment Frame  Length Name    Offset  Index  
   B7                                      String 
                             <cond.><----------repeated---------->  
  
Examples
--------

In C, the static keyword on functions or initialized variables
produces LPUBDEF records. Uninitialized static variables produce
LCOMDEF records.


B8H LCOMDEF--LOCAL COMMUNAL NAMES DEFINITION RECORD
===================================================

Description
-----------

This record is identical in form to the COMDEF record described
previously. However, the symbols named in this record are not visible
outside the module in which they are defined.

History
-------

This record was a Microsoft extension for C 5.0.

Record Format
-------------

   1  2       1       <String      1      1      <from      1
                      Length>      or 2          Data Type>
   B8 Record  String  Communal     Type   Data   Communal   Checksum
      Length  Length  Name         Index  Type   Length          
              <--------------repeated---------------------->  

Examples
--------

In C, uninitialized static variables produce an LCOMDEF record.


BCH CEXTDEF--COMDAT EXTERNAL NAMES DEFINITION RECORD
====================================================

Description
-----------

This record serves the same purpose as the EXTDEF record described
earlier. However, the symbol named is referred to through a Logical
Name Index field. Such a Logical Name Index field is defined through
an LNAMES or LLNAMES record.

History
-------

The record is a Microsoft extension for C 7.0.

Record Format
-------------

                                            
   1    2      1 or 2          1 or 2       1
   BC   Record Logical Name    Type         Checksum
        Length Index           Index        
               <---------repeated-------->  
               
               
  NOTE: A CEXTDEF can precede the COMDAT to which it will be resolved.
  In this case, the location of the COMDAT is not known at the time
  the CEXTDEF is seen.

Examples
--------

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


C2H OR C3H COMDAT--INITIALIZED COMMUNAL DATA RECORD
===================================================

Description
-----------

The purpose of the COMDAT record is to combine logical blocks of code
and data that may be duplicated across a number of compiled modules.

History
-------

The record is a Microsoft extension for C 7.0.

Record Format
-------------
 1  2      1      1      1      2 or 4 1 or  2      1 or 2 1    1     
 C2 Record Flags  Attrib Align  Enumer Type  Public Public Data Check
 or Length        -utes         -ated  Index Base   Name        Sum  
 C3                             Data                Index     
                                Offset                       
 
                                                    <repeated> 
                                                     
Flags Field
-----------

This field contains the following defined bits:

   01H   Continuation bit. If clear, this COMDAT record establishes
         a new instance of the COMDAT variable; otherwise, the data
         is a continuation of the previous COMDAT of the symbol.
         
   02H   Iterated data bit. If clear, the Data field contains
         enumerated data; otherwise, the Data field contains
         iterated data, as in an LIDATA record.
         
   04H   Local bit (effectively an "LCOMDAT"). This is used in
         preference to LLNAMES.
         
   08H   Data in code segment. If the application is overlayed, this
         COMDAT must be forced into the root text. Also, do not
         apply FARCALLTRANSLATION to this COMDAT.

Attributes Field
----------------
          
This field contains two 4-bit fields: the Selection Criteria to be
used, and the Allocation Type, an ordinal specifying the type of
allocation to be performed. Values are:

   Selection Criteria (High-Order 4 Bits):

   Bit       Selection Criteria
                       
   00H       No match  Only one instance of this COMDAT allowed.
                       
   10H       Pick Any  Pick any instance of this COMDAT.
                       
   20H       Same      Pick any instance, but instances must have
             Size      the same length or the linker will generate
                       an error.
                       
   30H       Exact     Pick any instance, but checksums of the
             Match     instances must match or the linker will
                       generate an error. Fixups are ignored.
                       
   40H -               Reserved.
   F0H

   Allocation Type (Low-Order 4 bits):
   
   Bit       Allocation 
                                  
   00H       Explicit Allocate in the segment specified in the
                      ensuing Base Group, Base Segment, and Base
                      Frame fields.
                                          
   01H       Far      Allocate as CODE16. The linker will create
             Code     segments to contain all COMDATs of this type.
                      
   02H       Far      Allocate as DATA16. The linker will create
             Data     segments to contain all COMDATs of this type.
                      
   03H       Code32   Allocate as CODE32. The linker will create
                      segments to contain all COMDATs of this type.
                      
   04H       Data32   Allocate as DATA32. The linker will create
                      segments to contain all COMDATs of this type.
                      
   05H -              Reserved.
   0FH

Align Field

These codes are based on the ones used by the SEGDEF record:
   
   0   Use value from SEGDEF
   1   Byte aligned
   2   Word aligned
   3   Paragraph (16 byte) aligned
   4   256-byte aligned
   5   Double word (4 byte) aligned
   6   Not defined
   7   Not defined

Enumerated Data Offset Field
----------------------------
          
This field specifies an offset relative to the beginning location of
the symbol specified in the Public Name Index field and defines the
relative location of the first byte of the Data field. Successive data
bytes in the Data field occupy higher locations of memory. This works
very much like the Enumerated Data Offset field in an LEDATA record,
but instead of an offset relative to a segment, this is relative to
the beginning of the COMDAT symbol.

Type Index Field
----------------

The Type Index field is encoded in index format; it contains either
proprietary CodeView-type information or an old-style TYPDEF index. If
this index is 0, there is no associated type data. Old-style TYPDEF
indexes are ignored by LINK. Current linkers do not perform type
checking.

Public Base Field
-----------------

This field is conditional and is identical to the public base fields
(Base Group, Base Segment, and Base Frame) stored in the PUBDEF
record. This field is present only if the Allocation Type field
specifies Explicit allocation.

Public Name Index Field
-----------------------

This field is a regular logical name index (1 or 2 bytes).

Data Field
----------

The Data field provides up to 1024 consecutive bytes of data. If there
are fixups, they must be emitted in a FIXUPP record that follows the
COMDAT record. The data can be either enumerated or iterated,
depending on the Flags field.

  NOTES
  
  Record type C3H has an Enumerated Data Offset field of 32 bits.
  
  While creating addressing frames, the linker will add the COMDAT
  data to the appropriate logical segments, adjusting their sizes. At
  that time, the offset at which the data will go inside the logical
  segment will be calculated. Next, the linker will create physical
  segments from adjusted logical segments, reporting any 64K boundary
  overflows.
  
  If the allocation type is not explicit, COMDAT code and data is
  accumulated by the linker and broken up into segments, so that the
  total can exceed 64K.
  
  In Pass 2, only the selected occurrence of COMDAT data will be
  stored in virtual memory, fixed up, and later written into the .EXE
  file.
  
  COMDATs are allocated in the order of their appearance in the .OBJ
  files if no explicit ordering is given.
  
  A COMDAT record cannot be continued across modules. A COMDAT record
  can be duplicated in a single module.
  
  If any COMDAT record on a given symbol has the local bit set, all
  the COMDAT records on that symbol have that bit set.
