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
|
#pragma once
/* SPDX-License-Identifier: Unlicense
*
* Common Object File Format loader implementation.
*
* A section "11. COMMON OBJECT FILE FORMAT (COFF)" from the document named
* "SYSTEM V/68 Release 3 Programmer's Guide" or "MU43715PG/D2" dated 12/01/87
* was used for reference to implement this functionality.
*
* A "TI-89 / TI-92 Plus Sierra C Assembler Reference Manual, Beta Version"
* dated "February 2, 2001" was used for reference to implement this
* functionality.
*/
#include "common.h"
#include <cstdint>
namespace COFF {
constexpr size_t kFileHeaderSize = 20;
constexpr size_t kOptionalHeaderSize = 28;
constexpr size_t kSectionHeaderSize = 40;
/// Relocation information stripped from the file
constexpr uint16_t F_RELFG = 0x1;
/// File is executable (i.be. no unresolved external references)
constexpr uint16_t F_EXEC = 0x2;
/// Line numbers stripped from the file
constexpr uint16_t F_LNNO = 0x4;
/// Local symbols stripped from the file
constexpr uint16_t F_LSYMS = 0x8;
/// Global symbols stripped from the file
constexpr uint16_t F_GSYMS = 0x10;
/// Error in object file
constexpr uint16_t F_ERROR = 0x80;
struct FileHeader {
uint16_t magic; ///< Magic number
/// Number of section headers (equals to number of sections)
uint16_t nsections;
/// Time and date stamp indicating when the file was created, expressed as
/// the number of elapsed seconds since 00:00:00 GMT, January 1, 1970
int32_t timedate;
/// File pointer containing the starting address of the symbol table
uint32_t symtable_offset;
uint32_t nsymbols; ///< Number of entries in the symbol table
uint16_t optional_header_nbytes; ///< Number of bytes in the optional header
uint16_t flags; ///< Flags (see F_* constexpr values)
static constexpr inline auto FromBytes(const uint8_t *data)
{
const bool be = true;
return FileHeader{
/* .magic */ GetU16(data + 0, be),
/* .nsections */ GetU16(data + 2, be),
/* .timedate */ GetI32(data + 4, be),
/* .symtable_offset */ GetU32(data + 8, be),
/* .nsymbols */ GetU32(data + 12, be),
/* .optional_header_nbytes */ GetU16(data + 16, be),
/* .flags */ GetU16(data + 18, be),
};
}
static constexpr uint16_t kMagicSierraM68k = 0x150;
};
struct OptionalHeader {
uint16_t magic; ///< Magic number
uint16_t version; ///< Version stamp
uint32_t tsize; ///< Size of text in bytes
uint32_t dsize; ///< Size of initialized data in bytes
uint32_t bsize; ///< Size of uninitialized data in bytes
uint32_t entry; ///< Program entry point
uint32_t text_start; ///< Base address of text
uint32_t data_start; ///< Base address of data
static constexpr inline auto FromBytes(const uint8_t *data)
{
const bool be = true;
return OptionalHeader{
/* .magic */ GetU16(data + 0, be),
/* .version */ GetU16(data + 2, be),
/* .tsize */ GetU32(data + 4, be),
/* .dsize */ GetU32(data + 8, be),
/* .bsize */ GetU32(data + 12, be),
/* .entry */ GetU32(data + 16, be),
/* .text_start */ GetU32(data + 20, be),
/* .data_start */ GetU32(data + 24, be),
};
}
};
enum class SectionType: uint32_t {
/// Regular section (allocated, relocated, loaded)
Regular = 0,
/// Dummy section (not allocated, relocated, not loaded)
Dummy = 0x1,
/// Noload section (allocated, relocated, not loaded)
NoLoad = 0x2,
/// Grouped section (formed from input sections)
Grouped = 0x4,
/// Padding section (not allocated, not relocated, loaded)
Padding = 0x8,
/// Copy section (for a decision function used in updating fields; not
/// allocated, not relocated, loaded, relocation and line number entries
/// processed normally)
Copy = 0x10,
/// Section contains executable text
Text = 0x20,
/// Section contains initialized data
Data = 0x40,
/// Section contains only uninitialized data
Bss = 0x80,
/// Section contains ORG'd (absolute) data
Org = 0x100,
/// Comment section (not allocated, not relocated, not loaded)
Info = 0x200,
/// Overlay section (not allocated, relocated, not loaded)
Overlay = 0x400,
/// For .lib section (treated like STYP_INFO)
Lib = 0x800,
};
struct SectionHeader {
char name[8]; ///< 8-character null-padded section name
uint32_t paddr; ///< Physical address of section
uint32_t vaddr; ///< Virtual address of section
uint32_t size; ///< Seciton size in bytes
uint32_t section_offset; ///< File pointer to raw data
uint32_t reloc_offset; ///< File pointer to relocation entries
uint32_t lineno_offset; ///< File pointer to line number entries
uint16_t nreloc; ///< Number of relocation entries
uint16_t nlineno; ///< Number of line number entries
uint32_t flags; ///< Flags (see STYP_* constexpr values)
static constexpr inline auto FromBytes(const void *data)
{
const uint8_t *d = static_cast<const uint8_t *>(data);
const char *c = static_cast<const char *>(data);
const bool be = true;
return SectionHeader{
/* .name */ {
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
},
/* .paddr */ GetU32(d + 8, be),
/* .vaddr */ GetU32(d + 12, be),
/* .size */ GetU32(d + 16, be),
/* .section_offset */ GetU32(d + 20, be),
/* .reloc_offset */ GetU32(d + 24, be),
/* .lineno_offset */ GetU32(d + 28, be),
/* .nreloc */ GetU16(d + 32, be),
/* .nlineno */ GetU16(d + 34, be),
/* .flags */ GetU32(d + 36, be),
};
}
};
}
|