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
|