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 <optional>
5#include <variant>
6#include "apple.h"
7#include "../common.h"
8#include "../dumper/dumper.h"
9#include "../linker/module.h"
10#include "../linker/segment.h"
11#include "../linker/segment_manager.h"
12#include "../linker/writer.h"
13
14/* TODO: most of this code is not tested, it can parse and dump executable binaries */
15
16namespace Apple
17{
24 class OMFFormat : public virtual Linker::SegmentManager
25 {
26 public:
27 class Segment
28 {
29 public:
31 offset_t segment_offset = 0;
33 offset_t total_segment_size = 0;
35 offset_t bss_size = 0;
37 offset_t total_size = 0;
39 {
41 SEG_CODE = 0x00,
43 SEG_DATA = 0x01,
51 SEG_INIT = 0x10,
56 };
60 uint16_t flags = 0;
62 uint8_t label_length = 0;
64 uint8_t number_length = 4;
65 enum omf_version
66 {
67 OMF_VERSION_0 = 0x0000, // TODO: unsure
68 OMF_VERSION_1 = 0x0100,
69 OMF_VERSION_2 = 0x0200,
70 OMF_VERSION_2_1 = 0x0201,
71 };
73 omf_version version = OMF_VERSION_2;
75 offset_t bank_size = 0;
77 offset_t base_address = 0;
79 offset_t align = 0x100;
81 uint8_t endiantype = 0;
83 uint8_t language_card_bank = 0;
85 uint16_t segment_number = 0;
87 offset_t entry = 0;
89 offset_t segment_name_offset = 0x2C;
91 offset_t segment_data_offset = 0;
93 offset_t temp_org = 0;
97 std::string segment_name;
98
100 static const uint16_t FLAG_BANK_RELATIVE = 0x0100;
102 static const uint16_t FLAG_SKIP_SEGMENT = 0x0200;
104 static const uint16_t FLAG_RELOAD = 0x0400;
106 static const uint16_t FLAG_ABSOLUTE_BANK = 0x0800;
108 static const uint16_t FLAG_NO_SPECIAL_MEMORY = 0x1000;
110 static const uint16_t FLAG_POSITION_INDEPENDENT = 0x2000;
112 static const uint16_t FLAG_PRIVATE = 0x4000;
114 static const uint16_t FLAG_DYNAMIC = 0x8000;
115
116 ::EndianType GetEndianType() const;
117
119 offset_t ReadUnsigned(const std::shared_ptr<Linker::Reader>& rd) const;
121 void WriteWord(const std::shared_ptr<Linker::Writer>& wr, offset_t value) const;
122
124 std::string ReadLabel(const std::shared_ptr<Linker::Reader>& rd) const;
126 void WriteLabel(const std::shared_ptr<Linker::Writer>& wr, std::string text) const;
127
134 offset_t CalculateValues(uint16_t segment_number, offset_t current_offset);
135 void ReadFile(const std::shared_ptr<Linker::Reader>& rd);
136 void WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
137 void Dump(Dumper::Dumper& dump, const OMFFormat& omf, unsigned segment_index) const;
138
139 size_t ReadData(size_t bytes, offset_t offset, void * buffer) const;
140 offset_t ReadUnsigned(size_t bytes, offset_t offset) const;
141
143 {
144 public:
145 // TODO: untested
146
152 {
153 End = 0x00,
154 Addition = 0x01,
155 Subtraction = 0x02,
156 Multiplication = 0x03,
157 Division = 0x04,
158 IntegerRemainder = 0x05,
159 Negation = 0x06,
160 BitShift = 0x07,
161 And = 0x08,
162 Or = 0x09,
163 EOr = 0x0A,
164 Not = 0x0B,
165 LessOrEqualTo = 0x0C,
166 GreaterOrEqualTo = 0x0D,
167 NotEqual = 0x0E,
168 LessThan = 0x0F,
169 GreaterThan = 0x10,
170 EqualTo = 0x11,
171 BitAnd = 0x12,
172 BitOr = 0x13,
173 BitEOr = 0x14,
174 BitNot = 0x15,
175 LocationCounterOperand = 0x80,
176 ConstantOperand = 0x81,
177 WeakLabelReferenceOperand = 0x82,
178 LabelReferenceOperand = 0x83,
179 LengthOfLabelReferenceOperand = 0x84,
180 TypeOfLabelReferenceOperand = 0x85,
181 CountOfLabelReferenceOperand = 0x86,
182 RelativeOffsetOperand = 0x87,
183
186 };
187
191 std::vector<std::unique_ptr<Expression>> operands;
193 std::optional<std::variant<offset_t, std::string>> value;
194
197 {
198 }
199
200 Expression(int operation, std::unique_ptr<Expression>& operand)
202 {
203 operands.emplace_back(std::move(operand));
204 }
205
206 Expression(int operation, std::unique_ptr<Expression>& operand1, std::unique_ptr<Expression>& operand2)
208 {
209 operands.emplace_back(std::move(operand1));
210 operands.emplace_back(std::move(operand2));
211 }
212
213 Expression(int operation, offset_t value)
215 {
216 }
217
218 Expression(int operation, std::string value)
220 {
221 }
222
223 offset_t GetLength(const Segment& segment) const;
224 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd);
225 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const;
227 std::string GetStandardNotation() const;
228 protected:
230 void PopElementsInto(size_t count, std::vector<std::unique_ptr<Expression>>& target);
232 uint8_t ReadSingleOperation(Segment& segment, const std::shared_ptr<Linker::Reader>& rd);
233
235 {
236 enum precedence_type
237 {
238 Or,
239 EOr,
240 And,
241 LessThan,
242 EqualTo,
243 BitOr,
244 BitEOr,
245 BitAnd,
246 BitShift,
247 Addition,
248 Multiplication,
249 Negation,
250 };
251 };
252 typedef precedence::precedence_type precedence_type;
253 void GetStandardNotation(std::ostream& out, precedence_type precedence) const;
254 };
255
257 class Record
258 {
259 public:
260 enum record_type
261 {
262 // E: executable, O: object, L: library
263 OPC_END = 0x00, // EOL
264 OPC_CONST_BASE = 0x00,
265 OPC_CONST_FIRST = 0x01, // O
266 OPC_CONST_LAST = 0xDF, // O
267 OPC_ALIGN = 0xE0, // O
268 OPC_ORG = 0xE1, // O
269 OPC_RELOC = 0xE2, // E
270 OPC_INTERSEG = 0xE3, // E
271 OPC_USING = 0xE4, // O
272 OPC_STRONG = 0xE5, // O
273 OPC_GLOBAL = 0xE6, // O
274 OPC_GEQU = 0xE7, // O
275 OPC_MEM = 0xE8, // O
276 OPC_EXPR = 0xEB, // O
277 OPC_ZEXPR = 0xEC, // O
278 OPC_BEXPR = 0xED, // O
279 OPC_RELEXPR = 0xEE, // O
280 OPC_LOCAL = 0xEF, // O
281 OPC_EQU = 0xF0, // O
282 OPC_DS = 0xF1, // EOL
283 OPC_LCONST = 0xF2, // EOL
284 OPC_LEXPR = 0xF3, // O
285 OPC_ENTRY = 0xF4, // L
286 OPC_C_RELOC = 0xF5, // E
287 OPC_C_INTERSEG = 0xF6, // E
288 OPC_SUPER = 0xF7, // E (V2)
289 };
290 record_type type;
291
292 Record(record_type type)
293 : type(type)
294 {
295 }
296
297 virtual ~Record() = default;
302 virtual offset_t GetLength(const Segment& segment) const;
307 virtual offset_t GetMemoryLength(const Segment& segment, offset_t current_address) const;
308 virtual void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd);
309 virtual void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const;
320 virtual void Dump(Dumper::Dumper& dump, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address, int display_options = Dumper::None) const;
322 virtual void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const;
324 virtual void AddSignals(Dumper::Block& block, offset_t current_segment_offset) const;
326 virtual void ReadData(size_t bytes, offset_t offset, void * buffer) const;
327 };
328
330 class DataRecord : public Record
331 {
332 public:
333 std::shared_ptr<Linker::Contents> image;
334
335 DataRecord(record_type type, std::shared_ptr<Linker::Contents> image)
336 : Record(type), image(image)
337 {
338 }
339
340 DataRecord(record_type type)
341 : Record(type)
342 {
343 }
344
345 offset_t GetLength(const Segment& segment) const override;
346 offset_t GetMemoryLength(const Segment& segment, offset_t current_address) const override;
347 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
348 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
349 void Dump(Dumper::Dumper& dump, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address, int display_options = Dumper::None) const override;
350 void ReadData(size_t bytes, offset_t offset, void * buffer) const override;
351 };
352
354 class ValueRecord : public Record
355 {
356 public:
357 offset_t value;
358
359 ValueRecord(record_type type, offset_t value)
360 : Record(type), value(value)
361 {
362 }
363
364 offset_t GetLength(const Segment& segment) const override;
365 offset_t GetMemoryLength(const Segment& segment, offset_t current_address) const override;
366 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
367 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
368 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
369 void ReadData(size_t bytes, offset_t offset, void * buffer) const override;
370 };
371
374 {
375 public:
376 uint8_t size = 0;
377 int8_t shift = 0;
378 offset_t source = 0;
379 offset_t target = 0;
380
381 RelocationRecord(record_type type)
382 : Record(type)
383 {
384 }
385
386 RelocationRecord(record_type type, uint8_t size, int8_t shift, offset_t source, offset_t target)
387 : Record(type), size(size), shift(shift), source(source), target(target)
388 {
389 }
390
391 offset_t GetLength(const Segment& segment) const override;
392 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
393 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
394 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
395 void AddSignals(Dumper::Block& block, offset_t current_segment_offset) const override;
396 };
397
400 {
401 public:
402 uint16_t file_number = 0;
403 uint16_t segment_number = 0;
404
406 : RelocationRecord(record_type(0))
407 {
408 }
409
410 IntersegmentRelocationRecord(record_type type)
411 : RelocationRecord(type)
412 {
413 }
414
415 IntersegmentRelocationRecord(record_type type, uint8_t size, uint8_t shift, offset_t source, uint16_t file_number, uint16_t segment_number, offset_t target)
416 : RelocationRecord(type, size, shift, source, target), file_number(file_number), segment_number(segment_number)
417 {
418 }
419
420 offset_t GetLength(const Segment& segment) const override;
421 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
422 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
423 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
424 };
425
427 class StringRecord : public Record
428 {
429 public:
430 std::string name;
431
432 StringRecord(record_type type, std::string name)
433 : Record(type), name(name)
434 {
435 }
436
437 offset_t GetLength(const Segment& segment) const override;
438 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
439 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
440 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
441 };
442
444 class LabelRecord : public Record
445 {
446 public:
447 std::string name;
448 uint16_t line_length = 0;
449 enum operation_type
450 {
451 OP_ADDRESS_DC = 'A',
452 OP_BOOL_DC = 'B',
453 OP_CHAR_DC = 'C',
454 OP_DOUBLE_DC = 'D',
455 OP_FLOAT_DC = 'E',
456 OP_EQU_GEQU = 'G',
457 OP_HEX_DC = 'H',
458 OP_INT_DC = 'I',
459 OP_REF_ADDRESS_DC = 'K',
460 OP_SOFT_REF_DC = 'L',
461 OP_INSTRUCTION = 'M',
462 OP_ASM_DIRECTIVE = 'N',
463 OP_ORG = 'O',
464 OP_ALIGN = 'P',
465 OP_DS = 'S',
466 OP_ARITHMETIC_SYMBOL = 'X',
467 OP_BOOL_SYMBOL = 'Y',
468 OP_CHAR_SYMBOL = 'Z'
469 };
470 operation_type operation = operation_type(0);
471 uint16_t private_flag = 0;
472
473 LabelRecord(record_type type)
474 : Record(type)
475 {
476 }
477
478 LabelRecord(record_type type, std::string name, uint16_t line_length, int operation, uint16_t private_flag)
479 : Record(type), name(name), line_length(line_length), operation(operation_type(operation)), private_flag(private_flag)
480 {
481 }
482
483 offset_t GetLength(const Segment& segment) const override;
484 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
485 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
486 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
487 };
488
491 {
492 public:
493 std::unique_ptr<Expression> expression;
494
495 LabelExpressionRecord(record_type type)
496 : LabelRecord(type)
497 {
498 }
499
500 LabelExpressionRecord(record_type type, std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression)
501 : LabelRecord(type, name, line_length, operation, private_flag), expression(std::move(expression))
502 {
503 }
504
505 offset_t GetLength(const Segment& segment) const override;
506 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
507 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
508 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
509 };
510
512 class RangeRecord : public Record
513 {
514 public:
515 offset_t start = 0;
516 offset_t end = 0;
517
518 RangeRecord(record_type type)
519 : Record(type)
520 {
521 }
522
523 RangeRecord(record_type type, offset_t start, offset_t end)
524 : Record(type), start(start), end(end)
525 {
526 }
527
528 offset_t GetLength(const Segment& segment) const override;
529 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
530 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
531 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
532 };
533
536 {
537 public:
538 uint8_t size = 0;
539 std::unique_ptr<Expression> expression;
540
541 ExpressionRecord(record_type type)
542 : Record(type)
543 {
544 }
545
546 ExpressionRecord(record_type type, uint8_t size, std::unique_ptr<Expression> expression)
547 : Record(type), size(size), expression(std::move(expression))
548 {
549 }
550
551 offset_t GetLength(const Segment& segment) const override;
552 offset_t GetMemoryLength(const Segment& segment, offset_t current_address) const override;
553 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
554 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
555 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
556 void ReadData(size_t bytes, offset_t offset, void * buffer) const override;
557 };
558
561 {
562 public:
563 offset_t origin = 0;
564
565 RelativeExpressionRecord(record_type type)
566 : ExpressionRecord(type)
567 {
568 }
569
570 RelativeExpressionRecord(record_type type, uint8_t size, offset_t origin, std::unique_ptr<Expression> expression)
571 : ExpressionRecord(type, size, std::move(expression)), origin(origin)
572 {
573 }
574
575 offset_t GetLength(const Segment& segment) const override;
576 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
577 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
578 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
579 };
580
582 class EntryRecord : public Record
583 {
584 public:
585 uint16_t segment_number;
586 offset_t location;
587 std::string name;
588
589 EntryRecord(record_type type)
590 : Record(type)
591 {
592 }
593
594 EntryRecord(record_type type, uint16_t segment_number, offset_t location, std::string name)
595 : Record(type), segment_number(segment_number), location(location), name(name)
596 {
597 }
598
599 offset_t GetLength(const Segment& segment) const override;
600 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
601 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
602 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
603 };
604
607 {
608 public:
609 enum super_record_type
610 {
611 SUPER_RELOC2,
612 SUPER_RELOC3,
613 SUPER_INTERSEG1,
614 SUPER_INTERSEG13 = SUPER_INTERSEG1 - 1 + 13,
615 SUPER_INTERSEG25 = SUPER_INTERSEG1 - 1 + 25,
616 SUPER_INTERSEG36 = SUPER_INTERSEG1 - 1 + 36,
617 };
618
619 super_record_type super_type = super_record_type(0);
620
621 std::vector<uint16_t> offsets;
622
623 SuperCompactRecord(record_type type, super_record_type super_type = super_record_type(0))
624 : Record(type), super_type(super_type)
625 {
626 }
627
628 offset_t GetLength(const Segment& segment) const override;
629 void ReadFile(Segment& segment, const std::shared_ptr<Linker::Reader>& rd) override;
630 void WriteFile(const Segment& segment, const std::shared_ptr<Linker::Writer>& wr) const override;
631 private:
632 void WritePatchList(const std::shared_ptr<Linker::Writer>& wr, const std::vector<uint8_t>& patches) const;
633
634 public:
635 void Dump(Dumper::Dumper& dump, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address, int display_options = Dumper::None) const override;
636 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, const OMFFormat& omf, const Segment& segment, unsigned index, offset_t file_offset, offset_t address) const override;
637 void AddSignals(Dumper::Block& block, offset_t current_segment_offset) const override;
638
640 bool GetRelocation(IntersegmentRelocationRecord& relocation, unsigned index) const;
642 bool GetRelocation(IntersegmentRelocationRecord& relocation, unsigned index, const Segment& segment) const;
643 };
644
645 std::vector<std::unique_ptr<Record>> records;
646
647 std::unique_ptr<Expression> ReadExpression(const std::shared_ptr<Linker::Reader>& rd);
648
649 std::unique_ptr<Record> ReadRecord(const std::shared_ptr<Linker::Reader>& rd);
650
651 std::unique_ptr<Record> makeEND();
652 std::unique_ptr<Record> makeCONST(std::shared_ptr<Linker::Contents> image);
653 std::unique_ptr<Record> makeCONST(size_t length);
654 std::unique_ptr<Record> makeALIGN(offset_t align = 0);
655 std::unique_ptr<Record> makeORG(offset_t value = 0);
656 std::unique_ptr<Record> makeRELOC(uint8_t size, uint8_t shift, offset_t source, offset_t target);
657 std::unique_ptr<Record> makeRELOC();
658 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);
659 std::unique_ptr<Record> makeINTERSEG();
660 std::unique_ptr<Record> makeUSING(std::string name = "");
661 std::unique_ptr<Record> makeSTRONG(std::string name = "");
662 std::unique_ptr<Record> makeGLOBAL();
663 std::unique_ptr<Record> makeGLOBAL(std::string name, uint16_t line_length, int operation, uint16_t private_flag);
664 std::unique_ptr<Record> makeGEQU();
665 std::unique_ptr<Record> makeGEQU(std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression);
666 std::unique_ptr<Record> makeMEM();
667 std::unique_ptr<Record> makeMEM(offset_t start, offset_t end);
668 std::unique_ptr<Record> makeEXPR();
669 std::unique_ptr<Record> makeEXPR(uint8_t size, std::unique_ptr<Expression> expression);
670 std::unique_ptr<Record> makeZEXPR();
671 std::unique_ptr<Record> makeZEXPR(uint8_t size, std::unique_ptr<Expression> expression);
672 std::unique_ptr<Record> makeBEXPR();
673 std::unique_ptr<Record> makeBEXPR(uint8_t size, std::unique_ptr<Expression> expression);
674 std::unique_ptr<Record> makeRELEXPR();
675 std::unique_ptr<Record> makeRELEXPR(uint8_t size, offset_t origin, std::unique_ptr<Expression> expression);
676 std::unique_ptr<Record> makeLOCAL();
677 std::unique_ptr<Record> makeLOCAL(std::string name, uint16_t line_length, int operation, uint16_t private_flag);
678 std::unique_ptr<Record> makeEQU();
679 std::unique_ptr<Record> makeEQU(std::string name, uint16_t line_length, int operation, uint16_t private_flag, std::unique_ptr<Expression> expression);
680 std::unique_ptr<Record> makeDS(offset_t count = 0);
681 std::unique_ptr<Record> makeLCONST();
682 std::unique_ptr<Record> makeLCONST(std::shared_ptr<Linker::Contents> image);
683 std::unique_ptr<Record> makeLEXPR();
684 std::unique_ptr<Record> makeLEXPR(uint8_t size, std::unique_ptr<Expression> expression);
685 std::unique_ptr<Record> makeENTRY();
686 std::unique_ptr<Record> makeENTRY(uint16_t segment_number, offset_t location, std::string name);
687 std::unique_ptr<Record> makecRELOC(uint8_t size, uint8_t shift, uint16_t source, uint16_t target);
688 std::unique_ptr<Record> makecRELOC();
689 std::unique_ptr<Record> makecINTERSEG(uint8_t size, uint8_t shift, uint16_t source, uint16_t segment_number, uint16_t target);
690 std::unique_ptr<Record> makecINTERSEG();
691 std::unique_ptr<Record> makeSUPER(SuperCompactRecord::super_record_type super_type = SuperCompactRecord::super_record_type(0));
692 };
693
694 std::vector<std::unique_ptr<Segment>> segments;
695
696 void CalculateValues() override;
697 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
699 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
700 offset_t ImageSize() const override;
701 void Dump(Dumper::Dumper& dump) const override;
702 /* TODO */
703 };
704
709 {
710 public:
711 static constexpr uint32_t FreeBlockSize = 8;
712 static constexpr uint32_t ReferenceRecordSize = 20;
713
714 uint32_t file_version = 0;
715 uint32_t file_to_map = 0;
716 uint32_t file_map_size = 0;
717 std::shared_ptr<Linker::Contents> file_memo;
718
719 uint32_t map_next = 0;
720 uint16_t map_flag = 0;
721 uint32_t map_offset = 0;
722 uint32_t map_size = 0;
723 uint16_t map_to_index = 0;
724 uint16_t map_file_num = 0;
725 uint16_t map_id = 0;
726 uint32_t map_index_size = 0;
727 uint32_t map_index_used = 0;
728 uint16_t map_free_list_size = 0;
729 uint16_t map_free_list_used = 0;
730
732 {
733 public:
734 uint32_t offset = 0;
735 uint32_t size = 0;
736
737 static FreeBlock ReadFile(const std::shared_ptr<Linker::Reader>& rd);
738 void WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
739 void Dump(const GSOSResourceFileFormat& format, Dumper::Dumper& dump, size_t index) const;
740 };
741
743 {
744 public:
745 uint16_t type = 0;
746 uint32_t id = 0;
747 uint32_t offset = 0;
748 uint16_t attributes = 0;
749 uint32_t size = 0;
750 uint32_t handle = 0;
751
752 std::shared_ptr<Linker::Contents> image;
753
754 static std::shared_ptr<ReferenceRecord> ReadFile(const std::shared_ptr<Linker::Reader>& rd);
755 void WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
756
757 void ReadContents(GSOSResourceFileFormat& format, const std::shared_ptr<Linker::Reader>& rd);
758 void WriteContents(const GSOSResourceFileFormat& format, const std::shared_ptr<Linker::Writer>& wr) const;
759 void Dump(const GSOSResourceFileFormat& format, Dumper::Dumper& dump, size_t index) const;
760 };
761
762 std::vector<FreeBlock> free_list;
763 std::vector<std::shared_ptr<ReferenceRecord>> map_index;
764
765 /* TODO */
766 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
768 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
769 offset_t ImageSize() const override;
770 void Dump(Dumper::Dumper& dump) const override;
771 };
772
783 {
784 public:
800
811
812 /* the ProDOS file type */
813 enum file_type_t : uint8_t
814 {
815 FILE_TYPE_BIN = 0x06,
816 FILE_TYPE_SOS = 0x0C,
817 FILE_TYPE_S16 = 0xB3,
818 FILE_TYPE_EXE = 0xB5,
819 FILE_TYPE_SYS = 0xFF,
820 };
821
822 // TODO: move to OutputDriver
823 GSOutputDriver(target_format_t target = TARGET_DATA_FORK)
824 : OutputDriver(OutputDriver::target_format_t(target),
825 OutputDriver::produce_format_t(
827 : produce_format_t(0)))
828 {
829 }
830
831 // TODO: move to OutputDriver
832 GSOutputDriver(target_format_t target, int produce)
833 : OutputDriver(OutputDriver::target_format_t(target), OutputDriver::produce_format_t(produce))
834 {
835 }
836
838 std::shared_ptr<GSOSResourceFileFormat> resource_fork;
839
840 protected:
841 bool SupportedSupplementaryFormat(OutputDriver::produce_format_t produce) override;
842 };
843}
844
845#endif /* GSOS_H */
A GS/OS resource fork.
Definition gsos.h:709
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition gsos.cc:1992
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition gsos.cc:2034
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition gsos.cc:2085
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition gsos.cc:2079
This is not actually a file format, but an interface to permit generating multiple binary outputs for...
Definition gsos.h:783
std::shared_ptr< GSOSResourceFileFormat > resource_fork
Definition gsos.h:838
produce_format_t
Represents what additional files should be generated.
Definition gsos.h:803
@ PRODUCE_RESOURCE_FORK
Places a GS/OS format resource file under the directory .rsrc.
Definition gsos.h:805
@ PRODUCE_APPLE_DOUBLE
Creates an AppleDouble binary with the '' prefix.
Definition gsos.h:807
@ PRODUCE_NAPS_SUFFIX
NuLib2 attribute preservation string suffix, such as #06xxxx.
Definition gsos.h:809
target_format_t
Represents the file type of the main file.
Definition gsos.h:787
@ TARGET_RESOURCE_FORK
Main file is a resource fork.
Definition gsos.h:793
@ TARGET_APPLE_SINGLE
Main file is an AppleSingle.
Definition gsos.h:795
@ TARGET_DATA_FORK
Main file is a data fork, typically empty.
Definition gsos.h:791
@ TARGET_APPLE_DOUBLE
Main file is an AppleDouble.
Definition gsos.h:797
@ TARGET_NONE
Do not generate main file.
Definition gsos.h:789
Represents a CONST or LCONST record, containing a sequence of bytes.
Definition gsos.h:331
void ReadData(size_t bytes, offset_t offset, void *buffer) const override
Attempts to read data from the in-memory image, if possible, it can be assumed that offset + bytes <=...
Definition gsos.cc:893
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:836
offset_t GetMemoryLength(const Segment &segment, offset_t current_address) const override
Returns the amount of memory the record occupies when loaded into memory. Most records have a length ...
Definition gsos.cc:848
void Dump(Dumper::Dumper &dump, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address, int display_options=Dumper::None) const override
Displays information pertaining to this record.
Definition gsos.cc:880
Represents an ENTRY record.
Definition gsos.h:583
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1286
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1266
Represents an EXPR, ZEXPR, BEXPR or LEXPR record.
Definition gsos.h:536
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1229
void ReadData(size_t bytes, offset_t offset, void *buffer) const override
Attempts to read data from the in-memory image, if possible, it can be assumed that offset + bytes <=...
Definition gsos.cc:1235
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1206
offset_t GetMemoryLength(const Segment &segment, offset_t current_address) const override
Returns the amount of memory the record occupies when loaded into memory. Most records have a length ...
Definition gsos.cc:1211
std::optional< std::variant< offset_t, std::string > > value
A value corresponding to an operation, such as an integer constant or a label name.
Definition gsos.h:193
uint8_t ReadSingleOperation(Segment &segment, const std::shared_ptr< Linker::Reader > &rd)
Reads a single byte of operation (plus optional number and label) and modifies the current list of op...
Definition gsos.cc:459
std::vector< std::unique_ptr< Expression > > operands
The operands the operation takes.
Definition gsos.h:191
void PopElementsInto(size_t count, std::vector< std::unique_ptr< Expression > > &target)
Removes elements from the top of the operands stack and copies them into target. On stack underflow,...
Definition gsos.cc:444
operation_type
Represents an operation inside an expression in the object file.
Definition gsos.h:152
@ StackUnderflow
A symbolic value to represent a stack underflow condition, it should not be printed back into a binar...
Definition gsos.h:185
std::string GetStandardNotation() const
Converts expression into a C-like syntax.
Definition gsos.cc:437
operation_type operation
The type of operation, End means that the result is the last operand.
Definition gsos.h:189
Represents an INTERSEG or cINTERSEG record, containing an intersegment relocation.
Definition gsos.h:400
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1060
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1008
Represents an EQU or GEQU record.
Definition gsos.h:491
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1176
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1152
Represents a LOCAL or GLOBAL record.
Definition gsos.h:445
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1092
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1114
Represents a MEM record.
Definition gsos.h:513
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1200
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1182
A single record inside the segment body, also represents an END record.
Definition gsos.h:258
virtual void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:824
virtual void AddSignals(Dumper::Block &block, offset_t current_segment_offset) const
If this is a relocation record, add the relocation signals to the block.
Definition gsos.cc:828
virtual void ReadData(size_t bytes, offset_t offset, void *buffer) const
Attempts to read data from the in-memory image, if possible, it can be assumed that offset + bytes <=...
Definition gsos.cc:832
virtual void Dump(Dumper::Dumper &dump, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address, int display_options=Dumper::None) const
Displays information pertaining to this record.
Definition gsos.cc:782
virtual offset_t GetMemoryLength(const Segment &segment, offset_t current_address) const
Returns the amount of memory the record occupies when loaded into memory. Most records have a length ...
Definition gsos.cc:768
virtual offset_t GetLength(const Segment &segment) const
Returns the size of the record, as stored in the file.
Definition gsos.cc:763
Represents a RELEXPR record.
Definition gsos.h:561
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1240
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1260
Represents a RELOC or cRELOC record, containing an intrasegment relocation.
Definition gsos.h:374
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:947
void AddSignals(Dumper::Block &block, offset_t current_segment_offset) const override
If this is a relocation record, add the relocation signals to the block.
Definition gsos.cc:1000
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:992
Represents a USING or STRONG record, containing a string.
Definition gsos.h:428
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1087
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1071
Represents a SUPER record.
Definition gsos.h:607
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:1292
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:1421
void Dump(Dumper::Dumper &dump, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address, int display_options=Dumper::None) const override
Displays information pertaining to this record.
Definition gsos.cc:1398
bool GetRelocation(IntersegmentRelocationRecord &relocation, unsigned index) const
Expands the super compact relocation into a full relocation, without filling in the target fields.
Definition gsos.cc:1451
void AddSignals(Dumper::Block &block, offset_t current_segment_offset) const override
If this is a relocation record, add the relocation signals to the block.
Definition gsos.cc:1440
Represents an ALIGN, ORG or DS record, containing an integer.
Definition gsos.h:355
offset_t GetMemoryLength(const Segment &segment, offset_t current_address) const override
Returns the amount of memory the record occupies when loaded into memory. Most records have a length ...
Definition gsos.cc:904
offset_t GetLength(const Segment &segment) const override
Returns the size of the record, as stored in the file.
Definition gsos.cc:899
void ReadData(size_t bytes, offset_t offset, void *buffer) const override
Attempts to read data from the in-memory image, if possible, it can be assumed that offset + bytes <=...
Definition gsos.cc:942
void AddFields(Dumper::Dumper &dump, Dumper::Region &region, const OMFFormat &omf, const Segment &segment, unsigned index, offset_t file_offset, offset_t address) const override
Adds any further fields to the file region that encompasses this record.
Definition gsos.cc:929
Definition gsos.h:28
offset_t segment_offset
Offset of segment within file.
Definition gsos.h:31
uint8_t label_length
(LABLEN) Label length, or 0 for variable length labels
Definition gsos.h:62
offset_t total_size
(LENGTH) Total size of segment when loaded into memory, including the additional zeroes
Definition gsos.h:37
offset_t bss_size
(RESSPC) Additional zeroes to append to segment
Definition gsos.h:35
offset_t base_address
(ORG) Base address of segment
Definition gsos.h:77
uint8_t language_card_bank
(LCBANK) Language card bank
Definition gsos.h:83
uint8_t number_length
(NUMLEN) Number length, must be 4
Definition gsos.h:64
omf_version version
(VERSION, REVISION) OMF file format version
Definition gsos.h:73
static const uint16_t FLAG_NO_SPECIAL_MEMORY
Segment flag: Do not load in special memory (version 2 only)
Definition gsos.h:108
std::string linker_segment_name
(LOADNAME) Name of segment according to linker
Definition gsos.h:95
offset_t align
(ALIGN) Segment alignment
Definition gsos.h:79
static const uint16_t FLAG_PRIVATE
Segment flag: Private.
Definition gsos.h:112
static const uint16_t FLAG_ABSOLUTE_BANK
Segment flag: Absolute bank segment (version 2 only)
Definition gsos.h:106
offset_t temp_org
(tempOrg) (only version 2.1, optional)
Definition gsos.h:93
void WriteLabel(const std::shared_ptr< Linker::Writer > &wr, std::string text) const
Writes a string the size of label_length, or variable length if it is 0.
Definition gsos.cc:43
static const uint16_t FLAG_RELOAD
Segment flag: Reload segment (version 2 only)
Definition gsos.h:104
segment_kind kind
(KIND) Segment type
Definition gsos.h:58
offset_t total_segment_size
(BYTECNT/BLKCNT) Total size of the segment, including the header, as stored in file
Definition gsos.h:33
void WriteWord(const std::shared_ptr< Linker::Writer > &wr, offset_t value) const
Writes a number the size of number_length.
Definition gsos.cc:28
std::string segment_name
(LOADNAME) Name of segment
Definition gsos.h:97
offset_t entry
(ENTRY) Entry point (not present in version 0)
Definition gsos.h:87
uint8_t endiantype
(NUMSEX) Endianness, must be 0 for LittleEndian
Definition gsos.h:81
offset_t bank_size
(BANKSIZE) Maximum bank size of segment
Definition gsos.h:75
static const uint16_t FLAG_POSITION_INDEPENDENT
Segment flag: Position independent.
Definition gsos.h:110
offset_t segment_data_offset
(DISPDATA) Offset to segment data, typically appearing after segment_name (not present in version 0)
Definition gsos.h:91
static const uint16_t FLAG_BANK_RELATIVE
Segment flag: Bank relative (version 2 only)
Definition gsos.h:100
static const uint16_t FLAG_DYNAMIC
Segment flag: Dynamic.
Definition gsos.h:114
std::string ReadLabel(const std::shared_ptr< Linker::Reader > &rd) const
Reads a string the size of label_length, or variable length if it is 0.
Definition gsos.cc:33
static const uint16_t FLAG_SKIP_SEGMENT
Segment flag: Skip segment (version 2 only)
Definition gsos.h:102
offset_t ReadUnsigned(const std::shared_ptr< Linker::Reader > &rd) const
Reads a number the size of number_length.
Definition gsos.cc:23
uint16_t flags
(KIND) Segment flags
Definition gsos.h:60
uint16_t segment_number
(SEGNUM) Segment number (not present in version 0)
Definition gsos.h:85
offset_t segment_name_offset
(DISPNAME) Offset to linker_segment_name (LOADNAME), (not present in version 0)
Definition gsos.h:89
segment_kind
Definition gsos.h:39
@ SEG_CODE
Code segment.
Definition gsos.h:41
@ SEG_DIRPAGE
Direct page/stack segment.
Definition gsos.h:55
@ SEG_JUMPTABLE
Jump table segment.
Definition gsos.h:45
@ SEG_INIT
Initialization segment.
Definition gsos.h:51
@ SEG_PATHNAME
Pathname segment.
Definition gsos.h:47
@ SEG_DATA
Data segment.
Definition gsos.h:43
@ SEG_LIBDICT
Library dictionary segment.
Definition gsos.h:49
@ SEG_ABSBANK
Absolute bank segment (version 1 only)
Definition gsos.h:53
Apple GS/OS OMF file format.
Definition gsos.h:25
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition gsos.cc:740
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition gsos.cc:719
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition gsos.cc:730
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition gsos.cc:710
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition gsos.cc:747
This is not actually a file format, but an interface to permit generating multiple binary outputs for...
Definition apple.h:709
produce_format_t
Represents what additional files should be generated.
Definition apple.h:731
@ PRODUCE_NAPS_SUFFIX
NuLib2 attribute preservation string suffix, such as #06xxxx (Apple II, III, IIgs only)
Definition apple.h:741
@ PRODUCE_RESOURCE_FORK
Places a GS/OS format resource file under the directory .rsrc.
Definition apple.h:733
@ PRODUCE_APPLE_DOUBLE
Creates an AppleDouble binary with the '' prefix.
Definition apple.h:737
target_format_t target
Format of "filename".
Definition apple.h:746
@ TARGET_DATA_FORK
Main file is a data fork, typically empty.
Definition apple.h:717
@ TARGET_RESOURCE_FORK
Main file is a resource fork.
Definition apple.h:719
@ TARGET_APPLE_SINGLE
Main file is an AppleSingle.
Definition apple.h:721
@ TARGET_NONE
Do not generate main file.
Definition apple.h:715
@ TARGET_APPLE_DOUBLE
Main file is an AppleDouble.
Definition apple.h:723
produce_format_t produce
Bitset of other files to produce.
Definition apple.h:749
A region within a file that can be dumped, decompiled, and it may contain fixups.
Definition dumper.h:941
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:1009
A record that represents a region within the file.
Definition dumper.h:902
offset_t WriteFile(const std::shared_ptr< Writer > &wr) const override=0
Stores data in memory to file.
offset_t file_offset
The offset of the first byte used by this format in the file it is stored in.
Definition format.h:34
A helper class to collect sections into segments.
Definition segment_manager.h:32
offset_t current_address
Holds the current address value when there is no current_segment.
Definition segment_manager.h:37