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 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 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 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 1 or 2 1 1 or 2 1 B0 Record String Communal Type Data Communal Checksum Length Length Name Index Type Length <----------------repeated------------------> Communal Name Field ------------------- The name is in 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 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 B6 Record Base Base Base String Local Local Type Checksum or Length Group Segment Frame Length Name Offset Index B7 String <----------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 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 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.