RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
gsos.h
1#ifndef GSOS_H
2#define GSOS_H
3
4#include "../common.h"
5#include "../linker/linker.h"
6#include "../linker/module.h"
7#include "../linker/segment.h"
8#include "../linker/writer.h"
9
10/* TODO: untested */
11
12namespace Apple
13{
21 {
22 public:
23 class Segment
24 {
25 public:
27 offset_t segment_offset = 0;
29 offset_t total_segment_size = 0;
31 offset_t bss_size = 0;
33 offset_t total_size = 0;
35 {
37 SEG_CODE = 0x00,
39 SEG_DATA = 0x01,
47 SEG_INIT = 0x10,
52 };
56 uint16_t flags = 0;
58 uint8_t label_length = 0;
60 uint8_t number_length = 4;
61 enum omf_version
62 {
63 OMF_VERSION_0 = 0x0000, // TODO: unsure
64 OMF_VERSION_1 = 0x0100,
65 OMF_VERSION_2 = 0x0200,
66 OMF_VERSION_2_1 = 0x0201,
67 };
69 omf_version version = OMF_VERSION_2;
71 offset_t bank_size = 0;
73 offset_t base_address = 0;
75 offset_t align = 0x100;
77 uint8_t endiantype = 0;
79 uint8_t language_card_bank = 0;
81 uint16_t segment_number = 0;
83 offset_t entry = 0;
85 offset_t segment_name_offset = 0x2C;
87 offset_t segment_data_offset = 0;
89 offset_t temp_org = 0;
93 std::string segment_name;
94
96 static const uint16_t FLAG_BANK_RELATIVE = 0x0100;
98 static const uint16_t FLAG_SKIP_SEGMENT = 0x0200;
100 static const uint16_t FLAG_RELOAD = 0x0400;
102 static const uint16_t FLAG_ABSOLUTE_BANK = 0x0800;
104 static const uint16_t FLAG_NO_SPECIAL_MEMORY = 0x1000;
106 static const uint16_t FLAG_POSITION_INDEPENDENT = 0x2000;
108 static const uint16_t FLAG_PRIVATE = 0x4000;
110 static const uint16_t FLAG_DYNAMIC = 0x8000;
111
113 offset_t ReadUnsigned(Linker::Reader& rd);
115 void WriteWord(Linker::Writer& wr, offset_t value);
116
118 std::string ReadLabel(Linker::Reader& rd);
120 void WriteLabel(Linker::Writer& wr, std::string text);
121
128 offset_t CalculateValues(uint16_t segment_number, offset_t current_offset);
129 void ReadFile(Linker::Reader& rd);
130 void WriteFile(Linker::Writer& wr);
131
133 {
134 public:
135 /* TODO */
136 virtual offset_t GetLength(Segment& segment) = 0;
137 virtual void ReadFile(Segment& segment, Linker::Reader& rd) = 0;
138 virtual void WriteFile(Segment& segment, Linker::Writer& wr) = 0;
139 };
140
141 class Record
142 {
143 public:
144 enum record_type
145 {
146 // E: executable, O: object, L: library
147 OPC_END = 0x00, // EOL
148 OPC_CONST_BASE = 0x00,
149 OPC_CONST_FIRST = 0x01, // O
150 OPC_CONST_LAST = 0xDF, // O
151 OPC_ALIGN = 0xE0, // O
152 OPC_ORG = 0xE1, // O
153 OPC_RELOC = 0xE2, // E
154 OPC_INTERSEG = 0xE3, // E
155 OPC_USING = 0xE4, // O
156 OPC_STRONG = 0xE5, // O
157 OPC_GLOBAL = 0xE6, // O
158 OPC_GEQU = 0xE7, // O
159 OPC_MEM = 0xE8, // O
160 OPC_EXPR = 0xEB, // O
161 OPC_ZEXPR = 0xEC, // O
162 OPC_BEXPR = 0xED, // O
163 OPC_RELEXPR = 0xEE, // O
164 OPC_LOCAL = 0xEF, // O
165 OPC_EQU = 0xF0, // O
166 OPC_DS = 0xF1, // EOL
167 OPC_LCONST = 0xF2, // EOL
168 OPC_LEXPR = 0xF3, // O
169 OPC_ENTRY = 0xF4, // L
170 OPC_C_RELOC = 0xF5, // E
171 OPC_C_INTERSEG = 0xF6, // E
172 OPC_SUPER = 0xF7, // E (V2)
173 };
174 record_type type;
175
176 Record(record_type type)
177 : type(type)
178 {
179 }
180
181 virtual ~Record();
182 virtual offset_t GetLength(Segment& segment);
183 virtual void ReadFile(Segment& segment, Linker::Reader& rd);
184 virtual void WriteFile(Segment& segment, Linker::Writer& wr);
185 };
186
187 class DataRecord : public Record
188 {
189 public:
190 std::vector<uint8_t> data;
191
192 DataRecord(record_type type, std::vector<uint8_t> data)
193 : Record(type), data(data)
194 {
195 }
196
197 DataRecord(record_type type, size_t length)
198 : Record(type), data(length, 0)
199 {
200 }
201
202 DataRecord(record_type type)
203 : Record(type)
204 {
205 }
206
207 offset_t GetLength(Segment& segment) override;
208 void ReadFile(Segment& segment, Linker::Reader& rd) override;
209 void WriteFile(Segment& segment, Linker::Writer& wr) override;
210 };
211
212 class ValueRecord : public Record
213 {
214 public:
215 offset_t value;
216
217 ValueRecord(record_type type, offset_t value)
218 : Record(type), value(value)
219 {
220 }
221
222 offset_t GetLength(Segment& segment) override;
223 void ReadFile(Segment& segment, Linker::Reader& rd) override;
224 void WriteFile(Segment& segment, Linker::Writer& wr) override;
225 };
226
227 class StringRecord : public Record
228 {
229 public:
230 std::string value;
231
232 StringRecord(record_type type, std::string value)
233 : Record(type), value(value)
234 {
235 }
236
237 offset_t GetLength(Segment& segment) override;
238 void ReadFile(Segment& segment, Linker::Reader& rd) override;
239 void WriteFile(Segment& segment, Linker::Writer& wr) override;
240 };
241
243 {
244 public:
245 uint8_t size = 0;
246 uint8_t shift = 0;
247 offset_t source = 0;
248 offset_t target = 0;
249
250 RelocationRecord(record_type type)
251 : Record(type)
252 {
253 }
254
255 RelocationRecord(record_type type, uint8_t size, uint8_t shift, offset_t source, offset_t target)
256 : Record(type), size(size), shift(shift), source(source), target(target)
257 {
258 }
259
260 offset_t GetLength(Segment& segment) override;
261 void ReadFile(Segment& segment, Linker::Reader& rd) override;
262 void WriteFile(Segment& segment, Linker::Writer& wr) override;
263 };
264
266 {
267 public:
268 uint16_t file_number = 0;
269 uint16_t segment_number = 0;
270
271 IntersegmentRelocationRecord(record_type type)
272 : RelocationRecord(type)
273 {
274 }
275
276 IntersegmentRelocationRecord(record_type type, uint8_t size, uint8_t shift, offset_t source, uint16_t file_number, uint16_t segment_number, offset_t target)
277 : RelocationRecord(type, size, shift, source, target), file_number(file_number), segment_number(segment_number)
278 {
279 }
280
281 offset_t GetLength(Segment& segment) override;
282 void ReadFile(Segment& segment, Linker::Reader& rd) override;
283 void WriteFile(Segment& segment, Linker::Writer& wr) override;
284 };
285
286 class LabelRecord : public Record
287 {
288 public:
289 std::string name;
290 uint16_t line_length = 0;
291 enum operation_type
292 {
293 OP_ADDRESS_DC = 'A',
294 // TODO: rest
295 };
296 operation_type operation = operation_type(0);
297 uint16_t private_flag = 0;
298
299 LabelRecord(record_type type)
300 : Record(type)
301 {
302 }
303
304 LabelRecord(record_type type, std::string name, uint16_t line_length, int operation, uint16_t private_flag)
305 : Record(type), name(name), line_length(line_length), operation(operation_type(operation)), private_flag(private_flag)
306 {
307 }
308
309 offset_t GetLength(Segment& segment) override;
310 void ReadFile(Segment& segment, Linker::Reader& rd) override;
311 void WriteFile(Segment& segment, Linker::Writer& wr) override;
312 };
313
315 {
316 public:
317 std::unique_ptr<Expression> expression;
318
319 LabelExpressionRecord(record_type type)
320 : LabelRecord(type)
321 {
322 }
323
324 LabelExpressionRecord(record_type type, std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression)
325 : LabelRecord(type, name, line_length, operation, private_flag), expression(std::move(expression))
326 {
327 }
328
329 offset_t GetLength(Segment& segment) override;
330 void ReadFile(Segment& segment, Linker::Reader& rd) override;
331 void WriteFile(Segment& segment, Linker::Writer& wr) override;
332 };
333
334 class RangeRecord : public Record
335 {
336 public:
337 offset_t start = 0;
338 offset_t end = 0;
339
340 RangeRecord(record_type type)
341 : Record(type)
342 {
343 }
344
345 RangeRecord(record_type type, offset_t start, offset_t end)
346 : Record(type), start(start), end(end)
347 {
348 }
349
350 offset_t GetLength(Segment& segment) override;
351 void ReadFile(Segment& segment, Linker::Reader& rd) override;
352 void WriteFile(Segment& segment, Linker::Writer& wr) override;
353 };
354
356 {
357 public:
358 uint8_t size = 0;
359 std::unique_ptr<Expression> expression;
360
361 ExpressionRecord(record_type type)
362 : Record(type)
363 {
364 }
365
366 ExpressionRecord(record_type type, uint8_t size, std::unique_ptr<Expression> expression)
367 : Record(type), size(size), expression(std::move(expression))
368 {
369 }
370
371 offset_t GetLength(Segment& segment) override;
372 void ReadFile(Segment& segment, Linker::Reader& rd) override;
373 void WriteFile(Segment& segment, Linker::Writer& wr) override;
374 };
375
377 {
378 public:
379 offset_t origin = 0;
380
381 RelativeExpressionRecord(record_type type)
382 : ExpressionRecord(type)
383 {
384 }
385
386 RelativeExpressionRecord(record_type type, uint8_t size, offset_t origin, std::unique_ptr<Expression> expression)
387 : ExpressionRecord(type, size, std::move(expression)), origin(origin)
388 {
389 }
390
391 offset_t GetLength(Segment& segment) override;
392 void ReadFile(Segment& segment, Linker::Reader& rd) override;
393 void WriteFile(Segment& segment, Linker::Writer& wr) override;
394 };
395
396 class EntryRecord : public Record
397 {
398 public:
399 uint16_t segment_number;
400 offset_t location;
401 std::string name;
402
403 EntryRecord(record_type type)
404 : Record(type)
405 {
406 }
407
408 EntryRecord(record_type type, uint16_t segment_number, offset_t location, std::string name)
409 : Record(type), segment_number(segment_number), location(location), name(name)
410 {
411 }
412
413 offset_t GetLength(Segment& segment) override;
414 void ReadFile(Segment& segment, Linker::Reader& rd) override;
415 void WriteFile(Segment& segment, Linker::Writer& wr) override;
416 };
417
419 {
420 public:
421 enum super_record_type
422 {
423 SUPER_RELOC2,
424 SUPER_RELOC3,
425 SUPER_INTERSEG1,
426 SUPER_INTERSEG13 = SUPER_INTERSEG1 - 1 + 13,
427 SUPER_INTERSEG25 = SUPER_INTERSEG1 - 1 + 25,
428 };
429
430 super_record_type super_type = super_record_type(0);
431
432 std::vector<uint16_t> offsets;
433
434 SuperCompactRecord(record_type type, super_record_type super_type = super_record_type(0))
435 : Record(type), super_type(super_type)
436 {
437 }
438
439 offset_t GetLength(Segment& segment) override;
440 void ReadFile(Segment& segment, Linker::Reader& rd) override;
441 void WriteFile(Segment& segment, Linker::Writer& wr) override;
442 private:
443 void WritePatchList(Linker::Writer& wr, const std::vector<uint8_t>& patches);
444 };
445
446 std::unique_ptr<Expression> ReadExpression(Linker::Reader& rd);
447
448 std::unique_ptr<Record> ReadRecord(Linker::Reader& rd);
449
450 std::unique_ptr<Record> makeEND();
451 std::unique_ptr<Record> makeCONST(std::vector<uint8_t> data);
452 std::unique_ptr<Record> makeCONST(std::vector<uint8_t> data, size_t length);
453 std::unique_ptr<Record> makeCONST(size_t length);
454 std::unique_ptr<Record> makeALIGN(offset_t align = 0);
455 std::unique_ptr<Record> makeORG(offset_t value = 0);
456 std::unique_ptr<Record> makeRELOC(uint8_t size, uint8_t shift, offset_t source, offset_t target);
457 std::unique_ptr<Record> makeRELOC();
458 std::unique_ptr<Record> makeINTERSEG(uint8_t size, uint8_t shift, offset_t source, uint16_t file_number, uint16_t segment_number, offset_t target);
459 std::unique_ptr<Record> makeINTERSEG();
460 std::unique_ptr<Record> makeUSING(std::string name = "");
461 std::unique_ptr<Record> makeSTRONG(std::string name = "");
462 std::unique_ptr<Record> makeGLOBAL();
463 std::unique_ptr<Record> makeGLOBAL(std::string name, uint16_t line_length, int operation, uint16_t private_flag);
464 std::unique_ptr<Record> makeGEQU();
465 std::unique_ptr<Record> makeGEQU(std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression);
466 std::unique_ptr<Record> makeMEM();
467 std::unique_ptr<Record> makeMEM(offset_t start, offset_t end);
468 std::unique_ptr<Record> makeEXPR();
469 std::unique_ptr<Record> makeEXPR(uint8_t size, std::unique_ptr<Expression> expression);
470 std::unique_ptr<Record> makeZEXPR();
471 std::unique_ptr<Record> makeZEXPR(uint8_t size, std::unique_ptr<Expression> expression);
472 std::unique_ptr<Record> makeBEXPR();
473 std::unique_ptr<Record> makeBEXPR(uint8_t size, std::unique_ptr<Expression> expression);
474 std::unique_ptr<Record> makeRELEXPR();
475 std::unique_ptr<Record> makeRELEXPR(uint8_t size, offset_t origin, std::unique_ptr<Expression> expression);
476 std::unique_ptr<Record> makeLOCAL();
477 std::unique_ptr<Record> makeLOCAL(std::string name, uint16_t line_length, int operation, uint16_t private_flag);
478 std::unique_ptr<Record> makeEQU();
479 std::unique_ptr<Record> makeEQU(std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression);
480 std::unique_ptr<Record> makeDS(offset_t count = 0);
481 std::unique_ptr<Record> makeLCONST();
482 std::unique_ptr<Record> makeLCONST(std::vector<uint8_t> data);
483 std::unique_ptr<Record> makeLCONST(std::vector<uint8_t> data, size_t length);
484 std::unique_ptr<Record> makeLEXPR();
485 std::unique_ptr<Record> makeLEXPR(uint8_t size, std::unique_ptr<Expression> expression);
486 std::unique_ptr<Record> makeENTRY();
487 std::unique_ptr<Record> makeENTRY(uint16_t segment_number, offset_t location, std::string name);
488 std::unique_ptr<Record> makecRELOC(uint8_t size, uint8_t shift, uint16_t source, uint16_t target);
489 std::unique_ptr<Record> makecRELOC();
490 std::unique_ptr<Record> makecINTERSEG(uint8_t size, uint8_t shift, uint16_t source, uint16_t segment_number, uint16_t target);
491 std::unique_ptr<Record> makecINTERSEG();
492 std::unique_ptr<Record> makeSUPER(SuperCompactRecord::super_record_type super_type = SuperCompactRecord::super_record_type(0));
493 };
494
495 std::vector<std::unique_ptr<Segment>> segments;
496
497 void CalculateValues() override;
498 void ReadFile(Linker::Reader& rd) override;
499 void WriteFile(Linker::Writer& wr) override;
500 /* TODO */
501 };
502}
503
504#endif /* GSOS_H */
Definition gsos.h:24
offset_t segment_offset
Offset of segment within file.
Definition gsos.h:27
std::string ReadLabel(Linker::Reader &rd)
Reads a string the size of label_length, or variable length if it is 0.
Definition gsos.cc:16
uint8_t label_length
(LABLEN) Label length, or 0 for variable length labels
Definition gsos.h:58
void WriteWord(Linker::Writer &wr, offset_t value)
Writes a string the size of number_length.
Definition gsos.cc:11
offset_t total_size
(LENGTH) Total size of segment when loaded into memory, including the additional zeroes
Definition gsos.h:33
offset_t bss_size
(RESSPC) Additional zeroes to append to segment
Definition gsos.h:31
offset_t base_address
(ORG) Base address of segment
Definition gsos.h:73
uint8_t language_card_bank
(LCBANK) Language card bank
Definition gsos.h:79
uint8_t number_length
(NUMLEN) Number length, must be 4
Definition gsos.h:60
omf_version version
(VERSION, REVISION) OMF file format version
Definition gsos.h:69
static const uint16_t FLAG_NO_SPECIAL_MEMORY
Segment flag: Do not load in special memory (version 2 only)
Definition gsos.h:104
std::string linker_segment_name
(LOADNAME) Name of segment according to linker
Definition gsos.h:91
offset_t align
(ALIGN) Segment alignment
Definition gsos.h:75
static const uint16_t FLAG_PRIVATE
Segment flag: Private.
Definition gsos.h:108
static const uint16_t FLAG_ABSOLUTE_BANK
Segment flag: Absolute bank segment (version 2 only)
Definition gsos.h:102
offset_t temp_org
(tempOrg) (only version 2.1, optional)
Definition gsos.h:89
void WriteLabel(Linker::Writer &wr, std::string text)
Writes a string the size of label_length, or variable length if it is 0.
Definition gsos.cc:26
static const uint16_t FLAG_RELOAD
Segment flag: Reload segment (version 2 only)
Definition gsos.h:100
segment_kind kind
(KIND) Segment type
Definition gsos.h:54
offset_t ReadUnsigned(Linker::Reader &rd)
Reads a number the size of number_length.
Definition gsos.cc:6
offset_t total_segment_size
(BYTECNT/BLKCNT) Total size of the segment, including the header, as stored in file
Definition gsos.h:29
std::string segment_name
(LOADNAME) Name of segment
Definition gsos.h:93
offset_t entry
(ENTRY) Entry point (not present in version 0)
Definition gsos.h:83
uint8_t endiantype
(NUMSEX) Endianness, must be 0 for LittleEndian
Definition gsos.h:77
offset_t bank_size
(BANKSIZE) Maximum bank size of segment
Definition gsos.h:71
static const uint16_t FLAG_POSITION_INDEPENDENT
Segment flag: Position independent.
Definition gsos.h:106
offset_t segment_data_offset
(DISPDATA) Offset to segment data, typically appearing after segment_name (not present in version 0)
Definition gsos.h:87
static const uint16_t FLAG_BANK_RELATIVE
Segment flag: Bank relative (version 2 only)
Definition gsos.h:96
static const uint16_t FLAG_DYNAMIC
Segment flag: Dynamic.
Definition gsos.h:110
static const uint16_t FLAG_SKIP_SEGMENT
Segment flag: Skip segment (version 2 only)
Definition gsos.h:98
uint16_t flags
(KIND) Segment flags
Definition gsos.h:56
uint16_t segment_number
(SEGNUM) Segment number (not present in version 0)
Definition gsos.h:81
offset_t segment_name_offset
(DISPNAME) Offset to linker_segment_name (LOADNAME), (not present in version 0)
Definition gsos.h:85
segment_kind
Definition gsos.h:35
@ SEG_CODE
Code segment.
Definition gsos.h:37
@ SEG_DIRPAGE
Direct page/stack segment.
Definition gsos.h:51
@ SEG_JUMPTABLE
Jump table segment.
Definition gsos.h:41
@ SEG_INIT
Initialization segment.
Definition gsos.h:47
@ SEG_PATHNAME
Pathname segment.
Definition gsos.h:43
@ SEG_DATA
Data segment.
Definition gsos.h:39
@ SEG_LIBDICT
Library dictionary segment.
Definition gsos.h:45
@ SEG_ABSBANK
Absolute bank segment (version 1 only)
Definition gsos.h:49
Apple GS/OS OMF file format.
Definition gsos.h:21
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
void WriteFile(Linker::Writer &wr) override
Stores data in memory to file.
Definition gsos.cc:269
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition gsos.cc:256
A helper class to collect sections into segments.
Definition linker.h:19
A class that provides a general interface to setting up generation for a format.
Definition format.h:56
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:16
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15