RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
coff.h
1#ifndef COFF_H
2#define COFF_H
3
4#include <map>
5#include "cpm68k.h"
6#include "mzexe.h"
7#include "../common.h"
8#include "../linker/linker.h"
9#include "../linker/module.h"
10#include "../linker/segment.h"
11#include "../linker/writer.h"
12
13namespace COFF
14{
26 {
27 /* * * General members * * */
28 public:
32 enum cpu
33 {
34 CPU_UNKNOWN = 0,
35 // main supported types
36 CPU_I386 = 0x014C,
37 CPU_M68K = 0x0150,
38 // GNU binutils output
39 CPU_W65 = 0x6500,
40 CPU_Z80 = 0x805A,
41 CPU_Z8K = 0x8000,
42 // other CPU types, included for completeness sake
43 CPU_I86 = 0x0148,
44 CPU_NS32K = 0x0154,
45 CPU_I370 = 0x0158, // IBM 370
46 CPU_MIPS = 0x0160,
47 CPU_M88K = 0x016D,
48 CPU_WE32K = 0x0170,
49 CPU_VAX = 0x0178,
50 CPU_AM29K = 0x017A,
51 CPU_ALPHA = 0x0183,
52 CPU_PPC = 0x01DF,
53 CPU_PPC64 = 0x01F7,
54 CPU_SHARC = 0x521C,
55 // overloaded values
56 // for now, none
57 };
58
60 {
61 cpu actual_cpu;
62 ::EndianType endian;
63 };
64
65 static const std::map<uint32_t, MachineType> MACHINE_TYPES;
66
68 char signature[2] = { };
69
73 ::EndianType GetEndianType() const;
74
79 {
80 public:
81 virtual ~Relocation();
82 virtual offset_t GetAddress() = 0;
83 virtual size_t GetSize() = 0;
84 virtual void FillEntry(Dumper::Entry& entry) = 0;
85 };
86
91 {
92 public:
93 // https://github.com/aixoss/binutils/blob/master/include/coff/internal.h
94 // https://github.com/aixoss/binutils/blob/master/include/coff/z80.h
95 // https://github.com/aixoss/binutils/blob/master/include/coff/z8k.h
96
97 static const uint16_t R_Z80_IMM8 = 0x22;
98 static const uint16_t R_Z80_IMM16 = 0x01;
99 static const uint16_t R_Z80_IMM24 = 0x33;
100 static const uint16_t R_Z80_IMM32 = 0x17;
101 static const uint16_t R_Z80_OFF8 = 0x32;
102 static const uint16_t R_Z80_JR = 0x02;
103
104 static const uint16_t R_Z8K_IMM4L = 0x23;
105 static const uint16_t R_Z8K_IMM4H = 0x24;
106 static const uint16_t R_Z8K_DISP7 = 0x25; /* djnz */
107 static const uint16_t R_Z8K_IMM8 = 0x22;
108 static const uint16_t R_Z8K_IMM16 = 0x01;
109 static const uint16_t R_Z8K_REL16 = 0x04;
110 static const uint16_t R_Z8K_IMM32 = 0x11;
111 static const uint16_t R_Z8K_JR = 0x02; /* jr */
112 static const uint16_t R_Z8K_CALLR = 0x05; /* callr */
113
114 static const uint16_t R_W65_ABS8 = 0x01;
115 static const uint16_t R_W65_ABS16 = 0x02;
116 static const uint16_t R_W65_ABS24 = 0x03;
117 static const uint16_t R_W65_ABS8S8 = 0x04;
118 static const uint16_t R_W65_ABS8S16 = 0x05;
119 static const uint16_t R_W65_ABS16S8 = 0x06;
120 static const uint16_t R_W65_ABS16S16 = 0x07;
121 static const uint16_t R_W65_PCR8 = 0x08;
122 static const uint16_t R_W65_PCR16 = 0x09;
123 static const uint16_t R_W65_DP = 0x0A;
124
125 cpu cpu_type;
126
130 uint32_t address;
134 uint32_t symbol_index;
138 uint32_t offset;
142 uint16_t type;
146 uint16_t data;
147
148 ZilogRelocation(cpu cpu_type)
149 : cpu_type(cpu_type)
150 {
151 }
152
153 void Read(Linker::Reader& in);
154
155 offset_t GetAddress() override;
156
157 size_t GetSize() override;
158
159 void FillEntry(Dumper::Entry& entry) override;
160 };
161
165 class Symbol
166 {
167 public:
171 std::string name;
175 uint32_t name_index;
179 uint32_t value;
187 uint16_t type;
198
199 void Read(Linker::Reader& rd);
200
201 bool IsExternal() const;
202 };
203
208 {
209 public:
213 std::string name;
217 uint32_t physical_address = 0;
221 uint32_t address = 0;
225 uint32_t size = 0;
229 uint32_t section_pointer = 0;
233 uint32_t relocation_pointer = 0;
241 uint16_t relocation_count = 0;
245 uint16_t line_number_count = 0;
249 uint32_t flags = 0;
250
254 std::shared_ptr<Linker::Writable> image;
255
259 std::vector<std::unique_ptr<Relocation>> relocations;
260
262 enum
263 {
265 TEXT = 0x0020,
267 DATA = 0x0040,
269 BSS = 0x0080,
270 };
271
272 void Clear();
273
274 Section(uint32_t flags = 0, std::shared_ptr<Linker::Writable> image = nullptr)
276 {
277 }
278
279 ~Section()
280 {
281 Clear();
282 }
283
284 void ReadSectionHeader(Linker::Reader& rd);
285
286 void WriteSectionHeader(Linker::Writer& wr);
287
288 uint32_t ActualDataSize();
289 };
290
294 std::vector<std::unique_ptr<Section>> sections;
295
299 uint16_t section_count = 0;
303 uint32_t timestamp = 0;
311 uint32_t symbol_count = 0;
315 std::vector<std::unique_ptr<Symbol>> symbols;
323 uint16_t flags = 0;
324
329 {
330 public:
331 virtual ~OptionalHeader();
335 virtual uint32_t GetSize() = 0;
336 virtual void ReadFile(Linker::Reader& rd) = 0;
337 virtual void WriteFile(Linker::Writer& wr) = 0;
341 virtual void PostReadFile(COFFFormat& coff, Linker::Reader& rd);
345 virtual void PostWriteFile(COFFFormat& coff, Linker::Writer& wr);
346
347 virtual void Dump(COFFFormat& coff, Dumper::Dumper& dump);
348 };
349
353 std::unique_ptr<OptionalHeader> optional_header = nullptr;
354
358 std::map<uint32_t, size_t> relocations; /* CDOS68K */
359
364 {
365 public:
366 std::unique_ptr<Linker::Buffer> buffer = nullptr;
367
368 UnknownOptionalHeader(offset_t size)
369 : buffer(std::make_unique<Linker::Buffer>(size))
370 {
371 }
372
373 uint32_t GetSize() override;
374
375 void ReadFile(Linker::Reader& rd) override;
376
377 void WriteFile(Linker::Writer& wr) override;
378
379 void Dump(COFFFormat& coff, Dumper::Dumper& dump) override;
380 };
381
386 {
387 public:
391 uint16_t magic = 0;
395 uint16_t version_stamp = 0;
396
400 uint32_t code_size = 0;
404 uint32_t data_size = 0;
408 uint32_t bss_size = 0;
412 uint32_t entry_address = 0;
416 uint32_t code_address = 0;
420 uint32_t data_address = 0;
421
422 AOutHeader(uint16_t magic = 0)
423 : magic(magic)
424 {
425 }
426
427 uint32_t GetSize() override;
428
429 void ReadFile(Linker::Reader& rd) override;
430
431 void WriteFile(Linker::Writer& wr) override;
432
433 protected:
434 virtual void DumpFields(COFFFormat& coff, Dumper::Dumper& dump, Dumper::Region& header_region);
435
436 public:
437 void Dump(COFFFormat& coff, Dumper::Dumper& dump) override;
438 };
439
445 {
446 public:
450 uint32_t relocations_offset = 0;
454 uint32_t stack_size = 0;
455
456 /* TODO: magic not needed for CDOS68K? */
457
458 uint32_t GetSize() override;
459
460 void ReadFile(Linker::Reader& rd) override;
461
462 void WriteFile(Linker::Writer& wr) override;
463
464 void PostReadFile(COFFFormat& coff, Linker::Reader& rd) override;
465
466 void PostWriteFile(COFFFormat& coff, Linker::Writer& wr) override;
467
468 protected:
469 void DumpFields(COFFFormat& coff, Dumper::Dumper& dump, Dumper::Region& header_region) override;
470 };
471
477 {
478 public:
479 /* Note: untested */
480 uint32_t info = 0;
481 uint32_t code_size = 0;
482 uint32_t data_size = 0;
483 uint32_t bss_size = 0;
484 uint32_t symbol_table_size = 0;
485 uint32_t entry_address = 0;
486 uint32_t code_relocation_size = 0;
487 uint32_t data_relocation_size = 0;
488
489 uint32_t GetSize() override;
490
491 void ReadFile(Linker::Reader& wr) override;
492
493 void WriteFile(Linker::Writer& wr) override;
494
495 void Dump(COFFFormat& coff, Dumper::Dumper& dump) override;
496 };
497
504 {
505 public:
506 // https://web.archive.org/web/20140723105157/http://www-scf.usc.edu/~csci402/ncode/coff_8h-source.html
507 /* bss_start */
508 uint32_t bss_address;
509 /* gpr_mask */
510 uint32_t gpr_mask;
511 /* cprmask */
512 uint32_t cpr_mask[4];
513 /* gp_value */
514 uint32_t gp_value;
515 /* TODO */
516
517 protected:
518 void DumpFields(COFFFormat& coff, Dumper::Dumper& dump, Dumper::Region& header_region) override;
519 };
520
521 void Clear() override;
522
523 void AssignMagicValue();
524
530 cpu cpu_type = CPU_UNKNOWN;
531
535 ::EndianType endiantype = ::EndianType(0);
536
537 bool DetectCpuType(::EndianType expected);
538
539 void DetectCpuType();
540
541 void ReadFile(Linker::Reader& rd) override;
542
543 void WriteFile(Linker::Writer& wr) override;
544
545 void Dump(Dumper::Dumper& dump) override;
546
547 /* * * Reader members * * */
548
549 void SetupOptions(std::shared_ptr<Linker::OutputFormat> format) override;
550
551 bool option_segmentation = false;
552
553 bool FormatRequiresDataStreamFix() const override;
554
555 private:
556 /* symbols */
557 std::string segment_prefix();
558
559 std::string segment_of_prefix();
560
564 std::string segmented_address_prefix();
565
566#if 0
567 // TODO: can this be used?
568 std::string segment_difference_prefix();
569#endif
570
571 enum
572 {
573 /* section number */
574 N_UNDEF = 0,
575 N_ABS = 0xFFFF,
576 N_DEBUG = 0xFFFE,
577
578 /* storage class */
579 C_EXT = 2,
580 C_STAT = 3,
581 C_LABEL = 6,
582 };
583
584 void GenerateModule(Linker::Module& module) const;
585
586 public:
587 void ProduceModule(Linker::Module& module, Linker::Reader& rd) override;
588
589 /* * * Writer members * * */
590
591 public:
618
623
627 uint32_t stub_size = 0;
628
632 std::shared_ptr<Linker::Segment> stack;
636 uint32_t entry_address = 0; /* TODO */
640 uint32_t relocations_offset = 0;
641
643 : type(type)
644 {
645 }
646
648 {
649 Clear();
650 }
651
652 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
653
654 static std::shared_ptr<COFFFormat> CreateWriter(format_type type);
655
656 using LinkerManager::SetLinkScript;
657
658 void SetOptions(std::map<std::string, std::string>& options) override;
659
661 enum
662 {
663 FLAG_NO_RELOCATIONS = 0x0001,
664 FLAG_EXECUTABLE = 0x0002,
665 FLAG_NO_LINE_NUMBERS = 0x0004,
666 FLAG_NO_SYMBOLS = 0x0008,
667 FLAG_32BIT_LITTLE_ENDIAN = 0x0100,
668 FLAG_32BIT_BIG_ENDIAN = 0x0200,
669
673 ZMAGIC = 0x010B,
674 };
675
676 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
677
678 void CreateDefaultSegments();
679
680 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
681
682 void Link(Linker::Module& module);
683
685 std::shared_ptr<Linker::Segment> GetSegment(std::unique_ptr<Section>& section);
686
687 std::shared_ptr<Linker::Segment> GetCodeSegment();
688
689 std::shared_ptr<Linker::Segment> GetDataSegment();
690
691 std::shared_ptr<Linker::Segment> GetBssSegment();
692
693 void ProcessModule(Linker::Module& module) override;
694
695 void CalculateValues() override;
696
697 void GenerateFile(std::string filename, Linker::Module& module) override;
698
699 std::string GetDefaultExtension(Linker::Module& module, std::string filename) override;
700 };
701
702}
703
704#endif /* COFF_H */
A standard 28 byte a.out optional header, used by DJGPP.
Definition coff.h:386
uint32_t code_address
unused (COFF name: text_start)
Definition coff.h:416
uint16_t version_stamp
unused (COFF name: vstamp)
Definition coff.h:395
uint32_t entry_address
Initial value of eip (COFF name: entry)
Definition coff.h:412
uint16_t magic
Type of executable, most typically ZMAGIC (COFF name: magic)
Definition coff.h:391
uint32_t GetSize() override
Returns size of optional header.
Definition coff.cc:338
uint32_t code_size
unused (COFF name: tsize)
Definition coff.h:400
uint32_t data_size
unused (COFF name: dsize)
Definition coff.h:404
uint32_t bss_size
unused (COFF name: bsize)
Definition coff.h:408
uint32_t data_address
unused (COFF name: data_start)
Definition coff.h:420
Concurrent DOS 68K/FlexOS 386 optional header Concurrent DOS 68K uses the typical a....
Definition coff.h:445
void PostWriteFile(COFFFormat &coff, Linker::Writer &wr) override
Stores any additional data in the file corresponding to this type of optional header.
Definition coff.cc:431
uint32_t GetSize() override
Returns size of optional header.
Definition coff.cc:407
void PostReadFile(COFFFormat &coff, Linker::Reader &rd) override
Retrieves any additional data from the file corresponding to this type of optional header.
Definition coff.cc:426
uint32_t stack_size
Size of stack for execution.
Definition coff.h:454
uint32_t relocations_offset
The offset to the crunched relocation data within the file.
Definition coff.h:450
GNU a.out optional header TODO.
Definition coff.h:477
uint32_t GetSize() override
Returns size of optional header.
Definition coff.cc:445
A standard 28 byte a.out optional header, used by DJGPP.
Definition coff.h:504
An abstract class to represent the optional header.
Definition coff.h:329
virtual void PostWriteFile(COFFFormat &coff, Linker::Writer &wr)
Stores any additional data in the file corresponding to this type of optional header.
Definition coff.cc:310
virtual uint32_t GetSize()=0
Returns size of optional header.
virtual void PostReadFile(COFFFormat &coff, Linker::Reader &rd)
Retrieves any additional data from the file corresponding to this type of optional header.
Definition coff.cc:306
A generic COFF relocation.
Definition coff.h:79
A COFF section.
Definition coff.h:208
std::string name
The name of the section (COFF name: s_name)
Definition coff.h:213
std::shared_ptr< Linker::Writable > image
The stored image data.
Definition coff.h:254
uint32_t address
The virtual address of the section (COFF name: s_vaddr)
Definition coff.h:221
std::vector< std::unique_ptr< Relocation > > relocations
Collection of COFF relocations.
Definition coff.h:259
uint16_t relocation_count
COFF relocation count (COFF name: s_nreloc)
Definition coff.h:241
uint16_t line_number_count
unused (COFF name: s_nlnno)
Definition coff.h:245
uint32_t section_pointer
Offset of stored image data from COFF header start (COFF name: s_scnptr)
Definition coff.h:229
uint32_t relocation_pointer
Offset to COFF relocations (COFF name: s_relptr)
Definition coff.h:233
@ DATA
Section contains initialized data (COFF name: STYP_DATA)
Definition coff.h:267
@ BSS
Section contains uninitialized data (COFF name: STYP_BSS)
Definition coff.h:269
@ TEXT
Section contains executable (COFF name: STYP_TEXT)
Definition coff.h:265
uint32_t physical_address
The physical address of the section (expected to be identical to the virtual address) (COFF name: s_p...
Definition coff.h:217
uint32_t size
The size of the section (COFF name: s_size)
Definition coff.h:225
uint32_t line_number_pointer
unused (COFF name: s_lnnoptr)
Definition coff.h:237
uint32_t flags
COFF section flags, determines the type of the section (text, data, bss, etc.) (COFF name: s_flags)
Definition coff.h:249
A COFF symbol.
Definition coff.h:166
std::string name
Symbol name (COFF name: n_name, if it fits inside field)
Definition coff.h:171
uint16_t section_number
The number of the section, with special values 0 (N_UNDEF), 1 (N_ABS) and 2 (N_DEBUG) (COFF name: n_s...
Definition coff.h:183
uint16_t type
The symbol type (COFF name: n_type)
Definition coff.h:187
uint8_t storage_class
COFF name: n_sclass, typical values are 2 (C_EXT), 3 (C_STAT)
Definition coff.h:193
uint32_t name_index
The index of the symbol name within the string table, if not stored directly in the entry,...
Definition coff.h:175
uint8_t auxiliary_count
Signifies how many extra entries are present, these should be skipped, 0 is a typical value (COFF nam...
Definition coff.h:197
uint32_t value
The actual value of the symbol (COFF name: n_value)
Definition coff.h:179
A simplified class to represent an optional header of unknown structure.
Definition coff.h:364
uint32_t GetSize() override
Returns size of optional header.
Definition coff.cc:318
A relocation, as stored by the Z80/Z8000 backend.
Definition coff.h:91
uint32_t symbol_index
Index of symbol in symbol table (COFF name: r_symndx)
Definition coff.h:134
uint16_t data
unknown (COFF name: r_stuff)
Definition coff.h:146
uint32_t address
Address of the relocation (COFF name: r_vaddr)
Definition coff.h:130
uint16_t type
Type of relocation (COFF name: r_type)
Definition coff.h:142
uint32_t offset
(COFF name: r_offset)
Definition coff.h:138
The UNIX COFF file format.
Definition coff.h:26
void Clear() override
Resets all fields to their default values, deallocate memory.
Definition coff.cc:514
std::string GetDefaultExtension(Linker::Module &module, std::string filename) override
Appends a default extension to the filename.
Definition coff.cc:1621
void Dump(Dumper::Dumper &dump) override
Display file contents in a nice manner.
Definition coff.cc:761
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition coff.cc:1514
format_type
Represents the type of target system, which will determine the CPU type and several other fields.
Definition coff.h:596
@ CDOS386
FlexOS 386 executable (unknown)
Definition coff.h:612
@ GENERIC
An unspecified value, probably will not work.
Definition coff.h:600
@ DJGPP
DJGPP COFF executable.
Definition coff.h:604
@ CDOS68K
Concurrent DOS 68K executable (untested but confident)
Definition coff.h:608
uint32_t optional_header_size
The size of the optional header (COFF: f_opthdr)
Definition coff.h:319
void WriteFile(Linker::Writer &wr) override
Stores data in memory to file.
Definition coff.cc:717
@ ZMAGIC
Stored as the magic of the a.out header.
Definition coff.h:673
std::map< uint32_t, size_t > relocations
Concurrent DOS 68K requires a special block of data to represent "crunched" relocations (see CPM68KWr...
Definition coff.h:358
void ProduceModule(Linker::Module &module, Linker::Reader &rd) override
Reads a file and loads the information into a module object.
Definition coff.cc:1228
format_type type
A representation of the format to generate.
Definition coff.h:617
char signature[2]
The actual value of the magic number (COFF name: f_magic)
Definition coff.h:68
uint32_t symbol_table_offset
Offset to the first symbol (COFF name: f_symptr)
Definition coff.h:307
std::vector< std::unique_ptr< Symbol > > symbols
The symbols stored inside the COFF file.
Definition coff.h:315
bool FormatRequiresDataStreamFix() const override
Whether the generated file might contain bugs that require fixing.
Definition coff.cc:887
cpu
Represents the first 16-bit word of a COFF file.
Definition coff.h:33
::EndianType endiantype
The byte order.
Definition coff.h:535
uint32_t relocations_offset
Concurrent DOS 68K: Offset to relocations.
Definition coff.h:640
bool option_no_relocation
Suppress relocation generation, only relevant for Concurrent DOS 68K, since the other target formats ...
Definition coff.h:622
uint32_t stub_size
Size of MZ stub, only used for DJGPP COFF executables.
Definition coff.h:627
std::shared_ptr< Linker::Segment > stack
Concurrent DOS 68K and FlexOS 386: The stack segment, not stored as part of any section.
Definition coff.h:632
void SetupOptions(std::shared_ptr< Linker::OutputFormat > format) override
Initializes the reader for linking purposes.
Definition coff.cc:882
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition coff.cc:584
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition coff.cc:1583
uint16_t section_count
Section count (COFF name: f_nscns)
Definition coff.h:299
std::shared_ptr< Linker::Segment > GetSegment(std::unique_ptr< Section > &section)
Return the segment stored inside the section, note that this only works for binary generation.
Definition coff.cc:1423
uint32_t entry_address
Entry address, gets stored in optional header later.
Definition coff.h:636
std::vector< std::unique_ptr< Section > > sections
The list of COFF sections.
Definition coff.h:294
uint32_t symbol_count
The number of symbols (COFF name: f_nsyms)
Definition coff.h:311
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition coff.cc:1253
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition coff.cc:1458
::EndianType GetEndianType() const
Retrieves the natural byte order for the architecture.
Definition coff.cc:77
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 coff.cc:1265
std::unique_ptr< OptionalHeader > optional_header
The optional header instance used for reading/writing the COFF file.
Definition coff.h:353
uint16_t flags
COFF flags, such as whether the file is executable (f_flags)
Definition coff.h:323
cpu cpu_type
The CPU type, reflected by the first 16-bit word of a COFF file.
Definition coff.h:530
uint32_t timestamp
Time stamp, unused (COFF name: f_timdat)
Definition coff.h:303
A class to control the output of a file analysis.
Definition dumper.h:550
A brief record, such as a relocation or imported library.
Definition dumper.h:476
A record that represents a region within the file.
Definition dumper.h:455
A class that provides a general interface to loading a module.
Definition format.h:161
A helper class to collect sections into segments.
Definition linker.h:19
Encodes an object module file as a collection of sections, symbols and relocations.
Definition module.h:20
A class that provides a general interface to setting up generation for a format.
Definition format.h:56
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:16
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15
Definition mzexe.h:248
Definition coff.h:60