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/segment.h"
10#include "../linker/segment_manager.h"
11#include "../linker/writer.h"
12
13namespace Microsoft
14{
15 namespace Windows
16 {
18 enum
19 {
20 RT_CURSOR = 0x0001,
21 RT_BITMAP = 0x0002,
22 RT_ICON = 0x0003,
23 RT_MENU = 0x0004,
24 RT_DIALOG = 0x0005,
25 RT_STRING = 0x0006,
26 RT_FONTDIR = 0x0007,
27 RT_FONT = 0x0008,
28 RT_ACCELERATOR = 0x0009,
29 RT_RCDATA = 0x000A,
30 RT_MESSAGETABLE = 0x000B,
31 RT_GROUP_CURSOR = 0x000C,
32 RT_GROUP_ICON = 0x000E,
33 RT_VERSION = 0x0010,
34 RT_DLGINCLUDE = 0x0011,
35 RT_PLUGPLAY = 0x0013,
36 RT_VXD = 0x0014,
37 RT_ANICURSOR = 0x0015,
38 RT_ANIICON = 0x0016,
39 RT_HTML = 0x0017,
40 RT_MANIFEST = 0x0018,
41 };
42 }
43
44 namespace OS2
45 {
46 // based on OpenWatcom sources
47
49 enum
50 {
51 // cursor
52 RT_POINTER = 0x0001,
53 RT_BITMAP = 0x0002,
54 RT_MENU = 0x0003,
55 RT_DIALOG = 0x0004,
56 RT_STRING = 0x0005,
57 RT_FONTDIR = 0x0006,
58 RT_FONT = 0x0007,
59 RT_ACCELERATOR = 0x0008,
60 // binary data
61 RT_RCDATA = 0x0009,
62 // error message
63 RT_MESSAGE = 0x000A,
64 RT_DLGINCLUDE = 0x000B,
65 RT_VKEYTBL = 0x000C,
66 RT_KEYTBL = 0x000D,
67 RT_CHARTBL = 0x000E,
68 RT_DISPLAYINFO = 0x000F,
69 // function key area
70 RT_FKASHORT = 0x0010,
71 RT_FKALONG = 0x0011,
72 RT_HELPTABLE = 0x0012,
73 RT_HELPSUBTABLE = 0x0013,
74 RT_FDDIR = 0x0014,
75 RT_FD = 0x0015,
76 };
77 }
78
88 class NEFormat : public virtual Linker::SegmentManager, public std::enable_shared_from_this<NEFormat>
89 {
90 public:
91 /* * * General members * * */
92
94 struct Name
95 {
96 public:
97 std::string name;
98 uint16_t ordinal = 0;
99 };
100
103 {
104 public:
105 std::shared_ptr<Linker::Image> image;
106 offset_t data_offset = 0;
108 offset_t image_size = 0;
109 enum flag_type : uint16_t
110 {
111 Data = 1, Code = 0,
112 Allocated = 2,
113 Loaded = 4, /* RealMode = 4 */ /* TODO */
114 Iterated = 8, /* TODO */
115 Movable = 0x10, Fixed = 0,
116 Shareable = 0x20,
117 Preload = 0x40, LoadOnCall = 0,
118 ExecuteOnly = 0x80|Code, ReadOnly = 0x80|Data,
119 Relocations = 0x0100,
120 DebugInfo = 0x0200,
121 Discardable = 0x1000,
122 };
123 flag_type flags = flag_type(0);
125 uint32_t total_size = 0;
131
132 Segment()
133 {
134 }
135
136 Segment(std::shared_ptr<Linker::Segment> segment, unsigned flags)
137 : image(segment), flags(flag_type(flags))
138 {
139 }
140
141 enum
142 {
143 PrivilegeLevelShift = 10,
144 };
145
147 {
148 public:
192 std::vector<uint16_t> offsets;
194 uint16_t module = 0;
195 enum
196 {
197 FIARQQ = 1, FJARQQ = 1,
198 FISRQQ = 2, FJSRQQ = 2,
199 FICRQQ = 3, FJCRQQ = 3,
200 FIERQQ = 4,
201 FIDRQQ = 5,
202 FIWRQQ = 6,
203 };
206
208 std::string module_name;
210 std::string import_name;
212 uint8_t actual_segment = 0;
215
216 Relocation() = default;
217
218 Relocation(unsigned type, unsigned flags, uint16_t offset, uint16_t module, uint16_t target)
219 : type(source_type(type)), flags(flag_type(flags)), module(module), target(target)
220 {
221 offsets.push_back(offset);
222 }
223
224 static source_type GetType(Linker::Relocation& rel);
225 size_t GetSize() const;
226 };
227 std::vector<Relocation> relocations;
229 std::map<uint16_t, Relocation> relocations_map;
230
231 void AddRelocation(const Relocation& rel);
232 void Dump(Dumper::Dumper& dump, unsigned index, bool isos2) const;
233 };
234
239 class Resource : public Segment
240 {
241 public:
246 uint16_t type_id = 0;
248 std::string type_id_name;
253 uint16_t id = 0;
255 std::string id_name;
257 uint16_t handle = 0;
259 uint16_t usage = 0;
260
261 void Dump(Dumper::Dumper& dump, unsigned index, bool isos2) const;
262 };
263
266 {
267 public:
268 uint16_t type_id = 0;
269 std::string type_id_name;
270 std::vector<Resource> resources;
271 };
272
274 class Entry
275 {
276 public:
290 uint8_t segment = 0;
292 enum flag_type : uint8_t
293 {
298 };
299 flag_type flags = flag_type(0);
301 uint16_t offset = 0;
302
303 // informational purposes
316 std::string entry_name;
317
318 enum
319 {
320 WordCountShift = 3,
321
323 INT_3Fh = 0x3FCD,
324 };
325
327 mutable bool same_bundle = false; // mutable because this isn't actually part of the entry state but the entire entry table
328
329 Entry() = default;
330
331 Entry(unsigned type, uint8_t segment, unsigned flags, uint16_t offset)
333 {
334 }
335
337 offset_t GetEntrySize() const;
338
340 uint8_t GetIndicatorByte() const;
341
343 static Entry ReadEntry(Linker::Reader& rd, uint8_t indicator_byte);
345 void WriteEntry(Linker::Writer& wr) const;
346 };
347
350 {
351 public:
353 uint16_t name_offset = 0;
355 std::string name;
356
357 ModuleReference(uint16_t name_offset, std::string name = "")
359 {
360 }
361 };
362
364 std::array<char, 2> signature{'N', 'E'};
365
367 struct version
368 {
369 uint8_t major, minor;
370 };
373
374 uint32_t crc32 = 0;
375
376 enum program_flag_type : uint8_t
377 {
390
391 GLOBAL_INITIALIZATION = 4,
392 PROTECTED_MODE_ONLY = 8,
393 CPU_8086 = 0x10, /* this is not how all systems handle this */
394 CPU_80286 = 0x20,
395 CPU_80386 = 0x40,
396 CPU_8087 = 0x80,
397 };
400
402 {
414 GUI = 3,
415
416 FAMILY_APPLICATION = 8, /* first segment loads application */
417 ERROR_IN_IMAGE = 0x20,
418
420 LIBRARY = 0x80,
421 };
424
426 uint16_t automatic_data = 0;
427
429 uint16_t stack_size = 0;
431 uint16_t heap_size = 0;
432
433 uint16_t ip = 0, cs = 0, sp = 0, ss = 0;
434
435 // The following fields are listed in the order the parts appearing in the binary instead of the fields in the header
436
442
443 std::vector<Segment> segments;
444
450
451 uint16_t resource_count = 0;
452
454 uint16_t resource_shift = 0;
455
457 std::vector<Resource> resources;
458
460 std::vector<ResourceType> resource_types;
461
463 std::vector<std::string> resource_strings;
464
470
471 std::vector<Name> resident_names;
472
478
479 std::vector<ModuleReference> module_references;
480
486
487 std::vector<std::string> imported_names;
488
494 uint32_t nonresident_name_table_length = 0;
495
496 std::vector<Name> nonresident_names;
497
502 uint32_t entry_table_offset = 0;
503
505 uint32_t entry_table_length = 0;
506
509
510 std::vector<Entry> entries;
511
513 uint16_t sector_shift = 9;
514
515 enum system_type : uint8_t
516 {
518 OS2 = 1,
523 Windows386,
524 BorlandOSS,
525 PharLap = 0x80,
526 };
527 system_type system = system_type(0);
528
529 enum additional_flag_type : uint8_t
530 {
531 SUPPORT_LONGFILENAME = 1,
532 WIN20_PROTECTED_MODE = 2,
533 WIN20_PROPORTIONAL_FONTS = 4,
534 FAST_LOAD_AREA = 8,
535 };
536 additional_flag_type additional_flags = additional_flag_type(0);
537
538 union
539 {
540 /* Windows */
541 uint16_t fast_load_area_offset;
542 /* OS/2 ? */
543 uint16_t return_thunks_offset;
544 };
545 union
546 {
547 /* Windows */
548 uint16_t fast_load_area_length;
549 /* OS/2 ? */
550 uint16_t segment_reference_thunks_offset;
551 };
552 uint16_t code_swap_area_length = 0;
553
554 version windows_version{0, 0};
555
556 offset_t file_size = offset_t(-1);
557
558 bool IsLibrary() const;
559
560 bool IsOS2() const;
561
562 void ReadFile(Linker::Reader& rd) override;
563
564 offset_t ImageSize() const override;
565
567 offset_t WriteFile(Linker::Writer& wr) const override;
568
569 void Dump(Dumper::Dumper& dump) const override;
570
571 explicit NEFormat()
572 {
573 }
574
575 NEFormat(system_type system, unsigned program_flags, unsigned application_flags)
577 fast_load_area_offset(0), fast_load_area_length(0)
578 {
579 }
580
581 /* * * Writer members * * */
582
583 mutable MZStubWriter stub;
584 std::shared_ptr<Linker::Segment> stack, heap;
585 std::map<std::shared_ptr<Linker::Segment>, size_t> segment_index;
586 std::map<std::string, uint16_t> module_reference_offsets;
587 std::map<std::string, uint16_t> imported_name_offsets;
588 uint16_t imported_names_length = 0;
589
590 /*std::string stub_file;*/
591 std::string module_name;
592 std::string program_name;
593
594 bool option_capitalize_names = false; /* TODO: parametrize */
595 enum memory_model_t
596 {
597 MODEL_SMALL,
598 MODEL_LARGE,
599 };
600 memory_model_t memory_model = MODEL_SMALL;
601
602 bool FormatSupportsSegmentation() const override;
603
604 bool FormatIs16bit() const override;
605
606 bool FormatSupportsLibraries() const override;
607
608 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
609
610 enum compatibility_type
611 {
612 CompatibleNone,
613 CompatibleWatcom,
614 CompatibleMicrosoft, /* TODO */
615 CompatibleGNU, /* TODO */
616 };
617 compatibility_type compatibility = CompatibleNone;
618
619 std::shared_ptr<NEFormat> SimulateLinker(compatibility_type compatibility);
620
621 static std::shared_ptr<NEFormat> CreateConsoleApplication(system_type system = Windows);
622
623 static std::shared_ptr<NEFormat> CreateGUIApplication(system_type system = Windows);
624
625 static std::shared_ptr<NEFormat> CreateLibraryModule(system_type system = Windows);
626
627 unsigned GetCodeSegmentFlags() const;
628 unsigned GetDataSegmentFlags() const;
629 void AddSegment(const Segment& segment);
630 uint16_t FetchModule(std::string name);
631 uint16_t FetchImportedName(std::string name);
632 std::string MakeProcedureName(std::string name);
633 uint16_t MakeEntry(Linker::Position value);
634 uint16_t MakeEntry(uint16_t ordinal, Linker::Position value);
635 uint8_t CountBundles(size_t entry_index) const;
636
637 void SetModel(std::string model) override;
638 void SetOptions(std::map<std::string, std::string>& options) override;
639 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
640 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
641 void Link(Linker::Module& module);
642 void ProcessModule(Linker::Module& module) override;
643 void CalculateValues() override;
644 void GenerateFile(std::string filename, Linker::Module& module) override;
646 std::string GetDefaultExtension(Linker::Module& module, std::string filename) const override;
647 };
648}
649
650#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
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
Represents an entry into the binary, typically DLL exported procedures.
Definition neexe.h:275
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:290
uint8_t segment
The number of the segment, 1 based.
Definition neexe.h:290
void WriteEntry(Linker::Writer &wr) const
Writes an entry within a bundle.
Definition neexe.cc:346
flag_type
Flags present in an entry.
Definition neexe.h:293
@ Exported
Set if the entry is exported.
Definition neexe.h:295
@ SharedData
Set if the data segment used by the entry is global, used in SINGLEDATA modules (libraries)
Definition neexe.h:297
bool same_bundle
Convenience field to signify this entry is part of the same bundle as the previous one.
Definition neexe.h:327
uint16_t offset
Offset within the segment.
Definition neexe.h:301
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:314
@ INT_3Fh
Byte code for interrupt call that must be placed in the entry field.
Definition neexe.h:323
static Entry ReadEntry(Linker::Reader &rd, uint8_t indicator_byte)
Reads an entry within a bundle.
Definition neexe.cc:321
uint8_t GetIndicatorByte() const
Retrieves the segment indicator byte. For Fixed entries, this the same as the segment number.
Definition neexe.cc:306
export_type
Definition neexe.h:305
@ NotExported
The entry is not exported, the Exported bit is not set.
Definition neexe.h:307
@ ExportByOrdinal
The entry is exported by ordinal, it is referenced in the nonresident name table.
Definition neexe.h:311
@ ExportByName
The entry is exported by name, it is referenced in the resident name table.
Definition neexe.h:309
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:316
entry_type
This field represents the type of the entry.
Definition neexe.h:279
@ Fixed
The entry references a fixed segment.
Definition neexe.h:283
@ Movable
The entry references a movable segment.
Definition neexe.h:285
@ Unused
The entry is unused, the other fields are meaningless.
Definition neexe.h:281
entry_type type
The type of entry, based on the first byte in an entry bundle.
Definition neexe.h:288
Represents an imported module in the module reference table.
Definition neexe.h:350
std::string name
The name of the module, not actually used during program generation.
Definition neexe.h:355
uint16_t name_offset
Offset to the module name within the imported names table.
Definition neexe.h:353
Windows executables bundle their resources by resource type.
Definition neexe.h:266
Represents a resource entry.
Definition neexe.h:240
uint16_t handle
Reserved field, named so in Microsoft documentation.
Definition neexe.h:257
std::string type_id_name
Type name, used only by Windows.
Definition neexe.h:248
uint16_t usage
Reserved field, named so in Microsoft documentation.
Definition neexe.h:259
std::string id_name
Resource name, used only by Windows.
Definition neexe.h:255
uint16_t type_id
Type identifier, used by both Windows and OS/2.
Definition neexe.h:246
std::string import_name
Convenience field that stores the imported procedure name, if imported by name, also the name for an ...
Definition neexe.h:210
uint8_t actual_segment
Convenience field that stores the actual segment for an entry.
Definition neexe.h:212
flag_type flags
The type of target.
Definition neexe.h:190
source_type
The type of the field that needs to be updated in the binary image.
Definition neexe.h:151
@ Offset16
A 16-bit offset within its preferred segment.
Definition neexe.h:159
@ Selector16
A 16-bit segment selector value (or paragraph in real mode)
Definition neexe.h:155
@ Offset32
A 32-bit offset within its preferred segment.
Definition neexe.h:163
@ Pointer48
A 48-bit far pointer, 16-bit segment and 32-bit offset value.
Definition neexe.h:161
@ Offset8
Lower 8 bits of value.
Definition neexe.h:153
@ Pointer32
A 32-bit far pointer, 16-bit segment and 16-bit offset value.
Definition neexe.h:157
uint16_t target
This field is an offset or ordinal, depending on the flags.
Definition neexe.h:205
flag_type
Encodes what the type of the target is for this relocation.
Definition neexe.h:169
@ TargetTypeMask
Mask to get the type of the target.
Definition neexe.h:171
@ Internal
An internal segment:offset, or if segment is 0xFF, offset is the entry number.
Definition neexe.h:173
@ Additive
Whether the relocation has an added in the image or it is the first element in a relocation chain.
Definition neexe.h:187
@ ImportName
An imported module:offset where module is the module number and offset is an offset to the name.
Definition neexe.h:177
@ OSFixup
This is actually an 80x87 instruction sequence that needs to be fixed up for 80x87 emulation.
Definition neexe.h:179
@ ImportOrdinal
An imported module:ordinal where module is the module number.
Definition neexe.h:175
source_type type
The type of relocation.
Definition neexe.h:166
std::string module_name
Convenience field that stores the module name.
Definition neexe.h:208
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:192
uint16_t
This field is a segment (1 based) or module (1 based) or 80x87 instruction reference,...
Definition neexe.h:194
uint16_t actual_offset
Convenience field that stores the actual offset for an entry.
Definition neexe.h:214
Represents an NE segment as stored in the segment table and segment data.
Definition neexe.h:103
uint32_t total_size
Size of segment as stored in memory.
Definition neexe.h:125
offset_t image_size
Size of segment as stored in the file, only used during reading.
Definition neexe.h:108
std::map< uint16_t, Relocation > relocations_map
Used internally during output generation.
Definition neexe.h:229
uint16_t movable_entry_index
Entry number for movable segments (field not present in segment table)
Definition neexe.h:130
NE .EXE new executable file format.
Definition neexe.h:89
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:485
uint32_t segment_table_offset
Offset of segment table.
Definition neexe.h:441
std::vector< ResourceType > resource_types
For non-OS/2 targets, the resources get organized according to their types.
Definition neexe.h:460
uint16_t heap_size
Size of initial heap, added to the size of the automatic data segment.
Definition neexe.h:431
offset_t WriteFile(Linker::Writer &wr) const override
Stores data in memory to file.
Definition neexe.cc:780
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:469
program_flag_type
Definition neexe.h:377
@ MULTIPLEDATA
There is an automatic data segment for each task instance, used for applications (EXE)
Definition neexe.h:389
@ NODATA
There are no automatic data segments.
Definition neexe.h:379
@ SINGLEDATA
There is a single, shared automatic segment, used for libraries (DLL)
Definition neexe.h:384
program_flag_type program_flags
Properties of the program during execution.
Definition neexe.h:399
application_flag_type
Definition neexe.h:402
@ GUI
Graphical application.
Definition neexe.h:414
@ GUI_AWARE
Application is well behaved when running in windowed mode.
Definition neexe.h:412
@ LIBRARY
Set for library modules (DLL)
Definition neexe.h:420
@ FULLSCREEN
Application can only run in full screen mode.
Definition neexe.h:407
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition neexe.cc:1439
bool FormatSupportsSegmentation() const override
Whether the format supports multiple segments.
Definition neexe.cc:1210
uint32_t resource_table_offset
Offset of resource table.
Definition neexe.h:449
uint16_t resource_shift
Specifies the shift count to get the actual offsets for the resource data.
Definition neexe.h:454
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition neexe.cc:1794
std::string GetDefaultExtension(Linker::Module &module, std::string filename) const override
Appends a default extension to the filename.
Definition neexe.cc:1942
uint32_t entry_table_length
Size of entry table in bytes.
Definition neexe.h:505
uint16_t automatic_data
Automatic data segment number, starting from 1, only used for SINGLEDATA/MULTIPLEDATA.
Definition neexe.h:426
uint16_t stack_size
Size of initial stack, added to the size of the automatic data segment.
Definition neexe.h:429
bool FormatIs16bit() const override
Whether the format is 16-bit or not.
Definition neexe.cc:1215
version linker_version
Version of the linker.
Definition neexe.h:372
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition neexe.cc:375
application_flag_type application_flags
Properties of the application.
Definition neexe.h:423
system_type
Definition neexe.h:516
@ OS2
Used for OS/2 1.0 - 1.3.
Definition neexe.h:518
@ MSDOS4
Signifies Multitasking MS-DOS 4.0.
Definition neexe.h:522
@ Windows
Used for Windows 1.0 - 3.11.
Definition neexe.h:520
uint16_t movable_entry_count
Number of movable entries in the entry table.
Definition neexe.h:508
offset_t ImageSize() const override
Retrieves size of stored data.
Definition neexe.cc:775
uint32_t entry_table_offset
Offset of entry table.
Definition neexe.h:502
std::array< char, 2 > signature
The signature, almost always "NE".
Definition neexe.h:364
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition neexe.cc:1220
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:463
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition neexe.cc:1909
uint16_t sector_shift
Specifies the shift count to get the actual offsets of segments.
Definition neexe.h:513
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition neexe.cc:1926
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition neexe.cc:1573
void Dump(Dumper::Dumper &dump) const override
Display file contents in a nice manner.
Definition neexe.cc:965
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:457
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:493
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:477
A name and ordinal pair, as used for resident and non-resident names.
Definition neexe.h:95
Version number.
Definition neexe.h:368