File: omf.h

package info (click to toggle)
objconv 2.56%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,300 kB
  • sloc: cpp: 27,039; makefile: 4; sh: 2
file content (269 lines) | stat: -rw-r--r-- 14,674 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/*****************************   omf.h   *************************************
* Author:        Agner Fog
* Date created:  2007-01-29
* Last modified: 2007-01-29
* Project:       objconv
* Module:        omf.h
* Description:
* Header file for definition of data structures and constants in OMF object 
* file format. Also defines class COMFFileBuilder.
*
* Copyright 2006-2008 GNU General Public License http://www.gnu.org/licenses
******************************************************************************
*
* An OMF file consists of a chain of records which all have the same basic
* structure: 
* 1. One byte describing the type of record
* 2. A 16-bit word indicating the length of the rest of the record
* 3. Data of variable types and sizes (max 1024 bytes)
* 4. One byte for checksum. Some systems just set this byte to 0
*
* The OMF format is designed for compactness. All integers of type "index"
* are represented by one byte if no bigger than 127, or by two bytes if
* 128 or more. The most significant bit of the first byte indicates whether
* there are one or two bytes. Integers indicating a segment offset are 16
* bits if the type byte is even, or 32 bits if the type byte is odd.
* Some fields can be left out if they are zero or repeated. The precense
* or absense of a particular field may depend on certain bits in the preceding
* fields. The records cannot be defined as C++ structures because a field
* with variable size or a field that can be absent makes the position of the
* subsequent fields variable.
*
* For these reasons, you will not find any structures defining OMF records
* in this header file. Only the bitfields that are used are defined here. 
* Instead, I have defined the member functions of SOMFRecordPointer for 
* reading fields of various types occurring in OMF records, and the member
* functions of COMFFileBuilder for writing these fields. The structure of 
* an OMF record is simply defined by calling these functions in the right 
* order.
*
* The size of the data field is limited to 1024 bytes because records of type
* FIXUPP have only 10 bits for indexing into the data field of a preceding
* record of type LEDATA or LIDATA. Most tools (but not all!) limit the size
* of all types of records to 1024 bytes of data, although this limitation
* is technically necessary only for LEDATA and LIDATA records. A segment 
* bigger than one kilobyte must be split into several LEDATA records. Each
* LEDATA record is followed by a FIXUPP record if it has relocations.
*
* Symbol names and other text strings are stored with one byte indicating the
* length of the string followed by an ASCII string without terminating zero.
* Consequently, the length of all symbol names is limited to 255 characters.
*
*****************************************************************************/

#ifndef OMF_H
#define OMF_H

//********************** Record types **********************

#define OMF_THEADR   0x80  // Translator Header Record
#define OMF_LHEADR   0x82  // Library Module Header Record
#define OMF_COMENT   0x88  // Comment Record (Including all comment class extensions)
#define OMF_MODEND   0x8A  // (0x8B) Module End Record
#define OMF_EXTDEF   0x8C  // External Names Definition Record
#define OMF_PUBDEF   0x90  // (0x91) Public Names Definition Record
#define OMF_LINNUM   0x94  // (0x95) Line Numbers Record
#define OMF_LNAMES   0x96  // List of Names Record
#define OMF_SEGDEF   0x98  // (0x99) Segment Definition Record
#define OMF_GRPDEF   0x9A  // Group Definition Record
#define OMF_FIXUPP   0x9C  // (0x9D) Fixup Record
#define OMF_LEDATA   0xA0  // (0xA1) Logical Enumerated Data Record
#define OMF_LIDATA   0xA2  // (0xA3) Logical Iterated Data Record
#define OMF_COMDEF   0xB0  // Communal Names Definition Record
#define OMF_BAKPAT   0xB2  // (0xB3) Backpatch Record
#define OMF_LEXTDEF  0xB4  // Local External Names Definition Record
#define OMF_LPUBDEF  0xB6  // (0xB7) Local Public Names Definition Record
#define OMF_LCOMDEF  0xB8  // Local Communal Names Definition Record
#define OMF_CEXTDEF  0xBC  // COMDAT External Names Definition Record
#define OMF_COMDAT   0xC2  // (0xC3) Initialized Communal Data Record
#define OMF_LINSYM   0xC4  // (0xC5) Symbol Line Numbers Record
#define OMF_ALIAS    0xC6  // Alias Definition Record
#define OMF_NBKPAT   0xC8  // (0xC9) Named Backpatch Record
#define OMF_LLNAMES  0xCA  // Local Logical Names Definition Record
#define OMF_VERNUM   0xCC  // OMF Version Number Record
#define OMF_VENDEXT  0xCE  // Vendor-specific OMF Extension Record
#define OMF_LIBHEAD  0xF0  // Library Header Record
#define OMF_LIBEND   0xF1  // Library End Record
#define OMF_LIBEXT   0xF2  // Library extended dictionary


/********************** Relocation types **********************/

#define OMF_Fixup_8bit         0  // 8 bit or low byte of 16 bits
#define OMF_Fixup_16bit        1  // 16 bit offset
#define OMF_Fixup_Segment      2  // 16 bit segment selector
#define OMF_Fixup_Far          3  // 16 bit offset + 16 big segment
#define OMF_Fixup_Hi8bit       4  // High 8 bits of 16 bit offset
#define OMF_Fixup_16bitLoader  5  // 16 bit, loader resolved
#define OMF_Fixup_Pharlab48    6  // 32 bit offset + 16 bit segment, Pharlab only
#define OMF_Fixup_32bit        9  // 32 bit offset
#define OMF_Fixup_Farword     11  // 32 bit offset + 16 bit segment
#define OMF_Fixup_32bitLoader 13  // 32 bit, loader resolved

// Define fixed indexes in LNAMES for default group and class names
#define OMF_LNAME_FLAT         1  // Default group name 
#define OMF_LNAME_CODE         2  // Default class for code
#define OMF_LNAME_DATA         3  // Default class for data
#define OMF_LNAME_BSS          4  // Default class for uninitialized data
#define OMF_LNAME_CONST        5  // Default class for constant data
#define OMF_LNAME_LAST         5  // Last default name. Nondefault names start at OMF_LNAME_LAST + 1
                                  // Class name STACK not used


// Define bitfield structures used in OMF records

union OMF_SAttrib { // Structure of attributes in SEGDEF record
   uint8_t b;                            // Byte
   struct {
      uint8_t P:1,                       // 0: 16 bit, 1: 32 bit
            B:1,                       // Big
            C:3,                       // Combination (private, public, stack, common)
            A:3;                       // Alignment
   } u;
};

union OMF_SLocat { // Structure of first two bytes of FIXUP subrecord swapped = Locat field
   uint8_t bytes[2];                     // First two bytes swapped
   struct {
      uint16_t Offset:10,                // Offset into LEDATA (or LIDATA)
             Location:4,               // Relocation method
             M:1,                      // 0 = self-relative, 1 = direct
             one:1;                    // 1 = FIXUP subrecord, 0 = THREAD subrecord
   } s;
};

union OMF_SFixData { // Structure of FixData field in FIXUP subrecord of FIXUPP record
   uint8_t b;                            // Byte
   struct {
      uint8_t  Target:2,                 // Target method (T=0) or target thread number (T=1)
             P:1,                      // 0 = target displacement field present, 1 = displacement is zero
             T:1,                      // 0 = target field present, 1 = target defined by thread
             Frame:3,                  // Frame method (F=0) or frame thread (F=1)
             F:1;                      // 0 = target frame field present, 1 = frame defined by thread
   } s;
};

union OMF_STrdDat { // Structure of Thread Data field in THREAD subrecord of FIXUPP record
   uint8_t b;                            // Byte
   struct {
      uint8_t  Thread:2,                 // Thread number
             Method:3,                 // Method (T0 - T3, F0 - F6)
             Unused:1,                 // 0
             D:1,                      // 0 = Target thread, 1 = Frame thread
             Zero:1;                   // 1 = FIXUP subrecord, 0 = THREAD subrecord
   } s;
};


// Structure of OMF record pointer
struct SOMFRecordPointer {
public:
   uint8_t  Type;            // Record type
   uint8_t  Type2;           // Record type, made even
   uint16_t Unused;          // Align
   uint32_t FileOffset;      // Position in file
   uint32_t FileEnd;         // End of file = file size
   uint32_t Index;           // Offset to current byte while parsing from start of record
   uint32_t End;             // Offset to checksum byte from start of record
   int8_t * buffer;          // Pointer to file buffer
   uint8_t  GetByte();       // Read next byte from buffer
   uint16_t GetWord();       // Read next 16 bit word from buffer
   uint32_t GetDword();      // Read next 32 bit dword from buffer
   uint32_t GetIndex();      // Read byte or word, depending on sign of first byte
   uint32_t GetNumeric();    // Read word or dword, depending on record type even or odd
   uint32_t GetLength();     // Read 1, 2, 3 or 4 bytes, depending on value of first byte
   char * GetString();     // Read string and return as ASCIIZ string
   void   Start(int8_t * Buffer, uint32_t FileOffset, uint32_t FileEnd); // Start scanning through records
   uint8_t  GetNext(uint32_t align = 0);// Get next record
   uint32_t InterpretLIDATABlock(); // Interpret Data block in LIDATA record recursively
   uint32_t UnpackLIDATABlock(int8_t * destination, uint32_t MaxSize); // Unpack Data block in LIDATA record recursively and store data at destination
};


// Class for building OMF files
class COMFFileBuilder : public CFileBuffer {
public:
   COMFFileBuilder();                  // Constructor
   void StartRecord(uint8_t type);       // Start building new record
   void EndRecord();                   // Finish building current record
   void PutByte(uint8_t);                // Put byte into buffer
   void PutWord(uint16_t);               // Put 16 bit word into buffer
   void PutDword(uint32_t);              // Put 32 bit dword into buffer
   void PutIndex(uint32_t);              // Put byte or word into buffer (word if > 127)
   void PutNumeric(uint32_t);            // Put word or dword into buffer, depending on type being even or odd
   void PutString(const char *);       // Put ASCII string into buffer, preceded by size
   void PutBinary(void *, uint32_t);     // Put binary data of any length
   uint32_t GetSize();                   // Get size of data added so far to current record
protected:
   uint8_t  Type;                        // Record type
   uint32_t Index;                       // Index to current offset
   uint32_t RecordStart;                 // Index to start of current record
};


// Structure for temporary segment list used while building OMF file
struct SOMFSegmentList {
public:
   uint32_t NewNumber;                   // Segment index in new file
   uint32_t OldName;                     // Segment name in old file as index into NameBuffer
   uint32_t NewName;                     // Segment name in new file as index into NameBuffer
   uint32_t NewNameI;                    // Segment name in new file as index into LNAMES record. Zero for subsequent entries with same segment name
   SCOFF_SectionHeader * psechdr;      // Pointer to old section header
   uint32_t Align;                       // Alignment = 2^Align
   uint32_t Class;                       // Class in new file
   uint32_t Offset;                      // Offset of section in old file to first section with same name
   uint32_t Size;                        // Size of section. First record has combined size of all sections with same name
   uint32_t SegmentSize;                 // Size of segment = combined size of all sections with same name. Stored only in first section of segment
};


// Structure for temporary symbol list used while building OMF file
struct SOMFSymbolList {
public:
   uint32_t Scope;                       // 0 = local, 1 = public, 2 = external
   uint32_t NewIndex;                    // PUBDEF index if Scope = 1, EXTDEF index if scope = 2
   uint32_t Segment;                     // New segment index
   uint32_t Offset;                      // Offset relative to segment = first section with same name
   uint32_t Name;                        // Symbol name in new file as index into NameBuffer
};


// Structure for temporary relocation (fixup) list used while building OMF file
struct SOMFRelocation {
public:
   uint32_t Section;                     // Section number in old file
   uint32_t SourceOffset;                // Offset of source relative to section
   int32_t  Mode;                        // 0 = EIP-relative, 1 = direct, -1 = unsupported
   uint32_t Scope;                       // 0 = local, 2 = external
   uint32_t TargetSegment;               // Segment index or EXTDEF index of target in new file 
   uint32_t TargetOffset;                // Offset relative to segment in new file of target
   int operator < (SOMFRelocation const & x) const {// operator < for sorting by CSList::Sort()
      return Section < x.Section || (Section == x.Section && SourceOffset < x.SourceOffset);
   }
};

// Structure for assigning names to unnamed local symbols while converting OMF file
struct SOMFLocalSymbol {
   uint32_t Offset;                      // Offset into segment
   uint32_t Segment;                     // Segment number in old file
   uint32_t Name;                        // Assigned name as index into new string table
   uint32_t NewSymtabIndex;              // Index into new symbol table
   // Operator < needed for sorting table of SOMFLocalSymbol:
   int operator < (const SOMFLocalSymbol & b) const {
      return Segment < b.Segment || (Segment == b.Segment && Offset < b.Offset);
   }
};

// Structure for interpreted SEGDEF record used during disassembly
struct SOMFSegment {
   uint32_t NameO;                       // Segment name, as offset into NameBuffer
   uint32_t Offset;                      // Segment address
   uint32_t Size;                        // Segment size
   uint32_t Align;                       // Alignment = 1 << Align
   uint32_t Type;                        // Segment type (as defined in disasm.h)
   uint32_t WordSize;                    // 16 or 32 bits
   uint32_t BufOffset;                   // Offset of raw data into SegmentData buffer
   uint32_t NameIndex;                   // Name index, used for COMDAT segment only
};

#endif // #ifndef OMF_H