RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
pefexe.h
1#ifndef PEFEXE_H
2#define PEFEXE_H
3
4#include "macos.h"
5#include "../common.h"
6#include "../dumper/dumper.h"
7#include "../linker/buffer.h"
8#include "../linker/reader.h"
9#include "../linker/segment_manager.h"
10#include "../linker/writer.h"
11
12namespace Linker
13{
14 class Position;
15}
16
17namespace Apple
18{
25 {
26 public:
27 // values are stored as the bigendian 32-bit word
28 enum cpu_type
29 {
30 M68K = 0x6D36386B, // 'm68k'
31 PPC = 0x70777063, // 'pwpc'
32 };
33 cpu_type architecture;
34 uint32_t format_version = 1;
35 ::Timestamp<Macintosh_clock> date_time_stamp = { };
36 uint32_t old_def_version = 0;
37 uint32_t old_imp_version = 0;
38 uint32_t current_version = 0;
39 uint16_t section_count = 0;
40 uint16_t inst_section_count = 0;
41 // only for PEF stored in the resource fork
42 uint32_t memory_address = 0;
43 uint32_t exported_symbol_count = 0;
44 uint16_t secondary_resource_id = 0;
45 uint16_t last_valid_code_resource = 0;
46 uint32_t below_a5_size = 0;
47
61
62 PEFHeaderBase(binary_type type = UnknownBinary, cpu_type architecture = PPC)
63 : architecture(architecture), type(type)
64 {
65 }
66
67 PEFHeaderBase(const PEFHeaderBase&) = default;
68
69 void ReadBaseFields(const std::shared_ptr<Linker::Reader>& rd);
70 void WriteBaseFields(const std::shared_ptr<Linker::Writer>& wr) const;
71 void AddBaseFields(Dumper::Region& header_region) const;
72 };
73
77 class PEFFormat : public virtual Linker::SegmentManager
78 {
79 public:
80 std::shared_ptr<PEFHeaderBase> header;
81
82 enum target_system_type
83 {
84 MacOS,
85 Carbon,
86 BeOS, // TODO: unimplemented
87 };
88 target_system_type system_type = MacOS;
89
90 PEFFormat(PEFHeaderBase::binary_type type = PEFHeaderBase::UnknownBinary, PEFHeaderBase::cpu_type architecture = PEFHeaderBase::PPC)
91 : header(std::make_shared<PEFHeaderBase>(type, architecture))
92 {
93 }
94
95 PEFFormat(const PEFHeaderBase& base)
96 : header(std::make_shared<PEFHeaderBase>(base))
97 {
98 }
99
100 uint32_t reserved = 0;
101
107 {
108 public:
109 enum opcode_type
110 {
111 Zero = 0,
112 BlockCopy = 1,
113 RepeatedBlock = 2,
114 InterleaveRepeatBlockWithBlockCopy = 3,
115 InterleaveRepeatBlockWithZero = 4,
116 };
118 offset_t file_offset;
120 opcode_type opcode;
122 uint32_t count;
124 std::vector<uint8_t> common_data;
126 std::vector<std::vector<uint8_t>> custom_data;
127
129 static uint32_t ReadValue(const std::shared_ptr<Linker::Reader>& rd);
131 static size_t GetValueSize(uint32_t value, size_t size_hint = 0);
133 static void WriteValue(const std::shared_ptr<Linker::Writer>& wr, uint32_t value, size_t size_hint = 0);
134
136 void ReadFile(const std::shared_ptr<Linker::Reader>& rd);
138 void WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
140 offset_t CodeSize() const;
142 offset_t DataSize() const;
144 void ExpandData(Linker::Buffer& buffer) const;
145 };
146
147 class Section;
148 class ImportedSymbol;
149 class ImportedLibrary;
150
156 {
157 public:
158 // add 32-bit section start to offset
159 enum target_type
160 {
161 Section,
162 Symbol,
163 };
164 target_type type = Section;
165 bool compiled = true;
166 // section: section number, symbol: symbol number
167 uint32_t number = 0;
168 // only for section targets
169 std::weak_ptr<PEFFormat::Section> section;
170 // only for symbol targets
171 std::weak_ptr<ImportedSymbol> symbol;
172
173 static inline Relocation ToSection(uint32_t section_number)
174 {
175 Relocation relocation;
176 relocation.type = Section;
177 relocation.number = section_number;
178 return relocation;
179 }
180
181 static inline Relocation ToSection(std::weak_ptr<PEFFormat::Section> section)
182 {
183 Relocation relocation;
184 relocation.type = Section;
185 relocation.compiled = false;
186 relocation.section = section;
187 return relocation;
188 }
189
190 static inline Relocation ToSymbol(uint32_t symbol_number)
191 {
192 Relocation relocation;
193 relocation.type = Symbol;
194 relocation.number = symbol_number;
195 return relocation;
196 }
197
198 static inline Relocation ToSymbol(std::weak_ptr<ImportedSymbol> symbol)
199 {
200 Relocation relocation;
201 relocation.type = Symbol;
202 relocation.compiled = false;
203 relocation.symbol = symbol;
204 return relocation;
205 }
206 };
207
208 class RelocOpcode;
209
218 {
219 public:
220 const PEFFormat& pef_format;
221
222 size_t reloc_instr_ptr = 0;
223 uint32_t reloc_address = 0;
224 uint32_t import_index = 0;
225 uint32_t section_c = 0;
226 uint32_t section_d = 0;
227 uint32_t current_repeat_count = 0;
228
229 std::vector<RelocOpcode>& reloc_opcodes;
230 std::map<uint32_t, Relocation>& relocations;
231
232 void Initialize();
233
234 RelocationProcessor(const PEFFormat& pef_format, std::vector<RelocOpcode>& reloc_opcodes, std::map<uint32_t, Relocation>& relocations)
235 : pef_format(pef_format), reloc_opcodes(reloc_opcodes), relocations(relocations)
236 {
237 Initialize();
238 }
239
240 void Advance(uint32_t offset)
241 {
242 reloc_address += offset;
243 }
244
245 void AddRelocation(Relocation relocation)
246 {
247 relocations[reloc_address] = relocation;
248 Advance(4);
249 }
250
251 void AddSection(uint32_t section_number)
252 {
253 AddRelocation(Relocation::ToSection(section_number));
254 }
255
256 void AddSectionC()
257 {
258 AddSection(section_c);
259 }
260
261 void AddSectionD()
262 {
263 AddSection(section_d);
264 }
265
266 void AddSymbol()
267 {
268 AddRelocation(Relocation::ToSymbol(import_index));
269 import_index ++;
270 }
271
273 void Regress(uint32_t block_count);
274
285 void Repeat(uint32_t block_count, uint32_t repeat_count)
286 {
287 // unless this is the last iteration of this block
288 if(current_repeat_count != 1)
289 {
290 // jump over this (already processed) instruction and the block
291 reloc_instr_ptr --;
292 Regress(block_count);
293 }
294
295 if(current_repeat_count == 0)
296 {
297 // iteration starts
298 current_repeat_count = repeat_count;
299 }
300 else
301 {
302 current_repeat_count --;
303 }
304 }
305
306 void GenerateRelocations();
307 };
308
311 {
312 public:
313 /* the values are chosen so that they can be bitwise or'd to the opcode word */
314 enum opcode_type
315 {
316 SmInvalid = -1,
317 //LgInvalid = -2,
318 BySectDWithSkip = 0x0000,
319 BySectC = 0x4000,
320 BySectD = 0x4200,
321 TVector12 = 0x4400,
322 TVector8 = 0x4600,
323 VTable8 = 0x4800,
324 ImportRun = 0x4A00,
325 SmByImport = 0x6000,
326 SmSetSectC = 0x6200,
327 SmSetSectD = 0x6400,
328 SmBySection = 0x6600,
329 IncrPosition = 0x8000,
330 SmRepeat = 0x9000,
331 SetPosition = 0xA000,
332 LgByImport = 0xA400,
333 LgRepeat = 0xB000,
334 LgBySection = 0xB400,
335 LgSetSectC = 0xB440,
336 LgSetSectD = 0xB480,
337 };
339 uint32_t offset = 0; // within file
341 opcode_type opcode = SmInvalid;
342
348 uint32_t value = 0;
349
350 /*union
351 {
352 uint32_t run_length; // BySectDWithSkip, BySect*, TVector*, VTable8, ImportRun
353 uint32_t repeat_count; // *Repeat
354 };*/
359 uint32_t repeat = 0;
360
361 RelocOpcode(opcode_type opcode = SmInvalid)
362 : opcode(opcode)
363 {
364 }
365
366 RelocOpcode(opcode_type opcode, uint32_t value, uint32_t repeat)
368 {
369 }
370
372 void ReadFile(const std::shared_ptr<Linker::Reader>& rd);
377 uint32_t GetWord() const;
379 offset_t CodeSize() const;
381 void WriteFile(const std::shared_ptr<Linker::Writer>& wr)
382 {
383 wr->WriteWord(CodeSize(), GetWord());
384 }
386 void GenerateRelocations(RelocationProcessor& processor) const;
387
388 void Dump(Dumper::Dumper& dump, const PEFFormat& pef_format, uint32_t opcode_index, int display_options = 0) const;
389 };
390
392 {
393 public:
394 enum section_type
395 {
396 Code = 0,
397 UnpackedData = 1,
398 PatternInitializedData = 2,
399 Constant = 3,
400 Loader = 4,
401 Debug = 5,
402 ExecutableData = 6,
403 Exception = 7,
404 Traceback = 8,
405 };
406 enum share_type
407 {
408 ProcessShare = 1,
409 GlobalShare = 4,
410 ProtectedShare = 5,
411 };
412 static constexpr uint32_t NoNameOffset = uint32_t(-1);
413 uint32_t name_offset = NoNameOffset;
414 std::string name = "";
415 uint32_t default_address = 0;
416 uint32_t total_size = 0;
417 uint32_t unpacked_size = 0;
418 uint32_t packed_size = 0;
419 uint32_t container_offset = 0;
420 section_type section_kind = Code;
421 share_type share_kind = ProcessShare;
422 uint8_t alignment = 0;
423 uint8_t reserved = 0;
424 // convenience field to determine index of symbol in table
425 uint32_t section_number = uint32_t(-1);
426
427 std::shared_ptr<Linker::Contents> image;
428 std::vector<PatternInitialization> patterns;
429 // only appearing in sections with relocations
430 std::map<uint32_t, Relocation> relocations;
431 std::vector<RelocOpcode> reloc_opcodes;
432 bool contains_relocations = false;
433 uint16_t reserved_a = 0;
434 uint32_t reloc_instr_size = 0;
435 uint32_t first_reloc_offset = 0;
436
437 Section() = default;
438 Section(section_type section_kind, share_type share_kind, std::shared_ptr<Linker::Contents> image)
439 : section_kind(section_kind), share_kind(share_kind), image(image)
440 {
441 alignment = ExpectedAlignment();
442 }
443
444 bool IsInstantiated() const
445 {
446 switch(section_kind)
447 {
448 case Code:
449 case UnpackedData:
450 case PatternInitializedData:
451 case Constant:
452 case ExecutableData:
453 return true;
454 default:
455 return false;
456 }
457 }
458
459 offset_t ExpectedAlignment() const
460 {
461 switch(section_kind)
462 {
463 case Code:
464 case UnpackedData:
465 case Constant:
466 case ExecutableData:
467 return 4;
468 case PatternInitializedData:
469 case Loader:
470 return 1;
471 default:
472 return 0;
473 }
474 }
475
486
488 void CompressData();
491
492 void ReadHeader(const std::shared_ptr<Linker::Reader>& rd);
493 void ReadFile(PEFFormat& pef_format, const std::shared_ptr<Linker::Reader>& rd);
494 size_t GetImageSize(PEFFormat& pef_format);
495 void CalculateValues(PEFFormat& pef_format);
496 void WriteHeader(const std::shared_ptr<Linker::Writer>& wr) const;
497 void WriteFile(const PEFFormat& pef_format, const std::shared_ptr<Linker::Writer>& wr) const;
498 };
499
500 // container header information
501
502 std::vector<std::shared_ptr<Section>> sections;
503 std::vector<std::string> section_name_table;
504 uint32_t section_name_table_end = 0;
505 offset_t image_size = 0;
506
507 static constexpr uint32_t ContainerHeaderSize = 40;
508 static constexpr uint32_t SectionHeaderSize = 28;
509
510 uint32_t GetSectionNameTableOffset() const
511 {
512 return ContainerHeaderSize + SectionHeaderSize * sections.size();
513 }
514
515 // loader section information
516 uint32_t loader_section_offset = 0; // duplicate value of sections[*]->container_offset for sections[*]->section_kind == Section::Loader
517
518 static constexpr uint32_t NoSection = uint32_t(-1);
519 static constexpr uint32_t Absolute = uint32_t(-2);
520 static constexpr uint32_t Reexported = uint32_t(-3);
521
524 {
525 std::weak_ptr<Section> section_pointer;
526 uint32_t section = NoSection;
527 uint32_t offset = 0;
528
529 void SetPosition(PEFFormat& pef_format, const Linker::Position& position);
530
531 bool IsPresent() const { return section != NoSection; }
532 void StoreSectionIndex()
533 {
534 auto actual_section = section_pointer.lock();
535 section = actual_section ? actual_section->section_number : NoSection;
536 }
537 };
538 Reference main_symbol, init_symbol, term_symbol;
539
541 class Name
542 {
543 public:
544 uint32_t name_offset = 0;
545 std::string name = "";
546 std::string LoadNameString(const PEFFormat& pef_format, const std::shared_ptr<Linker::Reader>& rd);
547 std::string LoadNameString(const PEFFormat& pef_format, const std::shared_ptr<Linker::Reader>& rd, uint16_t length);
548 void StoreNameString(PEFFormat& pef_format);
549 void StoreNameStringNoNull(PEFFormat& pef_format);
550
551 Name() = default;
552
553 Name(std::string name)
554 : name(name)
555 {
556 }
557 };
558
559 class ImportedLibrary;
560
561 enum symbol_class_type
562 {
563 Code = 0,
564 Data = 1,
565 TVect = 2,
566 TOC = 3,
567 Glue = 4,
568 };
569 static inline constexpr bool IsValidSymbolClass(int value)
570 {
571 switch(value)
572 {
573 case Code:
574 case Data:
575 case TVect:
576 case TOC:
577 case Glue:
578 return true;
579 default:
580 return false;
581 }
582 }
583
584 class ImportedSymbol : public Name
585 {
586 public:
587 symbol_class_type symbol_class = TVect;
588 uint8_t flags = 0;
589 // convenience field to determine index of symbol in table
590 uint32_t symbol_number = uint32_t(-1);
591
592 ImportedSymbol() = default;
593 ImportedSymbol(std::string name) : Name(name) { }
594 ImportedSymbol(std::string name, uint8_t flags) : Name(name), symbol_class(symbol_class_type(flags & 0x0F)), flags(flags & 0xF0) { }
595
596 std::weak_ptr<ImportedLibrary> library; // back link to library that includes it
597 };
598
599 class ImportedLibrary : public Name
600 {
601 public:
602 uint32_t old_imp_version = 0;
603 uint32_t current_version = 0;
604 uint32_t imported_symbol_count = 0;
605 uint32_t first_imported_symbol = 0;
606 std::vector<std::shared_ptr<ImportedSymbol>> imported_symbols;
607 // only used for generation
608 std::map<std::tuple<std::string, uint8_t>, std::shared_ptr<ImportedSymbol>> named_imported_symbols;
609 uint8_t options = 0;
610 uint8_t reserved_a = 0;
611 uint16_t reserved_b = 0;
612
613 ImportedLibrary() = default;
614 ImportedLibrary(std::string name) : Name(name) { }
615
616 std::shared_ptr<ImportedSymbol> GetImportByName(std::string name, uint8_t symbol_class = TVect)
617 {
618 auto key = std::make_tuple(name, symbol_class);
619 auto symbol_iter = named_imported_symbols.find(key);
620 if(symbol_iter == named_imported_symbols.end())
621 {
622 auto symbol = std::make_shared<ImportedSymbol>(name, symbol_class);
623 imported_symbols.push_back(symbol);
624 named_imported_symbols[key] = symbol;
625 return symbol;
626 }
627 else
628 {
629 return symbol_iter->second;
630 }
631 }
632 };
633 std::vector<std::shared_ptr<ImportedLibrary>> imported_libraries;
634 // only for CFM-68K
635 std::shared_ptr<MacintoshResourceFileFormat::JumpTableCodeResource> jump_table;
636 std::shared_ptr<Section> jump_table_section;
637 // only used for generation
638 std::map<std::string, std::shared_ptr<ImportedLibrary>> named_imported_libraries;
639 std::vector<std::shared_ptr<ImportedSymbol>> imported_symbols;
640 std::vector<uint32_t> reloc_section_indexes;
641 uint32_t reloc_instr_offset = 0;
642 uint32_t loader_strings_offset = 0;
643 uint32_t export_hash_offset = 0;
644 std::vector<RelocOpcode> relocs_area;
645 uint32_t relocs_area_size = 0;
646 std::vector<std::string> loader_string_table;
647 uint32_t loader_string_table_size = 0;
648
649 struct ExportedSymbol;
650
652 {
653 uint16_t chain_count = 0;
654 uint32_t first_index = 0;
655
656 // used only for generation
657 std::vector<std::shared_ptr<ExportedSymbol>> chain;
658 };
659 std::vector<HashTableEntry> hash_table;
660
661 struct ExportedSymbol : public Name, public Reference
662 {
663 uint16_t symbol_length = 0;
664 uint16_t hash_value = 0;
665 symbol_class_type symbol_class = Data;
666
667 ExportedSymbol() = default;
668
669 ExportedSymbol(std::string name)
670 : Name(name)
671 {
672 }
673
674 ExportedSymbol(std::string name, symbol_class_type symbol_class)
675 : Name(name), symbol_class(symbol_class)
676 {
677 }
678
679 using Name::LoadNameString;
680 std::string LoadNameString(const PEFFormat& pef_format, const std::shared_ptr<Linker::Reader>& rd);
681 };
682 std::vector<std::shared_ptr<ExportedSymbol>> exported_symbols;
683
684 static uint32_t ComputeHashWord(std::string name);
685 static uint32_t HashTableIndex(uint32_t hash_word, uint32_t export_hash_table_power);
686 static uint8_t ComputeHashTableExponent(uint32_t hash_table_size);
687
688 std::shared_ptr<ImportedLibrary> FetchImportLibrary(std::string name)
689 {
690 auto library_iter = named_imported_libraries.find(name);
691 if(library_iter == named_imported_libraries.end())
692 {
693 auto library = std::make_shared<ImportedLibrary>(name);
694 imported_libraries.push_back(library);
695 named_imported_libraries[name] = library;
696 return library;
697 }
698 else
699 {
700 return library_iter->second;
701 }
702 }
703
704 static constexpr uint32_t LoaderHeaderSize = 56;
705 static constexpr uint32_t LibraryDescriptionSize = 28;
706 uint32_t GetLibraryDescriptionsSize() const
707 {
708 return LibraryDescriptionSize * imported_libraries.size();
709 }
710 uint32_t GetSymbolTablesSize() const
711 {
712 uint32_t size = 0;
713 for(auto library : imported_libraries)
714 {
715 size += 4 * library->imported_symbols.size();
716 }
717 return size;
718 }
719 uint32_t GetRelocationHeadersSize() const
720 {
721 return 12 * reloc_section_indexes.size();
722 }
723 uint32_t GetRelocationAreaSize() const
724 {
725 return relocs_area_size;
726 }
727 uint32_t GetLoaderStringAreaSize() const
728 {
729 return loader_string_table_size;
730 }
731 uint32_t GetExportHashTableSize() const
732 {
733 return 4 * hash_table.size();
734 }
735 uint32_t GetExportKeyTableSize() const
736 {
737 return 4 * exported_symbols.size();
738 }
739 uint32_t GetExportSymbolTableSize() const
740 {
741 return 10 * exported_symbols.size();
742 }
743
744 uint32_t GetMinimumRelocInstrOffset() const
745 {
746 return LoaderHeaderSize
747 + GetLibraryDescriptionsSize()
748 + GetSymbolTablesSize()
749 + GetRelocationHeadersSize();
750 }
751
752 uint32_t GetLoaderSectionSize() const
753 {
754 return
755 std::max({LoaderHeaderSize
756 + GetLibraryDescriptionsSize()
757 + GetSymbolTablesSize()
758 + GetRelocationHeadersSize(),
759 reloc_instr_offset + GetRelocationAreaSize(),
760 loader_strings_offset + GetLoaderStringAreaSize(),
761 export_hash_offset
762 + GetExportHashTableSize()
763 + GetExportKeyTableSize()
764 + GetExportSymbolTableSize()});
765 }
766
767 // temporary structure to map linker segments to PEF sections
768 std::map<std::shared_ptr<Linker::Segment>, std::shared_ptr<Section>> segment_to_section_map;
769
770 uint32_t GetSectionNumber(std::shared_ptr<Section> section, uint32_t fallback)
771 {
772 size_t result = std::find(sections.begin(), sections.end(), section) - sections.begin();
773 if(result == sections.size())
774 return fallback;
775 else
776 return result;
777 }
778
779 bool FormatSupportsLibraries() const override;
780 bool FormatSupportsResources() const override;
781 bool FormatSupportsEntryTable() const override; // TODO: not yet implemented
782 bool FormatSupportsTransitionVectors() const override; // TODO: not yet implemented
783
784 void ReadLoaderSection(const std::shared_ptr<Linker::Reader>& rd);
785 void WriteLoaderSection(const std::shared_ptr<Linker::Writer>& wr) const;
786
787 private:
788 bool effect_handled = false;
789 public:
790 void ReparseResource(MacintoshResourceFileFormat& format, const std::shared_ptr<Linker::Reader>& rd, offset_t offset, offset_t length);
791
792 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
793 void CalculateValues() override;
794 offset_t ImageSize() const override;
796 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
797 void Dump(Dumper::Dumper& dump) const override;
798
800 {
801 public:
802 Linker::Option<bool> carbon{"carbon", "Generate Carbon binary"};
803
805 {
806 InitializeFields(carbon);
807 }
808 };
809
810 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
811 void SetOptions(std::map<std::string, std::string>& options) override;
812
813 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
814 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
815 void Link(Linker::Module& module);
816 void SortImports();
817 void ProcessRelocations(Linker::Module& module);
818 void ProcessModule(Linker::Module& module) override;
819 void GenerateFile(std::string filename, Linker::Module& module) override;
820
822 std::shared_ptr<MacintoshResourceFileFormat> resource_fork;
823 };
824
826 std::optional<
827 std::variant<
828 std::shared_ptr<MacintoshResourceFileFormat::CodeResource>,
829 std::shared_ptr<PEFFormat::Section>>>
830 FindSegment(std::shared_ptr<Linker::Segment> segment, MacintoshResourceFileFormat * resource_fork, PEFFormat * pef_container = nullptr);
831
833 bool CheckSimpleRelocation(const Linker::Relocation& rel);
835 void ProcessRelocations(Linker::Module& module, MacintoshResourceFileFormat * resource_fork, PEFFormat * pef_container = nullptr);
836
841 {
842 private:
843 bool effect_handled = false;
844 public:
845 std::shared_ptr<PEFHeaderBase> header;
846
847 PEFHeader(PEFHeaderBase::binary_type type = PEFHeaderBase::UnknownBinary, PEFHeaderBase::cpu_type architecture = PEFHeaderBase::PPC)
848 : header(std::make_shared<PEFHeaderBase>(type, architecture))
849 {
850 }
851
852 PEFHeader(std::shared_ptr<PEFHeaderBase> header)
853 : header(header)
854 {
855 }
856
857 void ReadFile(const std::shared_ptr<Linker::Reader>& rd);
858 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const;
859 void AddFields(Dumper::Region& header_region) const;
860
861 void ReparseResource(MacintoshResourceFileFormat& format, const std::shared_ptr<Linker::Reader>& rd, offset_t offset, offset_t length);
862 };
863
874 {
875 public:
877 std::variant<std::shared_ptr<PEFFormat>, std::shared_ptr<PEFHeader>> structured_data;
879 std::shared_ptr<MacintoshResourceFileFormat::Resource> raw_data;
880
881 RSegResource(std::shared_ptr<PEFHeader> structured_data, std::shared_ptr<MacintoshResourceFileFormat::Resource> raw_data = nullptr)
882 : Resource(
883 raw_data ? raw_data->type : "rseg",
884 raw_data ? raw_data->id : 0,
885 raw_data ? raw_data->name : std::optional<std::string>{},
886 raw_data ? raw_data->attributes : 0),
888 {
889 }
890
891 RSegResource(std::shared_ptr<PEFFormat> structured_data, std::shared_ptr<MacintoshResourceFileFormat::Resource> raw_data = nullptr)
892 : Resource(
893 raw_data ? raw_data->type : "rseg",
894 raw_data ? raw_data->id : 1,
895 raw_data ? raw_data->name : std::optional<std::string>{},
896 raw_data ? raw_data->attributes : 0),
898 {
899 }
900
901 void CalculateValues() override;
902
903 offset_t ImageSize() const override;
904
905 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
906 void ReadFile(const std::shared_ptr<Linker::Reader>& rd, offset_t length) override;
907
909 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
910 int GetDisplayOptions() const override;
912 void Dump(Dumper::Dumper& dump, offset_t file_offset) const override;
913 void AddFields(Dumper::Dumper& dump, Dumper::Region& region, offset_t file_offset) const override;
914 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length, unsigned display_width) const override;
915
916 void ReparseResource(MacintoshResourceFileFormat& format, const std::shared_ptr<Linker::Reader>& rd, offset_t offset, offset_t length);
917 void EffectFormat(MacintoshResourceFileFormat& format, const std::shared_ptr<Linker::Reader>& rd) override;
918 };
919
924 {
925 public:
926 // TODO: very preliminary
927
930 {
931 }
932
935 {
936 }
937
938 bool FormatSupportsLibraries() const override;
939 bool FormatSupportsResources() const override;
940 bool FormatSupportsEntryTable() const override; // TODO: not yet implemented
941 bool FormatSupportsTransitionVectors() const override; // TODO: not yet implemented
942
944 {
945 public:
947 std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member> member;
949 std::shared_ptr<PEFFormat> pef_format;
951 std::shared_ptr<PEFHeader> pef_header;
952
953 CodeFragment(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture)
954 : member(std::make_shared<MacintoshResourceFileFormat::CodeFragmentResource::Member>(architecture))
955 {
956 }
957
958 CodeFragment(std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member> member, std::shared_ptr<PEFFormat> pef_format = nullptr, std::shared_ptr<PEFHeader> pef_header = nullptr)
960 {
961 }
962
964 static CodeFragment CreateEmptyPEF();
965 protected:
967 static CodeFragment CreateWithHeader(std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member> member, std::shared_ptr<PEFFormat> pef_format);
968 public:
970 static CodeFragment CreateApplication(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture, std::string name);
972 static CodeFragment CreateLibrary(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture, std::string name, uint32_t current_version, uint32_t old_def_version);
973 };
974
976 {
977 public:
978 std::vector<CodeFragment> fragments;
979
980 offset_t ImageSize() const override;
981 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
982 offset_t WriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
983 void Dump(Dumper::Dumper& dump) const override;
984 };
985
986 private:
988 std::shared_ptr<DataFork> data_fork;
989 std::shared_ptr<FinderInfo> finder_info;
990
991 std::map<std::string, std::string> options;
992 std::string model;
993 std::string script_file;
994 std::map<std::string, std::string> script_options;
995
996 public:
997 // TODO: duplicated from Classic68K::DriverOptionCollector
998 // TODO: extend OutputDriver::DriverOptionCollector
1000 {
1001 public:
1002 class MacBinaryVersionEnumerator : public Linker::Enumeration<MacBinary::version_t>
1003 {
1004 public:
1006 : Enumeration(
1007 "1", MacBinary::MACBIN1,
1008 "GETINFO", MacBinary::MACBIN1_GETINFO,
1009 "2", MacBinary::MACBIN2,
1010 "3", MacBinary::MACBIN3)
1011 {
1012 descriptions = {
1013 { MacBinary::MACBIN1, "Revision 1 (1985)" },
1014 { MacBinary::MACBIN1_GETINFO, "Revision 1 (1985) with Get Info extension" },
1015 { MacBinary::MACBIN2, "MacBinary II, Revision 2 (1987)" },
1016 { MacBinary::MACBIN3, "MacBinary III, Revision 3 (1987)" },
1017 };
1018 }
1019 };
1020
1021 Linker::Option<std::optional<offset_t>> asver{"asver", "Version of the AppleSingle/AppleDouble container (recognized values: 1, 2)"};
1022 Linker::Option<std::optional<offset_t>> adver{"adver", "Version of the AppleSingle/AppleDouble container (recognized values: 1, 2)"};
1023 Linker::Option<std::optional<Linker::ItemOf<MacBinaryVersionEnumerator>>> mbinver{"mbinver", "Version of the MacBinary container"};
1024 Linker::Option<std::optional<Linker::ItemOf<MacBinaryVersionEnumerator>>> minmbinver{"minmbinver", "Minimum required version for the MacBinary container"};
1025
1026 DriverOptionCollector()
1027 : PEFOptionCollector()
1028 // TODO: if OutputDriver::DriverOptionCollector is created, call its too constructor
1029 {
1030 InitializeFields(asver, adver, mbinver, minmbinver);
1031 }
1032 };
1033
1034 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
1035 void SetOptions(std::map<std::string, std::string>& options) override;
1036
1037 std::vector<Linker::OptionDescription<void>> GetMemoryModelNames() override;
1038 void SetModel(std::string model) override;
1039
1040 void SetLinkScript(std::string script_file, std::map<std::string, std::string>& options) override;
1041
1042 void GenerateFile(std::string filename, Linker::Module& module) override;
1043
1044 void CalculateValues() override;
1045
1046 protected:
1047 void OnContainerCreated() override;
1048 void OnReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
1049 offset_t OnWriteFile(const std::shared_ptr<Linker::Writer>& wr) const override;
1050 void OnDump(Dumper::Dumper& dump) const override;
1051
1052 public:
1053 void ReadFile(const std::shared_ptr<Linker::Reader>& rd) override;
1054
1055 std::string GetDefaultExtension(Linker::Module& module) const override;
1056 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
1057 };
1058}
1059
1060#endif /* PEFEXE_H */
This is not actually a file format, but an interface to permit generating multiple binary outputs for...
Definition macos.h:968
target_format_t
Represents the file type of the main file.
Definition macos.h:972
@ TARGET_DATA_FORK
Main file is a data fork, typically empty.
Definition macos.h:976
A single resource in the resource file.
Definition macos.h:84
A Macintosh resource fork.
Definition macos.h:47
target_format_t target
Format of "filename".
Definition apple.h:746
produce_format_t produce
Bitset of other files to produce.
Definition apple.h:749
Definition pefexe.h:600
Definition pefexe.h:585
Represents a string stored in the loader section string table.
Definition pefexe.h:542
Pattern initialization data.
Definition pefexe.h:107
void ExpandData(Linker::Buffer &buffer) const
Expand the pattern into unpacked data and append it to the buffer.
Definition pefexe.cc:324
std::vector< uint8_t > common_data
Sequence of data to be used, possibly repeatedly.
Definition pefexe.h:124
static size_t GetValueSize(uint32_t value, size_t size_hint=0)
Determines the required number of bytes to store this value, with an optional minimum size.
Definition pefexe.cc:67
uint32_t count
Generic count parameter, used for repeating or zero filling data.
Definition pefexe.h:122
offset_t CodeSize() const
Size of the packed data, as stored in the file.
Definition pefexe.cc:221
void WriteFile(const std::shared_ptr< Linker::Writer > &wr) const
Writes the initialization pattern to a stream.
Definition pefexe.cc:152
opcode_type opcode
The pattern type.
Definition pefexe.h:120
static void WriteValue(const std::shared_ptr< Linker::Writer > &wr, uint32_t value, size_t size_hint=0)
Writes a variable length value, with an optional minimum size.
Definition pefexe.cc:78
std::vector< std::vector< uint8_t > > custom_data
Equal sized sequences of data to be inserted between repeated common data.
Definition pefexe.h:126
offset_t file_offset
Offset at which this pattern is stored in the file (only relevant for dumping)
Definition pefexe.h:118
offset_t DataSize() const
Size of the unpacked data, as loaded into memory.
Definition pefexe.cc:287
static uint32_t ReadValue(const std::shared_ptr< Linker::Reader > &rd)
Reads a variable length value as used by some patterns.
Definition pefexe.cc:55
void ReadFile(const std::shared_ptr< Linker::Reader > &rd)
Reads an initialization pattern and initializes this structure.
Definition pefexe.cc:101
Represents a single 16-bit or 32-bit opcode that encodes relocations.
Definition pefexe.h:311
uint32_t offset
Offset of opcode within file (only used for dumping)
Definition pefexe.h:339
void ReadFile(const std::shared_ptr< Linker::Reader > &rd)
Reads and initializes a single relocation opcode record.
Definition pefexe.cc:391
void GenerateRelocations(RelocationProcessor &processor) const
Executes the opcode to possibly produce some relocation information and/or alter the state of the pse...
Definition pefexe.cc:575
opcode_type opcode
Opcode type.
Definition pefexe.h:341
uint32_t value
A value parameter.
Definition pefexe.h:348
void WriteFile(const std::shared_ptr< Linker::Writer > &wr)
Outputs a single relocation opcode to the file.
Definition pefexe.h:381
offset_t CodeSize() const
Returns the number of bytes required to encode this opcode.
Definition pefexe.cc:542
uint32_t GetWord() const
Returns the bit sequence that this opcode is stored as in the file.
Definition pefexe.cc:502
uint32_t repeat
A repetition parameter.
Definition pefexe.h:359
A representation of a state machine that generates the actual relocations using the relocation data i...
Definition pefexe.h:218
void Regress(uint32_t block_count)
Step back this amount of 16-bit halfwords in the instruction stream.
Definition pefexe.cc:372
void Repeat(uint32_t block_count, uint32_t repeat_count)
Repeat a previous sequence of instructions.
Definition pefexe.h:285
Represents a single relocated 32-bit word in memory.
Definition pefexe.h:156
Definition pefexe.h:392
static compression_level DefaultCompressionLevel
Default compression level for data sections.
Definition pefexe.h:485
compression_level
Represents compression algorithm to be chosen.
Definition pefexe.h:478
@ Compression_None
Do not compress data sections.
Definition pefexe.h:480
@ Compression_Trivial
Embed data section inside a single BlockCopy command.
Definition pefexe.h:482
void CompressData()
Compress data section into PatternInitializedData section according to default level.
Definition pefexe.cc:739
PowerPC Classic Mac OS "PEF" file format.
Definition pefexe.h:78
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition pefexe.cc:1414
std::shared_ptr< Linker::OptionCollector > GetOptions() override
Returns object containing a sequence of option fields provided with the -S command line flag.
Definition pefexe.cc:2213
std::shared_ptr< MacintoshResourceFileFormat > resource_fork
If generated via the PEFOutputDriver, this will contain a reference to the resource fork.
Definition pefexe.h:822
void OnNewSegment(std::shared_ptr< Linker::Segment > segment) override
Callback function when allocating a new segment When the linker script runs, it creates segments cons...
Definition pefexe.cc:2229
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition pefexe.cc:1540
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition pefexe.cc:1813
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition pefexe.cc:2811
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition pefexe.cc:1808
bool FormatSupportsTransitionVectors() const override
Whether the format supports generating transition vectors.
Definition pefexe.cc:1058
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition pefexe.cc:2628
bool FormatSupportsEntryTable() const override
Whether the format supports a structure containing addresses of methods.
Definition pefexe.cc:1053
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition pefexe.cc:2218
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition pefexe.cc:1566
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition pefexe.cc:1043
bool FormatSupportsResources() const override
Whether the format supports resources.
Definition pefexe.cc:1048
Represents the common parts of a PEF container and the 'rseg'0 resource in a CFM-68K binary.
Definition pefexe.h:25
binary_type
Definition pefexe.h:49
@ ImportLibrary
A shared library.
Definition pefexe.h:53
@ UnflattenedLibrary
A shared library in an intermediate, unflattened format.
Definition pefexe.h:57
@ UnknownBinary
File type to generate not specified.
Definition pefexe.h:51
@ Application
An application.
Definition pefexe.h:55
binary_type type
Specifies the generated or parsed binary type.
Definition pefexe.h:60
Represents the contents of an 'rseg'0 resource in a CFM-68K binary, a cut-down version of the full PE...
Definition pefexe.h:841
std::shared_ptr< MacintoshResourceFileFormat::CodeFragmentResource::Member > member
Entry in the 'cfrg'0 resource for this fragment.
Definition pefexe.h:947
std::shared_ptr< PEFFormat > pef_format
The stored PEF container, stored in the resource fork in 'rsrg'1 if pef_header is non-null.
Definition pefexe.h:949
static CodeFragment CreateWithHeader(std::shared_ptr< MacintoshResourceFileFormat::CodeFragmentResource::Member > member, std::shared_ptr< PEFFormat > pef_format)
Initialize with header shared.
Definition pefexe.cc:3633
std::shared_ptr< PEFHeader > pef_header
For m68k only, the stored PEF header in 'rsrg'0.
Definition pefexe.h:951
static CodeFragment CreateApplication(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture, std::string name)
Initialize with default settings.
Definition pefexe.cc:3642
static CodeFragment CreateEmptyPEF()
Initialize with default settings.
Definition pefexe.cc:3625
static CodeFragment CreateLibrary(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture, std::string name, uint32_t current_version, uint32_t old_def_version)
Initialize with default settings.
Definition pefexe.cc:3660
Definition pefexe.h:976
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition pefexe.cc:3668
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition pefexe.cc:3713
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition pefexe.cc:3694
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition pefexe.cc:3700
Handles generation of a PEF binary and other files, such as a resource file.
Definition pefexe.h:924
bool FormatSupportsEntryTable() const override
Whether the format supports a structure containing addresses of methods.
Definition pefexe.cc:3731
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition pefexe.cc:3824
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition pefexe.cc:3932
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition pefexe.cc:3984
std::string GetDefaultExtension(Linker::Module &module) const override
Provides a default filename for the output file.
Definition pefexe.cc:3991
void OnReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Called if there is no container allocated.
Definition pefexe.cc:3961
bool FormatSupportsTransitionVectors() const override
Whether the format supports generating transition vectors.
Definition pefexe.cc:3736
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition pefexe.cc:3746
offset_t OnWriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Called if there is no container allocated.
Definition pefexe.cc:3974
void OnContainerCreated() override
Called after the container is created.
Definition pefexe.cc:3920
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition pefexe.cc:3721
void OnDump(Dumper::Dumper &dump) const override
Called if there is no container allocated.
Definition pefexe.cc:3979
void SetLinkScript(std::string script_file, std::map< std::string, std::string > &options) override
Selects a script file to use for linking.
Definition pefexe.cc:3829
std::shared_ptr< Linker::OptionCollector > GetOptions() override
Returns object containing a sequence of option fields provided with the -S command line flag.
Definition pefexe.cc:3741
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition pefexe.cc:3835
std::vector< Linker::OptionDescription< void > > GetMemoryModelNames() override
Returns a list of the supported memory models, used for documentation.
Definition pefexe.cc:3818
bool FormatSupportsResources() const override
Whether the format supports resources.
Definition pefexe.cc:3726
Represents an 'rseg' resource in a Macintosh resource file.
Definition pefexe.h:874
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition pefexe.cc:3507
void EffectFormat(MacintoshResourceFileFormat &format, const std::shared_ptr< Linker::Reader > &rd) override
Apply some changes to the format after parsing.
Definition pefexe.cc:3617
offset_t WriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Stores data in memory to file.
Definition pefexe.cc:3523
std::variant< std::shared_ptr< PEFFormat >, std::shared_ptr< PEFHeader > > structured_data
The parsed contents of the resource.
Definition pefexe.h:877
std::shared_ptr< MacintoshResourceFileFormat::Resource > raw_data
The contents of the resource, processed before recognizing it as an 'rseg' resource.
Definition pefexe.h:879
offset_t ImageSize() const override
Retrieves the offset of the byte after the last one belonging to this format from the first one.
Definition pefexe.cc:3482
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
A buffer that can be used to read and store data from a file.
Definition buffer.h:22
A representation of an enumeration with associated string representations for each value.
Definition options.h:15
std::map< value_type, std::string > descriptions
An empty dictionary that explains the value types in detail.
Definition options.h:20
virtual void Dump(Dumper::Dumper &dump) const
Display file contents in a nice manner.
Definition format.cc:11
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
Encodes an object module file as a collection of sections, symbols and relocations.
Definition module.h:24
Helper class that contains the options interpreted by the format.
Definition options.h:499
Documents and handles command line options.
Definition options.h:306
A class that provides a general interface to setting up generation for a format.
Definition format.h:69
Stores an absolute address along with the containing segment or address space.
Definition position.h:17
A representation of a value within some binary data that has to be fixed up once the exact position o...
Definition relocation.h:28
A helper class to collect sections into segments.
Definition segment_manager.h:32
Definition pefexe.h:662
Definition pefexe.h:652
Represents a reference to some data, stored as an offset into a section pair.
Definition pefexe.h:524