kolibrios-gitea/programs/develop/objconv/omf.h

270 lines
14 KiB
C
Raw Normal View History

/***************************** 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 b; // Byte
struct {
uint8 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 bytes[2]; // First two bytes swapped
struct {
uint16 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 b; // Byte
struct {
uint8 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 b; // Byte
struct {
uint8 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 Type; // Record type
uint8 Type2; // Record type, made even
uint16 Unused; // Align
uint32 FileOffset; // Position in file
uint32 FileEnd; // End of file = file size
uint32 Index; // Offset to current byte while parsing from start of record
uint32 End; // Offset to checksum byte from start of record
int8 * buffer; // Pointer to file buffer
uint8 GetByte(); // Read next byte from buffer
uint16 GetWord(); // Read next 16 bit word from buffer
uint32 GetDword(); // Read next 32 bit dword from buffer
uint32 GetIndex(); // Read byte or word, depending on sign of first byte
uint32 GetNumeric(); // Read word or dword, depending on record type even or odd
uint32 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 * Buffer, uint32 FileOffset, uint32 FileEnd); // Start scanning through records
uint8 GetNext(uint32 align = 0);// Get next record
uint32 InterpretLIDATABlock(); // Interpret Data block in LIDATA record recursively
uint32 UnpackLIDATABlock(int8 * destination, uint32 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 type); // Start building new record
void EndRecord(); // Finish building current record
void PutByte(uint8); // Put byte into buffer
void PutWord(uint16); // Put 16 bit word into buffer
void PutDword(uint32); // Put 32 bit dword into buffer
void PutIndex(uint32); // Put byte or word into buffer (word if > 127)
void PutNumeric(uint32); // 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); // Put binary data of any length
uint32 GetSize(); // Get size of data added so far to current record
protected:
uint8 Type; // Record type
uint32 Index; // Index to current offset
uint32 RecordStart; // Index to start of current record
};
// Structure for temporary segment list used while building OMF file
struct SOMFSegmentList {
public:
uint32 NewNumber; // Segment index in new file
uint32 OldName; // Segment name in old file as index into NameBuffer
uint32 NewName; // Segment name in new file as index into NameBuffer
uint32 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 Align; // Alignment = 2^Align
uint32 Class; // Class in new file
uint32 Offset; // Offset of section in old file to first section with same name
uint32 Size; // Size of section. First record has combined size of all sections with same name
uint32 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 Scope; // 0 = local, 1 = public, 2 = external
uint32 NewIndex; // PUBDEF index if Scope = 1, EXTDEF index if scope = 2
uint32 Segment; // New segment index
uint32 Offset; // Offset relative to segment = first section with same name
uint32 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 Section; // Section number in old file
uint32 SourceOffset; // Offset of source relative to section
int32 Mode; // 0 = EIP-relative, 1 = direct, -1 = unsupported
uint32 Scope; // 0 = local, 2 = external
uint32 TargetSegment; // Segment index or EXTDEF index of target in new file
uint32 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 Offset; // Offset into segment
uint32 Segment; // Segment number in old file
uint32 Name; // Assigned name as index into new string table
uint32 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 NameO; // Segment name, as offset into NameBuffer
uint32 Offset; // Segment address
uint32 Size; // Segment size
uint32 Align; // Alignment = 1 << Align
uint32 Type; // Segment type (as defined in disasm.h)
uint32 WordSize; // 16 or 32 bits
uint32 BufOffset; // Offset of raw data into SegmentData buffer
uint32 NameIndex; // Name index, used for COMDAT segment only
};
#endif // #ifndef OMF_H