10#include "../dumper/dumper.h"
11#include "../linker/module.h"
12#include "../linker/options.h"
13#include "../linker/segment.h"
14#include "../linker/segment_manager.h"
15#include "../linker/writer.h"
16#include "../runtime/resource.h"
22 typedef char OSType[4];
24 static constexpr uint32_t OSTypeToUInt32(
char type0,
char type1,
char type2,
char type3)
27 (uint32_t(uint8_t(type0)) << 24)
28 | (uint32_t(uint8_t(type1)) << 16)
29 | (uint32_t(uint8_t(type2)) << 8)
30 | uint32_t(uint8_t(type3));
33 uint32_t OSTypeToUInt32(
const OSType& type);
34 void UInt32ToOSType(OSType& type, uint32_t value);
69 InitializeFields(_32, far);
73 std::shared_ptr<Linker::OptionCollector>
GetOptions()
override;
74 void SetOptions(std::map<std::string, std::string>& options)
override;
76 static std::vector<Linker::OptionDescription<void>> MemoryModelNames;
78 void SetModel(std::string model)
override;
87 virtual void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length) = 0;
89 virtual int GetDisplayOptions()
const;
92 virtual std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length,
unsigned display_width)
const;
97 Resource(
const char type[4], uint16_t
id, uint8_t attributes = 0)
98 : id(
id), attributes(attributes)
100 memcpy(this->type, type, 4);
103 Resource(
const char type[4], uint16_t
id, std::optional<std::string> name, uint8_t attributes = 0)
104 : id(
id), name(name), attributes(attributes)
106 memcpy(this->type, type, 4);
113 std::optional<std::string> name;
118 virtual void CalculateValues() = 0;
133 std::shared_ptr<Linker::Contents>
image;
135 void CalculateValues()
override;
139 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
140 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length)
override;
143 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
145 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length,
unsigned display_width)
const override;
162 uint16_t segment = 0;
163 uint32_t section = 0;
166 bool IsSegmented()
const
171 bool IsSectioned()
const
176 bool IsAbsolute()
const
193 bool operator ==(
const Location& other)
const
195 if(type != other.type)
200 return offset == other.offset && segment == other.segment;
202 return offset == other.offset && section == other.section;
204 return offset == other.offset;
210 bool operator <(
const Location& other)
const
213 if(type < other.type)
215 else if(type > other.type)
221 return segment < other.segment || (segment == other.segment && offset < other.offset);
223 return section < other.section || (section == other.section && offset < other.offset);
225 return offset < other.offset;
248 std::optional<uint32_t> seg_loader_section;
249 uint32_t seg_loader_offset;
250 std::optional<uint32_t> a5_section;
253 std::optional<uint32_t> section;
257 uint32_t above_a5 = 0;
258 uint32_t below_a5 = 0;
259 uint32_t jump_table_size = 0;
260 uint32_t jump_table_offset = 32;
265 std::vector<TransitionVector> transition_vectors;
272 assert(entry.IsSegmented());
283 assert(entry.IsSegmented());
294 assert(entry.IsSectioned());
305 assert(seg_loader.IsSectioned());
306 assert(a5_world.IsSectioned());
307 assert(entry.IsSegmented());
308 transition_vectors.push_back(
TransitionVector{seg_loader.section, seg_loader.offset, a5_world.section, a5_world.offset, entry.segment, {}, entry.offset});
318 assert(a5_world.IsSectioned());
319 assert(entry.IsSegmented());
320 transition_vectors.push_back(
TransitionVector{{}, 0, a5_world.section, a5_world.offset, entry.segment, {}, entry.offset});
330 assert(a5_world.IsSectioned());
331 assert(entry.IsSectioned());
332 transition_vectors.push_back(
TransitionVector{{}, 0, a5_world.section, a5_world.offset, 0, entry.section, entry.offset});
340 std::shared_ptr<JumpTable> jump_table;
343 :
Resource(
"CODE", 0), jump_table(jump_table)
375 bool IsResource()
const
377 switch(jump_table_format)
388 void CalculateValues()
override;
390 offset_t JumpTableSize()
const;
396 MOVE_DATA_SP = 0x3F3C,
400 FAR_VERSION_MARK = 0xFFFF,
401 CFM_68K_VERSION_MARK = 0xFFFD,
404 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
405 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length)
override;
434 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
436 int GetDisplayOptions()
const override;
439 std::unique_ptr<Dumper::Region> CreateRegion(std::string name, offset_t offset, offset_t length,
unsigned display_width)
const override;
446 static constexpr uint32_t OSType = OSTypeToUInt32(
'C',
'O',
'D',
'E');
448 static constexpr uint32_t NearSegmentHeaderSize = 0x4;
449 static constexpr uint32_t FarSegmentHeaderSize = 0x28;
451 std::shared_ptr<JumpTableCodeResource> jump_table;
452 std::shared_ptr<Linker::Contents> image;
453 uint32_t zero_fill = 0;
455 CodeResource(uint16_t
id, std::shared_ptr<JumpTableCodeResource> jump_table =
nullptr)
456 :
Resource(
"CODE",
id), jump_table(jump_table)
470 uint32_t a5_address = 0;
471 uint32_t base_address = 0;
474 std::set<uint32_t> near_entries;
475 uint16_t near_entry_count = 0;
476 std::set<uint32_t> far_entries;
477 uint16_t far_entry_count = 0;
478 std::set<uint32_t> a5_relocations;
479 std::set<uint32_t> segment_relocations;
488 return offset == other.offset && a5_world == other.a5_world;
495 return offset < other.offset || (offset == other.offset && a5_world < other.a5_world);
498 std::set<TransitionVector> transition_vectors;
499 uint32_t transition_vector_count = 0;
501 std::map<uint32_t, std::vector<Linker::Relocation>> entry_relocations;
502 std::map<TransitionVector, std::vector<Linker::Relocation>> tvector_relocations;
505 uint32_t first_near_entry_offset;
506 uint32_t first_far_entry_offset;
507 uint32_t first_transition_vector_offset;
508 uint32_t a5_relocation_offset;
509 uint32_t segment_relocation_offset;
510 uint32_t resource_size;
520 std::shared_ptr<JumpTableCodeResource> jump_table,
521 uint32_t& jump_table_offset,
522 std::optional<uint32_t> starting_entry = {});
532 std::shared_ptr<JumpTableCodeResource> jump_table,
533 uint32_t& jump_table_offset,
534 std::optional<uint32_t> starting_entry = {});
543 std::shared_ptr<JumpTableCodeResource> jump_table,
544 uint32_t& jump_table_offset);
555 std::shared_ptr<JumpTableCodeResource> jump_table,
556 uint32_t& jump_table_offset,
558 std::optional<TransitionVector> starting_tvector = {});
560 void CalculateValues()
override;
564 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
565 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length)
override;
567 uint32_t MeasureRelocations(std::set<uint32_t>& relocations)
const;
569 void ReadRelocations(
const std::shared_ptr<Linker::Reader>& rd, std::set<uint32_t>& relocations)
const;
570 void WriteRelocations(
const std::shared_ptr<Linker::Writer>& wr,
const std::set<uint32_t>& relocations)
const;
573 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
575 int GetDisplayOptions()
const override;
584 static constexpr uint32_t OSType = OSTypeToUInt32(
'S',
'I',
'Z',
'E');
585 static constexpr uint32_t ExpectedLength = 10;
597 static constexpr uint16_t AcceptSuspendResumeEvents = 0x4000;
600 static constexpr uint16_t CanBackground = 0x1000;
601 static constexpr uint16_t MultiFinderAware = 0x0800;
602 static constexpr uint16_t OnlyBackground = 0x0400;
603 static constexpr uint16_t GetFrontClicks = 0x0200;
604 static constexpr uint16_t AcceptChildDiedEvents = 0x0100;
605 static constexpr uint16_t Is32BitCompatible = 0x0080;
606 static constexpr uint16_t IsHighLevelEventAware = 0x0040;
607 static constexpr uint16_t LocalAndRemoteHLEvents = 0x0020;
608 static constexpr uint16_t IsStationaryAware = 0x0010;
609 static constexpr uint16_t UseTextEditServices = 0x0008;
610 static constexpr uint16_t DisplayManagerAware = 0x0004;
613 uint32_t preferred_memory = 0;
614 uint32_t minimum_memory = 0;
616 static constexpr uint16_t GetDefaultFlags(target_type target)
624 return Is32BitCompatible;
627 return AcceptSuspendResumeEvents | MultiFinderAware | GetFrontClicks | Is32BitCompatible;
630 return AcceptSuspendResumeEvents | CanBackground | MultiFinderAware | IsHighLevelEventAware;
634 static constexpr uint32_t GetDefaultMemory(target_type target)
652 : Resource(
"SIZE", 0xFFFF)
656 SizeResource(target_type target)
657 : Resource(
"SIZE", 0xFFFF),
658 flags(GetDefaultFlags(target)),
659 preferred_memory(GetDefaultMemory(target)),
660 minimum_memory(GetDefaultMemory(target))
664 void CalculateValues()
override;
668 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
669 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length)
override;
672 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
673 int GetDisplayOptions()
const override;
684 static constexpr uint32_t OSType = OSTypeToUInt32(
'c',
'f',
'r',
'g');
689 enum architecture_type : uint32_t
691 PowerPC = OSTypeToUInt32(
'p',
'w',
'p',
'c'),
692 Motorola68K = OSTypeToUInt32(
'm',
'6',
'8',
'k'),
695 architecture_type architecture;
696 enum update_level_type : uint8_t
701 update_level_type update_level = FullLib;
702 uint32_t current_version = 0;
703 uint32_t old_def_version = 0;
704 static constexpr uint32_t DefaultStackSize = 0;
705 uint32_t app_stack_size = 0;
706 static constexpr int16_t NoAppSubFolder = 0;
707 int16_t app_subdir_id = 0;
708 enum usage_type : uint8_t
717 enum where_type : uint8_t
726 where_type where = DataFork;
727 static constexpr uint32_t RSEG = OSTypeToUInt32(
'r',
's',
'e',
'g');
729 static constexpr uint32_t CFragGoesToEOF = 0;
731 uint32_t space_id = 0;
732 uint16_t extension_count = 0;
733 uint16_t member_size = 0x38;
736 Member(architecture_type architecture)
737 : architecture(architecture)
741 offset_t ImageSize()
const;
742 static std::shared_ptr<Member> ReadFile(
const std::shared_ptr<Linker::Reader>& rd);
743 offset_t WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const;
745 static std::shared_ptr<Member> CreateEmpty()
747 return std::make_shared<Member>(architecture_type(0));
751 static std::shared_ptr<Member>
CreateApplication(architecture_type architecture, std::string name)
753 std::shared_ptr<Member> member = std::make_shared<Member>(architecture);
754 member->update_level = FullLib;
755 member->current_version = 0;
756 member->old_def_version = 0;
757 member->app_stack_size = DefaultStackSize;
758 member->app_subdir_id = NoAppSubFolder;
759 member->usage = Application;
760 if(architecture == Motorola68K)
763 member->offset = RSEG;
768 member->where = DataFork;
770 member->length = CFragGoesToEOF;
773 if(member->name.size() > 15)
775 member->name = member->name.substr(0, 15);
781 static std::shared_ptr<Member>
CreateLibrary(architecture_type architecture, std::string name, uint32_t current_version, uint32_t old_def_version)
783 std::shared_ptr<Member> member = std::make_shared<Member>(architecture);
784 member->update_level = FullLib;
785 member->current_version = current_version;
786 member->old_def_version = old_def_version;
787 member->app_stack_size = DefaultStackSize;
788 member->app_subdir_id = NoAppSubFolder;
789 member->usage = ImportLibrary;
790 member->where = DataFork;
792 member->length = CFragGoesToEOF;
794 if(member->name.size() > 15)
796 member->name = member->name.substr(0, 15);
802 uint16_t version = 1;
803 std::vector<std::shared_ptr<Member>> members;
810 void CalculateValues()
override;
814 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
815 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd, offset_t length)
override;
818 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
819 int GetDisplayOptions()
const override;
828 MacintoshResourceFileFormat()
836 uint16_t name_offset = 0xFFFF;
837 std::optional<std::string> name;
838 uint8_t attributes = 0;
839 uint32_t data_offset = 0;
840 std::shared_ptr<Resource> data;
845 OSType type { 0, 0, 0, 0 };
848 std::vector<ResourceReference> references;
851 static std::shared_ptr<Resource> ReadResource(
const std::shared_ptr<Linker::Reader>& rd,
const ResourceType& type,
const ResourceReference& reference);
853 uint16_t attributes = 0;
855 bool use_far_segments =
false;
862 std::map<uint32_t, std::map<uint16_t, std::shared_ptr<Resource>>>
resources;
865 uint32_t data_offset = 0, data_length = 0, map_offset = 0, map_length = 0;
866 uint16_t resource_type_list_offset = 28;
867 uint16_t name_list_offset = 0;
870 std::shared_ptr<JumpTableCodeResource> jump_table;
871 std::vector<std::shared_ptr<CodeResource>> codes;
872 std::map<std::shared_ptr<Linker::Segment>, std::shared_ptr<CodeResource>> segment_to_resource_map;
873 std::shared_ptr<Linker::Segment> a5world;
874 std::shared_ptr<SizeResource> size_resource =
nullptr;
876 void AddResource(std::shared_ptr<Resource> resource);
877 std::shared_ptr<Resource> FindResource(
const OSType& type, uint16_t
id);
880 void OnNewSegment(std::shared_ptr<Linker::Segment> segment)
override;
894 void BuildNearModelJumpTable(std::shared_ptr<CodeResource> entry_segment, uint32_t entry_offset);
895 void BuildFarModelJumpTable(std::shared_ptr<CodeResource> init_segment, uint32_t init_offset, std::shared_ptr<CodeResource> entry_segment, uint32_t entry_offset);
896 void BuildCFM68KJumpTable(std::shared_ptr<CodeResource> init_segment, uint32_t init_offset, std::shared_ptr<CodeResource> entry_segment, uint32_t entry_offset, std::optional<uint32_t> seg_loader_section, uint32_t seg_loader_offset, std::optional<uint32_t> a5_section, uint32_t a5_offset);
904 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
907 offset_t
WriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
925 : resource_type(resource_type), resource_reference(resource_reference)
935 std::vector<ResourceType>& resource_types;
936 mutable std::vector<ResourceType>::iterator resource_types_iterator;
937 mutable std::vector<ResourceReference>::iterator resource_references_iterator;
940 std::vector<ResourceType>& resource_types,
941 std::vector<ResourceType>::iterator resource_types_iterator,
942 std::vector<ResourceReference>::iterator resource_references_iterator)
943 : resource_types(resource_types), resource_types_iterator(resource_types_iterator), resource_references_iterator(resource_references_iterator)
947 void Step()
const override;
948 std::shared_ptr<const Runtime::Resource> Get()
const override;
950 void Erase()
override;
954 std::shared_ptr<Runtime::ResourceIterator> BeginIteration()
override;
955 std::shared_ptr<Runtime::ResourceIterator> EndOfIteration()
override;
956 std::shared_ptr<Runtime::ResourceIterator> FindResource(
const Runtime::Value& value)
override;
957 bool UpdateResource(std::shared_ptr<Runtime::Resource> resource)
override;
1050 std::shared_ptr<FinderInfo> finder_info;
1052 std::map<std::string, std::string> options;
1054 std::string script_file;
1055 std::map<std::string, std::string> script_options;
1067 "1", MacBinary::MACBIN1,
1068 "GETINFO", MacBinary::MACBIN1_GETINFO,
1069 "2", MacBinary::MACBIN2,
1070 "3", MacBinary::MACBIN3)
1073 { MacBinary::MACBIN1,
"Revision 1 (1985)" },
1074 { MacBinary::MACBIN1_GETINFO,
"Revision 1 (1985) with Get Info extension" },
1075 { MacBinary::MACBIN2,
"MacBinary II, Revision 2 (1987)" },
1076 { MacBinary::MACBIN3,
"MacBinary III, Revision 3 (1987)" },
1086 DriverOptionCollector()
1087 : MacintoshOptionCollector()
1090 InitializeFields(asver, adver, mbinver, minmbinver);
1094 std::shared_ptr<Linker::OptionCollector>
GetOptions()
override;
1095 void SetOptions(std::map<std::string, std::string>& options)
override;
1098 void SetModel(std::string model)
override;
1100 void SetLinkScript(std::string script_file, std::map<std::string, std::string>& options)
override;
1107 void OnReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
1108 offset_t
OnWriteFile(
const std::shared_ptr<Linker::Writer>& wr)
const override;
1112 void ReadFile(
const std::shared_ptr<Linker::Reader>& rd)
override;
Interface to generate files required for the Classic 68K Mac OS runtime.
Definition macos.h:1034
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition macos.cc:2593
void ReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Loads file into memory.
Definition macos.cc:2651
std::shared_ptr< Linker::OptionCollector > GetOptions() override
Returns object containing a sequence of option fields provided with the -S command line flag.
Definition macos.cc:2499
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition macos.cc:2622
void OnContainerCreated() override
Called after the container is created.
Definition macos.cc:2610
void SetLinkScript(std::string script_file, std::map< std::string, std::string > &options) override
Selects a script file to use for linking.
Definition macos.cc:2587
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition macos.cc:2582
bool FormatSupportsEntryTable() const override
Whether the format supports a structure containing addresses of methods.
Definition macos.cc:2494
bool FormatSupportsResources() const override
Whether the format supports resources.
Definition macos.cc:2489
void OnDump(Dumper::Dumper &dump) const override
Called if there is no container allocated.
Definition macos.cc:2646
offset_t OnWriteFile(const std::shared_ptr< Linker::Writer > &wr) const override
Called if there is no container allocated.
Definition macos.cc:2641
std::string GetDefaultExtension(Linker::Module &module) const override
Provides a default filename for the output file.
Definition macos.cc:2661
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition macos.cc:2504
std::vector< Linker::OptionDescription< void > > GetMemoryModelNames() override
Returns a list of the supported memory models, used for documentation.
Definition macos.cc:2576
void OnReadFile(const std::shared_ptr< Linker::Reader > &rd) override
Called if there is no container allocated.
Definition macos.cc:2627
This is not actually a file format, but an interface to permit generating multiple binary outputs for...
Definition macos.h:968
std::shared_ptr< MacintoshResourceFileFormat > resource_fork
Definition macos.h:1021
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_NONE
Do not generate main file.
Definition macos.h:974
@ TARGET_MAC_BINARY
Main file as a MacBinary.
Definition macos.h:984
@ TARGET_APPLE_SINGLE
Main file is an AppleSingle.
Definition macos.h:980
@ TARGET_APPLE_DOUBLE
Main file is an AppleDouble.
Definition macos.h:982
@ TARGET_RESOURCE_FORK
Main file is a resource fork.
Definition macos.h:978
produce_format_t
Represents what additional files should be generated.
Definition macos.h:989
@ PRODUCE_MAC_BINARY
Creates a MacBinary with the .mbin extension.
Definition macos.h:997
@ PRODUCE_FINDER_INFO
Places a Finder Information file under the directory .finf.
Definition macos.h:993
@ PRODUCE_APPLE_DOUBLE
Creates an AppleDouble binary with the '' prefix.
Definition macos.h:995
@ PRODUCE_RESOURCE_FORK
Places a Macintosh format resource file under the directory .rsrc.
Definition macos.h:991
void GenerateFiles(std::string filename, std::shared_ptr< Contents > data_fork, std::shared_ptr< Contents > resource_fork)
Tasked to create all the requested files.
Definition macos.cc:2482
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_FINDER_INFO
Places a Finder Information file under the directory .finf (Macintosh only)
Definition apple.h:735
@ PRODUCE_MAC_BINARY
Creates a MacBinary with the .mbin extension (Macintosh only)
Definition apple.h:739
@ 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
@ TARGET_MAC_BINARY
Main file as a MacBinary (Macintosh only)
Definition apple.h:725
produce_format_t produce
Bitset of other files to produce.
Definition apple.h:749
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 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
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 resource.h:108
A YAML/JSON-like data format.
Definition value.h:16
Describes a single jump table entry.
Definition macos.h:238
std::optional< uint32_t > section
Section number: only in PEF flattened shared libraries.
Definition macos.h:242