RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
neexe.h
1#ifndef NEEXE_H
2#define NEEXE_H
3
4#include <array>
5#include "mzexe.h"
6#include "../common.h"
7#include "../dumper/dumper.h"
8#include "../linker/module.h"
9#include "../linker/options.h"
10#include "../linker/segment.h"
11#include "../linker/segment_manager.h"
12#include "../linker/writer.h"
13
14namespace Microsoft
15{
16 namespace Windows
17 {
19 enum
20 {
21 RT_CURSOR = 0x0001,
22 RT_BITMAP = 0x0002,
23 RT_ICON = 0x0003,
24 RT_MENU = 0x0004,
25 RT_DIALOG = 0x0005,
26 RT_STRING = 0x0006,
27 RT_FONTDIR = 0x0007,
28 RT_FONT = 0x0008,
29 RT_ACCELERATOR = 0x0009,
30 RT_RCDATA = 0x000A,
31 RT_MESSAGETABLE = 0x000B,
32 RT_GROUP_CURSOR = 0x000C,
33 RT_GROUP_ICON = 0x000E,
34 RT_VERSION = 0x0010,
35 RT_DLGINCLUDE = 0x0011,
36 RT_PLUGPLAY = 0x0013,
37 RT_VXD = 0x0014,
38 RT_ANICURSOR = 0x0015,
39 RT_ANIICON = 0x0016,
40 RT_HTML = 0x0017,
41 RT_MANIFEST = 0x0018,
42 };
43 }
44
45 namespace OS2
46 {
47 // based on OpenWatcom sources
48
50 enum
51 {
52 // cursor
53 RT_POINTER = 0x0001,
54 RT_BITMAP = 0x0002,
55 RT_MENU = 0x0003,
56 RT_DIALOG = 0x0004,
57 RT_STRING = 0x0005,
58 RT_FONTDIR = 0x0006,
59 RT_FONT = 0x0007,
60 RT_ACCELERATOR = 0x0008,
61 // binary data
62 RT_RCDATA = 0x0009,
63 // error message
64 RT_MESSAGE = 0x000A,
65 RT_DLGINCLUDE = 0x000B,
66 RT_VKEYTBL = 0x000C,
67 RT_KEYTBL = 0x000D,
68 RT_CHARTBL = 0x000E,
69 RT_DISPLAYINFO = 0x000F,
70 // function key area
71 RT_FKASHORT = 0x0010,
72 RT_FKALONG = 0x0011,
73 RT_HELPTABLE = 0x0012,
74 RT_HELPSUBTABLE = 0x0013,
75 RT_FDDIR = 0x0014,
76 RT_FD = 0x0015,
77 };
78 }
79
89 class NEFormat : public virtual Linker::SegmentManager, public std::enable_shared_from_this<NEFormat>
90 {
91 public:
92 /* * * General members * * */
93
95 struct Name
96 {
97 public:
98 std::string name;
99 uint16_t ordinal = 0;
100 };
101
104 {
105 public:
106 std::shared_ptr<Linker::Image> image;
107 offset_t data_offset = 0;
109 offset_t image_size = 0;
110 enum flag_type : uint16_t
111 {
112 Data = 1, Code = 0,
113 Allocated = 2,
114 Loaded = 4, /* RealMode = 4 */ /* TODO */
115 Iterated = 8, /* TODO */
116 Movable = 0x10, Fixed = 0,
117 Shareable = 0x20,
118 Preload = 0x40, LoadOnCall = 0,
119 ExecuteOnly = 0x80|Code, ReadOnly = 0x80|Data,
120 Relocations = 0x0100,
121 DebugInfo = 0x0200,
122 Discardable = 0x1000,
123 };
124 flag_type flags = flag_type(0);
126 uint32_t total_size = 0;
132
133 Segment()
134 {
135 }
136
137 Segment(std::shared_ptr<Linker::Segment> segment, unsigned flags)
138 : image(segment), flags(flag_type(flags))
139 {
140 }
141
142 enum
143 {
144 PrivilegeLevelShift = 10,
145 };
146
148 {
149 public:
193 std::vector<uint16_t> offsets;
195 uint16_t module = 0;
196 enum
197 {
198 FIARQQ = 1, FJARQQ = 1,
199 FISRQQ = 2, FJSRQQ = 2,
200 FICRQQ = 3, FJCRQQ = 3,
201 FIERQQ = 4,
202 FIDRQQ = 5,
203 FIWRQQ = 6,
204 };
207
209 std::string module_name;
211 std::string import_name;
213 uint8_t actual_segment = 0;
216
217 Relocation() = default;
218
219 Relocation(unsigned type, unsigned flags, uint16_t offset, uint16_t module, uint16_t target)
220 : type(source_type(type)), flags(flag_type(flags)), module(module), target(target)
221 {
222 offsets.push_back(offset);
223 }
224
225 static source_type GetType(Linker::Relocation& rel);
226 size_t GetSize() const;
227 };
228 std::vector<Relocation> relocations;
230 std::map<uint16_t, Relocation> relocations_map;
231
232 void AddRelocation(const Relocation& rel);
233 void Dump(Dumper::Dumper& dump, unsigned index, bool isos2) const;
234 };
235
240 class Resource : public Segment
241 {
242 public:
247 uint16_t type_id = 0;
249 std::string type_id_name;
254 uint16_t id = 0;
256 std::string id_name;
258 uint16_t handle = 0;
260 uint16_t usage = 0;
261
262 void Dump(Dumper::Dumper& dump, unsigned index, bool isos2) const;
263 };
264
267 {
268 public:
269 uint16_t type_id = 0;
270 std::string type_id_name;
271 std::vector<Resource> resources;
272 };
273
275 class Entry
276 {
277 public:
291 uint8_t segment = 0;
293 enum flag_type : uint8_t
294 {
299 };
300 flag_type flags = flag_type(0);
302 uint16_t offset = 0;
303
304 // informational purposes
317 std::string entry_name;
318
319 enum
320 {
321 WordCountShift = 3,
322
324 INT_3Fh = 0x3FCD,
325 };
326
328 mutable bool same_bundle = false; // mutable because this isn't actually part of the entry state but the entire entry table
329
330 Entry() = default;
331
332 Entry(unsigned type, uint8_t segment, unsigned flags, uint16_t offset)
334 {
335 }
336
338 offset_t GetEntrySize() const;
339
341 uint8_t GetIndicatorByte() const;
342
344 static Entry ReadEntry(Linker::Reader& rd, uint8_t indicator_byte);
346 void WriteEntry(Linker::Writer& wr) const;
347 };
348
351 {
352 public:
354 uint16_t name_offset = 0;
356 std::string name;
357
358 ModuleReference(uint16_t name_offset, std::string name = "")
360 {
361 }
362 };
363
365 std::array<char, 2> signature{'N', 'E'};
366
368 struct version
369 {
370 uint8_t major, minor;
371 };
374
375 uint32_t crc32 = 0;
376
377 enum program_flag_type : uint8_t
378 {
391
392 GLOBAL_INITIALIZATION = 4,
393 PROTECTED_MODE_ONLY = 8,
394 CPU_8086 = 0x10, /* this is not how all systems handle this */
395 CPU_80286 = 0x20,
396 CPU_80386 = 0x40,
397 CPU_8087 = 0x80,
398 };
401
403 {
415 GUI = 3,
416
417 FAMILY_APPLICATION = 8, /* first segment loads application */
418 ERROR_IN_IMAGE = 0x20,
419
421 LIBRARY = 0x80,
422 };
425
427 uint16_t automatic_data = 0;
428
430 uint16_t stack_size = 0;
432 uint16_t heap_size = 0;
433
434 uint16_t ip = 0, cs = 0, sp = 0, ss = 0;
435
436 // The following fields are listed in the order the parts appearing in the binary instead of the fields in the header
437
443
444 std::vector<Segment> segments;
445
451
452 uint16_t resource_count = 0;
453
455 uint16_t resource_shift = 0;
456
458 std::vector<Resource> resources;
459
461 std::vector<ResourceType> resource_types;
462
464 std::vector<std::string> resource_strings;
465
471
472 std::vector<Name> resident_names;
473
479
480 std::vector<ModuleReference> module_references;
481
487
488 std::vector<std::string> imported_names;
489
495 uint32_t nonresident_name_table_length = 0;
496
497 std::vector<Name> nonresident_names;
498
503 uint32_t entry_table_offset = 0;
504
506 uint32_t entry_table_length = 0;
507
510
511 std::vector<Entry> entries;
512
514 uint16_t sector_shift = 9;
515
516 enum system_type : uint8_t
517 {
519 OS2 = 1,
524 Windows386,
525 BorlandOSS,
526 PharLap = 0x80,
527 };
528 system_type system = system_type(0);
529
530 enum additional_flag_type : uint8_t
531 {
532 SUPPORT_LONGFILENAME = 1,
533 WIN20_PROTECTED_MODE = 2,
534 WIN20_PROPORTIONAL_FONTS = 4,
535 FAST_LOAD_AREA = 8,
536 };
537 additional_flag_type additional_flags = additional_flag_type(0);
538
539 union
540 {
541 /* Windows */
542 uint16_t fast_load_area_offset;
543 /* OS/2 ? */
544 uint16_t return_thunks_offset;
545 };
546 union
547 {
548 /* Windows */
549 uint16_t fast_load_area_length;
550 /* OS/2 ? */
551 uint16_t segment_reference_thunks_offset;
552 };
553 uint16_t code_swap_area_length = 0;
554
555 version windows_version{0, 0};
556
557 offset_t file_size = offset_t(-1);
558
559 bool IsLibrary() const;
560
561 bool IsOS2() const;
562
563 void ReadFile(Linker::Reader& rd) override;
564
565 offset_t ImageSize() const override;
566
568 offset_t WriteFile(Linker::Writer& wr) const override;
569
570 void Dump(Dumper::Dumper& dump) const override;
571
572 explicit NEFormat()
573 {
574 }
575
576 NEFormat(system_type system, unsigned program_flags, unsigned application_flags)
578 fast_load_area_offset(0), fast_load_area_length(0)
579 {
580 }
581
582 /* * * Writer members * * */
583
585 {
586 public:
587 Linker::Option<std::string> stub{"stub", "Filename for stub that gets prepended to executable"};
588
590 {
591 InitializeFields(stub);
592 }
593 };
594
595 mutable MZStubWriter stub;
596 std::shared_ptr<Linker::Segment> stack, heap;
597 std::map<std::shared_ptr<Linker::Segment>, size_t> segment_index;
598 std::map<std::string, uint16_t> module_reference_offsets;
599 std::map<std::string, uint16_t> imported_name_offsets;
600 uint16_t imported_names_length = 0;
601
602 /*std::string stub_file;*/
603 std::string module_name;
604 std::string program_name;
605
606 bool option_capitalize_names = false; /* TODO: parametrize */
607 enum memory_model_t
608 {
609 MODEL_SMALL,
610 MODEL_LARGE,
611 };
612 memory_model_t memory_model = MODEL_SMALL;
613
614 bool FormatSupportsSegmentation() const override;
615
616 bool FormatIs16bit() const override;
617
618 bool FormatIsProtectedMode() const override;
619
620 bool FormatSupportsLibraries() const override;
621
622 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
623
624 enum compatibility_type
625 {
626 CompatibleNone,
627 CompatibleWatcom,
628 CompatibleMicrosoft, /* TODO */
629 CompatibleGNU, /* TODO */
630 };
631 compatibility_type compatibility = CompatibleNone;
632
633 std::shared_ptr<NEFormat> SimulateLinker(compatibility_type compatibility);
634
635 static std::shared_ptr<NEFormat> CreateConsoleApplication(system_type system = Windows);
636
637 static std::shared_ptr<NEFormat> CreateGUIApplication(system_type system = Windows);
638
639 static std::shared_ptr<NEFormat> CreateLibraryModule(system_type system = Windows);
640
641 unsigned GetCodeSegmentFlags() const;
642 unsigned GetDataSegmentFlags() const;
643 void AddSegment(const Segment& segment);
644 uint16_t FetchModule(std::string name);
645 uint16_t FetchImportedName(std::string name);
646 std::string MakeProcedureName(std::string name);
647 uint16_t MakeEntry(Linker::Position value);
648 uint16_t MakeEntry(uint16_t ordinal, Linker::Position value);
649 uint8_t CountBundles(size_t entry_index) const;
650
651 void SetModel(std::string model) override;
652 std::shared_ptr<Linker::OptionCollector> GetOptions() override;
653 void SetOptions(std::map<std::string, std::string>& options) override;
654 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
655 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
656 void Link(Linker::Module& module);
657 void ProcessModule(Linker::Module& module) override;
658 void CalculateValues() override;
659 void GenerateFile(std::string filename, Linker::Module& module) override;
661 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
662 };
663}
664
665#endif /* NEEXE_H */
An abstract interface that separates structure and presentation of the data inside a file.
Definition dumper.h:586
offset_t WriteFile(Writer &wr) const override=0
Stores data in memory to file.
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:308
Documents and handles command line options.
Definition options.h:196
virtual std::string GetDefaultExtension(Module &module, std::string filename) const
Appends a default extension to the filename.
Stores an absolute address along with the containing segment or address space.
Definition position.h:17
A helper class, encapsulating functionality needed to import binary data.
Definition reader.h:16
A representation of a value within some binary data that has to be fixed up once the exact position o...
Definition relocation.h:27
A helper class to collect sections into segments.
Definition segment_manager.h:32
A helper class, encapsulating functionality needed to export binary data.
Definition writer.h:15
Definition mzexe.h:300
Represents an entry into the binary, typically DLL exported procedures.
Definition neexe.h:276
offset_t GetEntrySize() const
Returns the size of an entry as stored in the file, without the first two bytes of the bundle.
Definition neexe.cc:299
uint8_t segment
The number of the segment, 1 based.
Definition neexe.h:291
void WriteEntry(Linker::Writer &wr) const
Writes an entry within a bundle.
Definition neexe.cc:355
flag_type
Flags present in an entry.
Definition neexe.h:294
@ Exported
Set if the entry is exported.
Definition neexe.h:296
@ SharedData
Set if the data segment used by the entry is global, used in SINGLEDATA modules (libraries)
Definition neexe.h:298
bool same_bundle
Convenience field to signify this entry is part of the same bundle as the previous one.
Definition neexe.h:328
uint16_t offset
Offset within the segment.
Definition neexe.h:302
export_type export_state
Whether the entry is exported. This is not actually stored in the entry table and its value is ignore...
Definition neexe.h:315
static Entry ReadEntry(Linker::Reader &rd, uint8_t indicator_byte)
Reads an entry within a bundle.
Definition neexe.cc:330
uint8_t GetIndicatorByte() const
Retrieves the segment indicator byte. For Fixed entries, this the same as the segment number.
Definition neexe.cc:315
export_type
Definition neexe.h:306
@ NotExported
The entry is not exported, the Exported bit is not set.
Definition neexe.h:308
@ ExportByOrdinal
The entry is exported by ordinal, it is referenced in the nonresident name table.
Definition neexe.h:312
@ ExportByName
The entry is exported by name, it is referenced in the resident name table.
Definition neexe.h:310
std::string entry_name
The name of an exported entry. This is not actually stored in the entry table and its value is ignore...
Definition neexe.h:317
entry_type
This field represents the type of the entry.
Definition neexe.h:280
@ Fixed
The entry references a fixed segment.
Definition neexe.h:284
@ Movable
The entry references a movable segment.
Definition neexe.h:286
@ Unused
The entry is unused, the other fields are meaningless.
Definition neexe.h:282
@ INT_3Fh
Byte code for interrupt call that must be placed in the entry field.
Definition neexe.h:324
entry_type type
The type of entry, based on the first byte in an entry bundle.
Definition neexe.h:289
Represents an imported module in the module reference table.
Definition neexe.h:351
std::string name
The name of the module, not actually used during program generation.
Definition neexe.h:356
uint16_t name_offset
Offset to the module name within the imported names table.
Definition neexe.h:354
Windows executables bundle their resources by resource type.
Definition neexe.h:267
Represents a resource entry.
Definition neexe.h:241
uint16_t handle
Reserved field, named so in Microsoft documentation.
Definition neexe.h:258
std::string type_id_name
Type name, used only by Windows.
Definition neexe.h:249
uint16_t usage
Reserved field, named so in Microsoft documentation.
Definition neexe.h:260
std::string id_name
Resource name, used only by Windows.
Definition neexe.h:256
uint16_t type_id
Type identifier, used by both Windows and OS/2.
Definition neexe.h:247
std::string import_name
Convenience field that stores the imported procedure name, if imported by name, also the name for an ...
Definition neexe.h:211
uint8_t actual_segment
Convenience field that stores the actual segment for an entry.
Definition neexe.h:213
flag_type flags
The type of target.
Definition neexe.h:191
source_type
The type of the field that needs to be updated in the binary image.
Definition neexe.h:152
@ Offset16
A 16-bit offset within its preferred segment.
Definition neexe.h:160
@ Selector16
A 16-bit segment selector value (or paragraph in real mode)
Definition neexe.h:156
@ Offset32
A 32-bit offset within its preferred segment.
Definition neexe.h:164
@ Pointer48
A 48-bit far pointer, 16-bit segment and 32-bit offset value.
Definition neexe.h:162
@ Offset8
Lower 8 bits of value.
Definition neexe.h:154
@ Pointer32
A 32-bit far pointer, 16-bit segment and 16-bit offset value.
Definition neexe.h:158
uint16_t target
This field is an offset or ordinal, depending on the flags.
Definition neexe.h:206
flag_type
Encodes what the type of the target is for this relocation.
Definition neexe.h:170
@ TargetTypeMask
Mask to get the type of the target.
Definition neexe.h:172
@ Internal
An internal segment:offset, or if segment is 0xFF, offset is the entry number.
Definition neexe.h:174
@ Additive
Whether the relocation has an added in the image or it is the first element in a relocation chain.
Definition neexe.h:188
@ ImportName
An imported module:offset where module is the module number and offset is an offset to the name.
Definition neexe.h:178
@ OSFixup
This is actually an 80x87 instruction sequence that needs to be fixed up for 80x87 emulation.
Definition neexe.h:180
@ ImportOrdinal
An imported module:ordinal where module is the module number.
Definition neexe.h:176
source_type type
The type of relocation.
Definition neexe.h:167
std::string module_name
Convenience field that stores the module name.
Definition neexe.h:209
std::vector< uint16_t > offsets
The offset to the relocation, or if the relocation is chained, a list of offsets (this is not possibl...
Definition neexe.h:193
uint16_t
This field is a segment (1 based) or module (1 based) or 80x87 instruction reference,...
Definition neexe.h:195
uint16_t actual_offset
Convenience field that stores the actual offset for an entry.
Definition neexe.h:215
Represents an NE segment as stored in the segment table and segment data.
Definition neexe.h:104
uint32_t total_size
Size of segment as stored in memory.
Definition neexe.h:126
offset_t image_size
Size of segment as stored in the file, only used during reading.
Definition neexe.h:109
std::map< uint16_t, Relocation > relocations_map
Used internally during output generation.
Definition neexe.h:230
uint16_t movable_entry_index
Entry number for movable segments (field not present in segment table)
Definition neexe.h:131
NE .EXE new executable file format.
Definition neexe.h:90
uint32_t imported_names_table_offset
Offset of imported names table, containing the names of imported modules and procedures imported by n...
Definition neexe.h:486
uint32_t segment_table_offset
Offset of segment table.
Definition neexe.h:442
std::vector< ResourceType > resource_types
For non-OS/2 targets, the resources get organized according to their types.
Definition neexe.h:461
uint16_t heap_size
Size of initial heap, added to the size of the automatic data segment.
Definition neexe.h:432
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition neexe.cc:789
uint32_t resident_name_table_offset
Offset of resident name table, containing this module's name and the names and ordinals of procedures...
Definition neexe.h:470
program_flag_type
Definition neexe.h:378
@ MULTIPLEDATA
There is an automatic data segment for each task instance, used for applications (EXE)
Definition neexe.h:390
@ NODATA
There are no automatic data segments.
Definition neexe.h:380
@ SINGLEDATA
There is a single, shared automatic segment, used for libraries (DLL)
Definition neexe.h:385
program_flag_type program_flags
Properties of the program during execution.
Definition neexe.h:400
application_flag_type
Definition neexe.h:403
@ GUI
Graphical application.
Definition neexe.h:415
@ GUI_AWARE
Application is well behaved when running in windowed mode.
Definition neexe.h:413
@ LIBRARY
Set for library modules (DLL)
Definition neexe.h:421
@ FULLSCREEN
Application can only run in full screen mode.
Definition neexe.h:408
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition neexe.cc:1470
bool FormatSupportsSegmentation() const override
Whether the format supports multiple segments.
Definition neexe.cc:1229
uint32_t resource_table_offset
Offset of resource table.
Definition neexe.h:450
uint16_t resource_shift
Specifies the shift count to get the actual offsets for the resource data.
Definition neexe.h:455
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition neexe.cc:1829
std::shared_ptr< Linker::OptionCollector > GetOptions() override
Returns object containing a sequence of option fields provided with the -S command line flag.
Definition neexe.cc:1465
std::string GetDefaultExtension(Linker::Module &module, std::string filename) const override
Appends a default extension to the filename.
Definition neexe.cc:1977
uint32_t entry_table_length
Size of entry table in bytes.
Definition neexe.h:506
uint16_t automatic_data
Automatic data segment number, starting from 1, only used for SINGLEDATA/MULTIPLEDATA.
Definition neexe.h:427
uint16_t stack_size
Size of initial stack, added to the size of the automatic data segment.
Definition neexe.h:430
bool FormatIs16bit() const override
Whether the format is 16-bit or not.
Definition neexe.cc:1234
bool FormatIsProtectedMode() const override
Whether the format is in protected mode or not (x86 only)
Definition neexe.cc:1239
version linker_version
Version of the linker.
Definition neexe.h:373
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition neexe.cc:384
application_flag_type application_flags
Properties of the application.
Definition neexe.h:424
system_type
Definition neexe.h:517
@ OS2
Used for OS/2 1.0 - 1.3.
Definition neexe.h:519
@ MSDOS4
Signifies Multitasking MS-DOS 4.0.
Definition neexe.h:523
@ Windows
Used for Windows 1.0 - 3.11.
Definition neexe.h:521
uint16_t movable_entry_count
Number of movable entries in the entry table.
Definition neexe.h:509
offset_t ImageSize() const override
Retrieves size of stored data.
Definition neexe.cc:784
uint32_t entry_table_offset
Offset of entry table.
Definition neexe.h:503
std::array< char, 2 > signature
The signature, almost always "NE".
Definition neexe.h:365
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition neexe.cc:1245
std::vector< std::string > resource_strings
For non-OS/2 targets, this is a list of all the resource type strings and resource strings.
Definition neexe.h:464
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition neexe.cc:1944
uint16_t sector_shift
Specifies the shift count to get the actual offsets of segments.
Definition neexe.h:514
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition neexe.cc:1961
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition neexe.cc:1606
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition neexe.cc:974
std::vector< Resource > resources
On OS/2, this is a sequence of resources, for non-OS/2 targets, this must be compiled into resource_t...
Definition neexe.h:458
uint32_t nonresident_name_table_offset
Offset of non-resident names table, containing this module's description and the names of procedures ...
Definition neexe.h:494
uint32_t module_reference_table_offset
Offset of module reference table, containing 16-bit offsets to the names of the imported modules in t...
Definition neexe.h:478
A name and ordinal pair, as used for resident and non-resident names.
Definition neexe.h:96
Version number.
Definition neexe.h:369