Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*****************************   omf.h   *************************************
  2. * Author:        Agner Fog
  3. * Date created:  2007-01-29
  4. * Last modified: 2007-01-29
  5. * Project:       objconv
  6. * Module:        omf.h
  7. * Description:
  8. * Header file for definition of data structures and constants in OMF object
  9. * file format. Also defines class COMFFileBuilder.
  10. *
  11. * Copyright 2006-2008 GNU General Public License http://www.gnu.org/licenses
  12. ******************************************************************************
  13. *
  14. * An OMF file consists of a chain of records which all have the same basic
  15. * structure:
  16. * 1. One byte describing the type of record
  17. * 2. A 16-bit word indicating the length of the rest of the record
  18. * 3. Data of variable types and sizes (max 1024 bytes)
  19. * 4. One byte for checksum. Some systems just set this byte to 0
  20. *
  21. * The OMF format is designed for compactness. All integers of type "index"
  22. * are represented by one byte if no bigger than 127, or by two bytes if
  23. * 128 or more. The most significant bit of the first byte indicates whether
  24. * there are one or two bytes. Integers indicating a segment offset are 16
  25. * bits if the type byte is even, or 32 bits if the type byte is odd.
  26. * Some fields can be left out if they are zero or repeated. The precense
  27. * or absense of a particular field may depend on certain bits in the preceding
  28. * fields. The records cannot be defined as C++ structures because a field
  29. * with variable size or a field that can be absent makes the position of the
  30. * subsequent fields variable.
  31. *
  32. * For these reasons, you will not find any structures defining OMF records
  33. * in this header file. Only the bitfields that are used are defined here.
  34. * Instead, I have defined the member functions of SOMFRecordPointer for
  35. * reading fields of various types occurring in OMF records, and the member
  36. * functions of COMFFileBuilder for writing these fields. The structure of
  37. * an OMF record is simply defined by calling these functions in the right
  38. * order.
  39. *
  40. * The size of the data field is limited to 1024 bytes because records of type
  41. * FIXUPP have only 10 bits for indexing into the data field of a preceding
  42. * record of type LEDATA or LIDATA. Most tools (but not all!) limit the size
  43. * of all types of records to 1024 bytes of data, although this limitation
  44. * is technically necessary only for LEDATA and LIDATA records. A segment
  45. * bigger than one kilobyte must be split into several LEDATA records. Each
  46. * LEDATA record is followed by a FIXUPP record if it has relocations.
  47. *
  48. * Symbol names and other text strings are stored with one byte indicating the
  49. * length of the string followed by an ASCII string without terminating zero.
  50. * Consequently, the length of all symbol names is limited to 255 characters.
  51. *
  52. *****************************************************************************/
  53.  
  54. #ifndef OMF_H
  55. #define OMF_H
  56.  
  57. //********************** Record types **********************
  58.  
  59. #define OMF_THEADR   0x80  // Translator Header Record
  60. #define OMF_LHEADR   0x82  // Library Module Header Record
  61. #define OMF_COMENT   0x88  // Comment Record (Including all comment class extensions)
  62. #define OMF_MODEND   0x8A  // (0x8B) Module End Record
  63. #define OMF_EXTDEF   0x8C  // External Names Definition Record
  64. #define OMF_PUBDEF   0x90  // (0x91) Public Names Definition Record
  65. #define OMF_LINNUM   0x94  // (0x95) Line Numbers Record
  66. #define OMF_LNAMES   0x96  // List of Names Record
  67. #define OMF_SEGDEF   0x98  // (0x99) Segment Definition Record
  68. #define OMF_GRPDEF   0x9A  // Group Definition Record
  69. #define OMF_FIXUPP   0x9C  // (0x9D) Fixup Record
  70. #define OMF_LEDATA   0xA0  // (0xA1) Logical Enumerated Data Record
  71. #define OMF_LIDATA   0xA2  // (0xA3) Logical Iterated Data Record
  72. #define OMF_COMDEF   0xB0  // Communal Names Definition Record
  73. #define OMF_BAKPAT   0xB2  // (0xB3) Backpatch Record
  74. #define OMF_LEXTDEF  0xB4  // Local External Names Definition Record
  75. #define OMF_LPUBDEF  0xB6  // (0xB7) Local Public Names Definition Record
  76. #define OMF_LCOMDEF  0xB8  // Local Communal Names Definition Record
  77. #define OMF_CEXTDEF  0xBC  // COMDAT External Names Definition Record
  78. #define OMF_COMDAT   0xC2  // (0xC3) Initialized Communal Data Record
  79. #define OMF_LINSYM   0xC4  // (0xC5) Symbol Line Numbers Record
  80. #define OMF_ALIAS    0xC6  // Alias Definition Record
  81. #define OMF_NBKPAT   0xC8  // (0xC9) Named Backpatch Record
  82. #define OMF_LLNAMES  0xCA  // Local Logical Names Definition Record
  83. #define OMF_VERNUM   0xCC  // OMF Version Number Record
  84. #define OMF_VENDEXT  0xCE  // Vendor-specific OMF Extension Record
  85. #define OMF_LIBHEAD  0xF0  // Library Header Record
  86. #define OMF_LIBEND   0xF1  // Library End Record
  87. #define OMF_LIBEXT   0xF2  // Library extended dictionary
  88.  
  89.  
  90. /********************** Relocation types **********************/
  91.  
  92. #define OMF_Fixup_8bit         0  // 8 bit or low byte of 16 bits
  93. #define OMF_Fixup_16bit        1  // 16 bit offset
  94. #define OMF_Fixup_Segment      2  // 16 bit segment selector
  95. #define OMF_Fixup_Far          3  // 16 bit offset + 16 big segment
  96. #define OMF_Fixup_Hi8bit       4  // High 8 bits of 16 bit offset
  97. #define OMF_Fixup_16bitLoader  5  // 16 bit, loader resolved
  98. #define OMF_Fixup_Pharlab48    6  // 32 bit offset + 16 bit segment, Pharlab only
  99. #define OMF_Fixup_32bit        9  // 32 bit offset
  100. #define OMF_Fixup_Farword     11  // 32 bit offset + 16 bit segment
  101. #define OMF_Fixup_32bitLoader 13  // 32 bit, loader resolved
  102.  
  103. // Define fixed indexes in LNAMES for default group and class names
  104. #define OMF_LNAME_FLAT         1  // Default group name
  105. #define OMF_LNAME_CODE         2  // Default class for code
  106. #define OMF_LNAME_DATA         3  // Default class for data
  107. #define OMF_LNAME_BSS          4  // Default class for uninitialized data
  108. #define OMF_LNAME_CONST        5  // Default class for constant data
  109. #define OMF_LNAME_LAST         5  // Last default name. Nondefault names start at OMF_LNAME_LAST + 1
  110.                                   // Class name STACK not used
  111.  
  112.  
  113. // Define bitfield structures used in OMF records
  114.  
  115. union OMF_SAttrib { // Structure of attributes in SEGDEF record
  116.    uint8 b;                            // Byte
  117.    struct {
  118.       uint8 P:1,                       // 0: 16 bit, 1: 32 bit
  119.             B:1,                       // Big
  120.             C:3,                       // Combination (private, public, stack, common)
  121.             A:3;                       // Alignment
  122.    } u;
  123. };
  124.  
  125. union OMF_SLocat { // Structure of first two bytes of FIXUP subrecord swapped = Locat field
  126.    uint8 bytes[2];                     // First two bytes swapped
  127.    struct {
  128.       uint16 Offset:10,                // Offset into LEDATA (or LIDATA)
  129.              Location:4,               // Relocation method
  130.              M:1,                      // 0 = self-relative, 1 = direct
  131.              one:1;                    // 1 = FIXUP subrecord, 0 = THREAD subrecord
  132.    } s;
  133. };
  134.  
  135. union OMF_SFixData { // Structure of FixData field in FIXUP subrecord of FIXUPP record
  136.    uint8 b;                            // Byte
  137.    struct {
  138.       uint8  Target:2,                 // Target method (T=0) or target thread number (T=1)
  139.              P:1,                      // 0 = target displacement field present, 1 = displacement is zero
  140.              T:1,                      // 0 = target field present, 1 = target defined by thread
  141.              Frame:3,                  // Frame method (F=0) or frame thread (F=1)
  142.              F:1;                      // 0 = target frame field present, 1 = frame defined by thread
  143.    } s;
  144. };
  145.  
  146. union OMF_STrdDat { // Structure of Thread Data field in THREAD subrecord of FIXUPP record
  147.    uint8 b;                            // Byte
  148.    struct {
  149.       uint8  Thread:2,                 // Thread number
  150.              Method:3,                 // Method (T0 - T3, F0 - F6)
  151.              Unused:1,                 // 0
  152.              D:1,                      // 0 = Target thread, 1 = Frame thread
  153.              Zero:1;                   // 1 = FIXUP subrecord, 0 = THREAD subrecord
  154.    } s;
  155. };
  156.  
  157.  
  158. // Structure of OMF record pointer
  159. struct SOMFRecordPointer {
  160. public:
  161.    uint8  Type;            // Record type
  162.    uint8  Type2;           // Record type, made even
  163.    uint16 Unused;          // Align
  164.    uint32 FileOffset;      // Position in file
  165.    uint32 FileEnd;         // End of file = file size
  166.    uint32 Index;           // Offset to current byte while parsing from start of record
  167.    uint32 End;             // Offset to checksum byte from start of record
  168.    int8 * buffer;          // Pointer to file buffer
  169.    uint8  GetByte();       // Read next byte from buffer
  170.    uint16 GetWord();       // Read next 16 bit word from buffer
  171.    uint32 GetDword();      // Read next 32 bit dword from buffer
  172.    uint32 GetIndex();      // Read byte or word, depending on sign of first byte
  173.    uint32 GetNumeric();    // Read word or dword, depending on record type even or odd
  174.    uint32 GetLength();     // Read 1, 2, 3 or 4 bytes, depending on value of first byte
  175.    char * GetString();     // Read string and return as ASCIIZ string
  176.    void   Start(int8 * Buffer, uint32 FileOffset, uint32 FileEnd); // Start scanning through records
  177.    uint8  GetNext(uint32 align = 0);// Get next record
  178.    uint32 InterpretLIDATABlock(); // Interpret Data block in LIDATA record recursively
  179.    uint32 UnpackLIDATABlock(int8 * destination, uint32 MaxSize); // Unpack Data block in LIDATA record recursively and store data at destination
  180. };
  181.  
  182.  
  183. // Class for building OMF files
  184. class COMFFileBuilder : public CFileBuffer {
  185. public:
  186.    COMFFileBuilder();                  // Constructor
  187.    void StartRecord(uint8 type);       // Start building new record
  188.    void EndRecord();                   // Finish building current record
  189.    void PutByte(uint8);                // Put byte into buffer
  190.    void PutWord(uint16);               // Put 16 bit word into buffer
  191.    void PutDword(uint32);              // Put 32 bit dword into buffer
  192.    void PutIndex(uint32);              // Put byte or word into buffer (word if > 127)
  193.    void PutNumeric(uint32);            // Put word or dword into buffer, depending on type being even or odd
  194.    void PutString(const char *);       // Put ASCII string into buffer, preceded by size
  195.    void PutBinary(void *, uint32);     // Put binary data of any length
  196.    uint32 GetSize();                   // Get size of data added so far to current record
  197. protected:
  198.    uint8  Type;                        // Record type
  199.    uint32 Index;                       // Index to current offset
  200.    uint32 RecordStart;                 // Index to start of current record
  201. };
  202.  
  203.  
  204. // Structure for temporary segment list used while building OMF file
  205. struct SOMFSegmentList {
  206. public:
  207.    uint32 NewNumber;                   // Segment index in new file
  208.    uint32 OldName;                     // Segment name in old file as index into NameBuffer
  209.    uint32 NewName;                     // Segment name in new file as index into NameBuffer
  210.    uint32 NewNameI;                    // Segment name in new file as index into LNAMES record. Zero for subsequent entries with same segment name
  211.    SCOFF_SectionHeader * psechdr;      // Pointer to old section header
  212.    uint32 Align;                       // Alignment = 2^Align
  213.    uint32 Class;                       // Class in new file
  214.    uint32 Offset;                      // Offset of section in old file to first section with same name
  215.    uint32 Size;                        // Size of section. First record has combined size of all sections with same name
  216.    uint32 SegmentSize;                 // Size of segment = combined size of all sections with same name. Stored only in first section of segment
  217. };
  218.  
  219.  
  220. // Structure for temporary symbol list used while building OMF file
  221. struct SOMFSymbolList {
  222. public:
  223.    uint32 Scope;                       // 0 = local, 1 = public, 2 = external
  224.    uint32 NewIndex;                    // PUBDEF index if Scope = 1, EXTDEF index if scope = 2
  225.    uint32 Segment;                     // New segment index
  226.    uint32 Offset;                      // Offset relative to segment = first section with same name
  227.    uint32 Name;                        // Symbol name in new file as index into NameBuffer
  228. };
  229.  
  230.  
  231. // Structure for temporary relocation (fixup) list used while building OMF file
  232. struct SOMFRelocation {
  233. public:
  234.    uint32 Section;                     // Section number in old file
  235.    uint32 SourceOffset;                // Offset of source relative to section
  236.    int32  Mode;                        // 0 = EIP-relative, 1 = direct, -1 = unsupported
  237.    uint32 Scope;                       // 0 = local, 2 = external
  238.    uint32 TargetSegment;               // Segment index or EXTDEF index of target in new file
  239.    uint32 TargetOffset;                // Offset relative to segment in new file of target
  240.    int operator < (SOMFRelocation const & x) const {// operator < for sorting by CSList::Sort()
  241.       return Section < x.Section || (Section == x.Section && SourceOffset < x.SourceOffset);
  242.    }
  243. };
  244.  
  245. // Structure for assigning names to unnamed local symbols while converting OMF file
  246. struct SOMFLocalSymbol {
  247.    uint32 Offset;                      // Offset into segment
  248.    uint32 Segment;                     // Segment number in old file
  249.    uint32 Name;                        // Assigned name as index into new string table
  250.    uint32 NewSymtabIndex;              // Index into new symbol table
  251.    // Operator < needed for sorting table of SOMFLocalSymbol:
  252.    int operator < (const SOMFLocalSymbol & b) const {
  253.       return Segment < b.Segment || (Segment == b.Segment && Offset < b.Offset);
  254.    }
  255. };
  256.  
  257. // Structure for interpreted SEGDEF record used during disassembly
  258. struct SOMFSegment {
  259.    uint32 NameO;                       // Segment name, as offset into NameBuffer
  260.    uint32 Offset;                      // Segment address
  261.    uint32 Size;                        // Segment size
  262.    uint32 Align;                       // Alignment = 1 << Align
  263.    uint32 Type;                        // Segment type (as defined in disasm.h)
  264.    uint32 WordSize;                    // 16 or 32 bits
  265.    uint32 BufOffset;                   // Offset of raw data into SegmentData buffer
  266.    uint32 NameIndex;                   // Name index, used for COMDAT segment only
  267. };
  268.  
  269. #endif // #ifndef OMF_H
  270.