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"
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;
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;
63 : architecture(architecture),
type(
type)
69 void ReadBaseFields(
const std::shared_ptr<Linker::Reader>& rd);
70 void WriteBaseFields(
const std::shared_ptr<Linker::Writer>& wr)
const;
80 std::shared_ptr<PEFHeaderBase> header;
82 enum target_system_type
88 target_system_type system_type = MacOS;
91 : header(std::make_shared<PEFHeaderBase>(type, architecture))
96 : header(std::make_shared<PEFHeaderBase>(base))
100 uint32_t reserved = 0;
114 InterleaveRepeatBlockWithBlockCopy = 3,
115 InterleaveRepeatBlockWithZero = 4,
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);
136 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd);
138 void WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const;
165 bool compiled =
true;
169 std::weak_ptr<PEFFormat::Section> section;
171 std::weak_ptr<ImportedSymbol> symbol;
173 static inline Relocation ToSection(uint32_t section_number)
177 relocation.number = section_number;
181 static inline Relocation ToSection(std::weak_ptr<PEFFormat::Section> section)
185 relocation.compiled =
false;
186 relocation.section = section;
190 static inline Relocation ToSymbol(uint32_t symbol_number)
193 relocation.type = Symbol;
194 relocation.number = symbol_number;
198 static inline Relocation ToSymbol(std::weak_ptr<ImportedSymbol> symbol)
201 relocation.type = Symbol;
202 relocation.compiled =
false;
203 relocation.symbol = symbol;
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;
229 std::vector<RelocOpcode>& reloc_opcodes;
230 std::map<uint32_t, Relocation>& relocations;
235 : pef_format(pef_format), reloc_opcodes(reloc_opcodes), relocations(relocations)
240 void Advance(uint32_t offset)
242 reloc_address += offset;
247 relocations[reloc_address] = relocation;
251 void AddSection(uint32_t section_number)
253 AddRelocation(Relocation::ToSection(section_number));
258 AddSection(section_c);
263 AddSection(section_d);
268 AddRelocation(Relocation::ToSymbol(import_index));
273 void Regress(uint32_t block_count);
285 void Repeat(uint32_t block_count, uint32_t repeat_count)
288 if(current_repeat_count != 1)
295 if(current_repeat_count == 0)
298 current_repeat_count = repeat_count;
302 current_repeat_count --;
306 void GenerateRelocations();
318 BySectDWithSkip = 0x0000,
328 SmBySection = 0x6600,
329 IncrPosition = 0x8000,
331 SetPosition = 0xA000,
334 LgBySection = 0xB400,
372 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd);
381 void WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
388 void Dump(
Dumper::Dumper& dump,
const PEFFormat& pef_format, uint32_t opcode_index,
int display_options = 0)
const;
398 PatternInitializedData = 2,
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;
425 uint32_t section_number = uint32_t(-1);
427 std::shared_ptr<Linker::Contents> image;
428 std::vector<PatternInitialization> patterns;
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;
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)
441 alignment = ExpectedAlignment();
444 bool IsInstantiated()
const
450 case PatternInitializedData:
459 offset_t ExpectedAlignment()
const
468 case PatternInitializedData:
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);
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;
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;
507 static constexpr uint32_t ContainerHeaderSize = 40;
508 static constexpr uint32_t SectionHeaderSize = 28;
510 uint32_t GetSectionNameTableOffset()
const
512 return ContainerHeaderSize + SectionHeaderSize * sections.size();
516 uint32_t loader_section_offset = 0;
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);
525 std::weak_ptr<Section> section_pointer;
526 uint32_t section = NoSection;
531 bool IsPresent()
const {
return section != NoSection; }
532 void StoreSectionIndex()
534 auto actual_section = section_pointer.lock();
535 section = actual_section ? actual_section->section_number : NoSection;
538 Reference main_symbol, init_symbol, term_symbol;
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);
553 Name(std::string name)
561 enum symbol_class_type
569 static inline constexpr bool IsValidSymbolClass(
int value)
587 symbol_class_type symbol_class = TVect;
590 uint32_t symbol_number = uint32_t(-1);
594 ImportedSymbol(std::string name, uint8_t flags) :
Name(name), symbol_class(symbol_class_type(flags & 0x0F)), flags(flags & 0xF0) { }
596 std::weak_ptr<ImportedLibrary> library;
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;
608 std::map<std::tuple<std::string, uint8_t>, std::shared_ptr<ImportedSymbol>> named_imported_symbols;
610 uint8_t reserved_a = 0;
611 uint16_t reserved_b = 0;
616 std::shared_ptr<ImportedSymbol> GetImportByName(std::string name, uint8_t symbol_class = TVect)
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())
622 auto symbol = std::make_shared<ImportedSymbol>(name, symbol_class);
623 imported_symbols.push_back(symbol);
624 named_imported_symbols[key] = symbol;
629 return symbol_iter->second;
633 std::vector<std::shared_ptr<ImportedLibrary>> imported_libraries;
635 std::shared_ptr<MacintoshResourceFileFormat::JumpTableCodeResource> jump_table;
636 std::shared_ptr<Section> jump_table_section;
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;
653 uint16_t chain_count = 0;
654 uint32_t first_index = 0;
657 std::vector<std::shared_ptr<ExportedSymbol>> chain;
659 std::vector<HashTableEntry> hash_table;
663 uint16_t symbol_length = 0;
664 uint16_t hash_value = 0;
665 symbol_class_type symbol_class = Data;
675 :
Name(name), symbol_class(symbol_class)
679 using Name::LoadNameString;
680 std::string LoadNameString(
const PEFFormat& pef_format,
const std::shared_ptr<Linker::Reader>& rd);
682 std::vector<std::shared_ptr<ExportedSymbol>> exported_symbols;
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);
688 std::shared_ptr<ImportedLibrary> FetchImportLibrary(std::string name)
690 auto library_iter = named_imported_libraries.find(name);
691 if(library_iter == named_imported_libraries.end())
693 auto library = std::make_shared<ImportedLibrary>(name);
694 imported_libraries.push_back(library);
695 named_imported_libraries[name] = library;
700 return library_iter->second;
704 static constexpr uint32_t LoaderHeaderSize = 56;
705 static constexpr uint32_t LibraryDescriptionSize = 28;
706 uint32_t GetLibraryDescriptionsSize()
const
708 return LibraryDescriptionSize * imported_libraries.size();
710 uint32_t GetSymbolTablesSize()
const
713 for(
auto library : imported_libraries)
715 size += 4 * library->imported_symbols.size();
719 uint32_t GetRelocationHeadersSize()
const
721 return 12 * reloc_section_indexes.size();
723 uint32_t GetRelocationAreaSize()
const
725 return relocs_area_size;
727 uint32_t GetLoaderStringAreaSize()
const
729 return loader_string_table_size;
731 uint32_t GetExportHashTableSize()
const
733 return 4 * hash_table.size();
735 uint32_t GetExportKeyTableSize()
const
737 return 4 * exported_symbols.size();
739 uint32_t GetExportSymbolTableSize()
const
741 return 10 * exported_symbols.size();
744 uint32_t GetMinimumRelocInstrOffset()
const
746 return LoaderHeaderSize
747 + GetLibraryDescriptionsSize()
748 + GetSymbolTablesSize()
749 + GetRelocationHeadersSize();
752 uint32_t GetLoaderSectionSize()
const
755 std::max({LoaderHeaderSize
756 + GetLibraryDescriptionsSize()
757 + GetSymbolTablesSize()
758 + GetRelocationHeadersSize(),
759 reloc_instr_offset + GetRelocationAreaSize(),
760 loader_strings_offset + GetLoaderStringAreaSize(),
762 + GetExportHashTableSize()
763 + GetExportKeyTableSize()
764 + GetExportSymbolTableSize()});
768 std::map<std::shared_ptr<Linker::Segment>, std::shared_ptr<Section>> segment_to_section_map;
770 uint32_t GetSectionNumber(std::shared_ptr<Section> section, uint32_t fallback)
772 size_t result = std::find(sections.begin(), sections.end(), section) - sections.begin();
773 if(result == sections.size())
784 void ReadLoaderSection(
const std::shared_ptr<Linker::Reader>& rd);
785 void WriteLoaderSection(
const std::shared_ptr<Linker::Writer>& wr)
const;
788 bool effect_handled =
false;
790 void ReparseResource(MacintoshResourceFileFormat& format,
const std::shared_ptr<Linker::Reader>& rd, offset_t offset, offset_t length);
792 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
796 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
806 InitializeFields(carbon);
810 std::shared_ptr<Linker::OptionCollector>
GetOptions()
override;
811 void SetOptions(std::map<std::string, std::string>& options)
override;
813 void OnNewSegment(std::shared_ptr<Linker::Segment> segment)
override;
828 std::shared_ptr<MacintoshResourceFileFormat::CodeResource>,
829 std::shared_ptr<PEFFormat::Section>>>
843 bool effect_handled =
false;
845 std::shared_ptr<PEFHeaderBase> header;
848 : header(std::make_shared<PEFHeaderBase>(type, architecture))
852 PEFHeader(std::shared_ptr<PEFHeaderBase> header)
857 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd);
858 offset_t WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const;
861 void ReparseResource(
MacintoshResourceFileFormat& format,
const std::shared_ptr<Linker::Reader>& rd, offset_t offset, offset_t length);
879 std::shared_ptr<MacintoshResourceFileFormat::Resource>
raw_data;
891 RSegResource(std::shared_ptr<PEFFormat>
structured_data, std::shared_ptr<MacintoshResourceFileFormat::Resource>
raw_data =
nullptr)
901 void CalculateValues()
override;
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;
909 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
910 int GetDisplayOptions()
const override;
914 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length,
unsigned display_width)
const override;
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;
947 std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member>
member;
953 CodeFragment(MacintoshResourceFileFormat::CodeFragmentResource::Member::architecture_type architecture)
958 CodeFragment(std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member>
member, std::shared_ptr<PEFFormat>
pef_format =
nullptr, std::shared_ptr<PEFHeader>
pef_header =
nullptr)
967 static CodeFragment
CreateWithHeader(std::shared_ptr<MacintoshResourceFileFormat::CodeFragmentResource::Member>
member, std::shared_ptr<PEFFormat>
pef_format);
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);
978 std::vector<CodeFragment> fragments;
981 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
982 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
988 std::shared_ptr<DataFork> data_fork;
989 std::shared_ptr<FinderInfo> finder_info;
991 std::map<std::string, std::string> options;
993 std::string script_file;
994 std::map<std::string, std::string> script_options;
1007 "1", MacBinary::MACBIN1,
1008 "GETINFO", MacBinary::MACBIN1_GETINFO,
1009 "2", MacBinary::MACBIN2,
1010 "3", MacBinary::MACBIN3)
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)" },
1026 DriverOptionCollector()
1027 : PEFOptionCollector()
1030 InitializeFields(asver, adver, mbinver, minmbinver);
1034 std::shared_ptr<Linker::OptionCollector>
GetOptions()
override;
1035 void SetOptions(std::map<std::string, std::string>& options)
override;
1038 void SetModel(std::string model)
override;
1040 void SetLinkScript(std::string script_file, std::map<std::string, std::string>& options)
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;
1053 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
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
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
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
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
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
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