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 "mzexe.h"
5#include "../common.h"
6#include "../linker/linker.h"
7#include "../linker/module.h"
8#include "../linker/segment.h"
9#include "../linker/writer.h"
10
11namespace Microsoft
12{
22 class NEFormat : public virtual Linker::OutputFormat, public Linker::LinkerManager, protected Microsoft::MZStubWriter, public std::enable_shared_from_this<NEFormat>
23 {
24 public:
25 void ReadFile(Linker::Reader& rd) override;
26
27 bool FormatSupportsSegmentation() const override;
28
29 bool FormatIs16bit() const override;
30
31 bool FormatSupportsLibraries() const override;
32
33 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
34
35 enum system_type
36 {
37 OS2 = 1, /* OS/2 1.0 - 1.3 */
38 Windows, /* Windows 1.0 - 3.11 */
39 MSDOS4, /* Multitasking MS-DOS 4.0 */
40 Windows386,
41 BorlandOSS,
42 PharLap = 0x80,
43 };
44 system_type system = system_type(0);
45
46 enum program_flag_type
47 {
48 NODATA = 0,
49 SINGLEDATA = 1, /* .DLL */
50 MULTIPLEDATA = 2, /* .EXE */
51 GLOBAL_INITIALIZATION = 4,
52 PROTECTED_MODE_ONLY = 8,
53 CPU_8086 = 0x10, /* TODO: this is not how all systems handle this */
54 CPU_80286 = 0x20,
55 CPU_80386 = 0x40,
56 CPU_8087 = 0x80,
57 };
58 program_flag_type program_flags = program_flag_type(0);
59
60 enum application_flag_type
61 {
62 FULLSCREEN = 1,
63 GUI_AWARE = 2,
64 GUI = 3,
65 FAMILY_APPLICATION = 8, /* first segment loads application */
66 ERROR_IN_IMAGE = 0x20,
67 LIBRARY = 0x80,
68 };
69 application_flag_type application_flags = application_flag_type(0);
70
71 bool IsLibrary() const;
72
73 enum additional_flag_type
74 {
75 SUPPORT_LONGFILENAME = 1,
76 WIN20_PROTECTED_MODE = 2,
77 WIN20_PROPORTIONAL_FONTS = 4,
78 FAST_LOAD_AREA = 8,
79 };
80 additional_flag_type additional_flags = additional_flag_type(0);
81
82 enum compatibility_type
83 {
84 CompatibleNone,
85 CompatibleWatcom,
86 CompatibleMicrosoft, /* TODO */
87 CompatibleGNU, /* TODO */
88 };
89 compatibility_type compatibility = CompatibleNone;
90
91 NEFormat(system_type system, unsigned program_flags, unsigned application_flags)
92 : system(system), program_flags(program_flag_type(program_flags)), application_flags(application_flag_type(application_flags)),
93 fast_load_area_offset(0), fast_load_area_length(0)
94 {
95 }
96
97 std::shared_ptr<NEFormat> SimulateLinker(compatibility_type compatibility);
98
99 static std::shared_ptr<NEFormat> CreateConsoleApplication(system_type system = Windows);
100
101 static std::shared_ptr<NEFormat> CreateGUIApplication(system_type system = Windows);
102
103 static std::shared_ptr<NEFormat> CreateLibraryModule(system_type system = Windows);
104
105 class Entry
106 {
107 public:
108 enum entry_type
109 {
110 Unused,
111 Fixed,
112 Movable,
113 };
114 entry_type type = Unused;
115 uint8_t segment = 0;
116 enum flag_type
117 {
118 Exported = 1,
119 SharedData = 2,
120 };
121 flag_type flags = flag_type(0);
122 uint16_t offset = 0;
123
124 enum
125 {
126 WordCountShift = 3,
127
128 INT_3Fh = 0x3FCD,
129 };
130
131 Entry()
132 {
133 }
134
135 Entry(unsigned type, uint8_t segment, unsigned flags, uint16_t offset)
136 : type((entry_type)type), segment(segment), flags((flag_type)flags), offset(offset)
137 {
138 }
139
140 offset_t GetEntrySize() const;
141
142 uint8_t GetIndicatorByte() const;
143
144 void WriteEntry(Linker::Writer& wr);
145 };
146
148 {
149 public:
150 std::shared_ptr<Linker::Segment> image;
151 offset_t data_offset = 0;
152 enum flag_type
153 {
154 Data = 1, Code = 0,
155 Allocated = 2,
156 Loaded = 4, /* RealMode = 4 */ /* TODO */
157 Iterated = 8, /* TODO */
158 Movable = 0x10, Fixed = 0,
159 Shareable = 0x20,
160 Preload = 0x40, LoadOnCall = 0,
161 ExecuteOnly = 0x80, ReadOnly = 0x80|Data,
162 Relocations = 0x0100,
163 DebugInfo = 0x0200,
164 Discardable = 0x1000,
165 };
166 flag_type flags;
167 uint16_t movable_entry_index = 0; /* for movable segments, each relocation targetting it needs one and only one entry */
168
169 Segment(std::shared_ptr<Linker::Segment> segment, unsigned flags)
170 : image(segment), flags((flag_type)flags)
171 {
172 }
173
174 enum
175 {
176 PrivilegeLevelShift = 10,
177 };
178
180 {
181 public:
182 enum source_type
183 {
184 Offset8 = 0,
185 Selector16 = 2,
186 Pointer32 = 3,
187 Offset16 = 5,
188 Pointer48 = 11,
189 Offset32 = 13,
190 };
191 source_type type = source_type(0);
192 enum flag_type
193 {
194 Internal = 0,
195 ImportOrdinal = 1,
196 ImportName = 2,
197 OSFixup = 3,
198 Additive = 4,
199 };
200 flag_type flags = flag_type(0);
201 uint16_t offset = 0;
202 union
203 {
204 uint16_t module;
205 uint8_t segment;
206 };
207 enum
208 {
209 FIARQQ = 1, FJARQQ = 1,
210 FISRQQ = 2, FJSRQQ = 2,
211 FICRQQ = 3, FJCRQQ = 3,
212 FIERQQ = 4,
213 FIDRQQ = 5,
214 FIWRQQ = 6,
215 };
216 uint16_t target = 0;
217 Relocation()
218 : module(0)
219 {
220 }
221
222 Relocation(unsigned type, unsigned flags, uint16_t offset, uint16_t module, uint16_t target)
223 : type((source_type)type), flags((flag_type)flags), offset(offset), module(module), target(target)
224 {
225 }
226
227 static source_type GetType(Linker::Relocation& rel);
228 };
229 std::map<uint16_t, Relocation> relocations;
230
231 void AddRelocation(const Relocation& rel);
232 };
233
234 struct Name
235 {
236 public:
237 std::string name;
238 uint16_t ordinal = 0;
239 };
240
242 {
243 public:
244 /* TODO */
245 };
246
248 struct version
249 {
250 uint8_t major, minor;
251 };
252 version linker_version{1, 0}, windows_version{0, 0};
253
254 uint16_t automatic_data = 0;
255 uint16_t heap_size = 0, stack_size = 0;
256 uint16_t ss = 0, sp = 0, cs = 0, ip = 0;
257 uint16_t sector_shift = 9;
258
259 uint32_t segment_table_offset = 0;
260 uint32_t resource_table_offset = 0;
261 uint32_t resident_name_table_offset = 0;
262 uint32_t module_reference_table_offset = 0;
263 uint32_t imported_names_table_offset = 0;
264 uint32_t entry_table_offset = 0;
265 uint32_t entry_table_length = 0;
266 uint16_t movable_entry_count = 0;
267 uint32_t nonresident_name_table_length = 0;
268 uint32_t nonresident_name_table_offset = 0;
269 union
270 {
271 /* Windows */
272 uint16_t fast_load_area_offset;
273 /* OS/2 ? */
274 uint16_t return_thunks_offset;
275 };
276 union
277 {
278 /* Windows */
279 uint16_t fast_load_area_length;
280 /* OS/2 ? */
281 uint16_t segment_reference_thunks_offset;
282 };
283 uint16_t code_swap_area_length = 0;
284
285 std::shared_ptr<Linker::Segment> stack, heap;
286 std::vector<Segment> segments;
287 std::map<std::shared_ptr<Linker::Segment>, size_t> segment_index;
288 std::vector<Resource> resources;
289 std::vector<Name> resident_names, nonresident_names;
290 std::vector<uint16_t> module_references;
291 std::map<std::string, uint16_t> module_reference_offsets;
292 std::vector<std::string> imported_names;
293 std::map<std::string, uint16_t> imported_name_offsets;
294 uint16_t imported_names_length = 0;
295
296 std::vector<Entry> entries;
297
298 /*std::string stub_file;*/
299 std::string module_name;
300 std::string program_name;
301
302 bool option_capitalize_names = false; /* TODO: parametrize */
303 enum memory_model_t
304 {
305 MODEL_SMALL,
306 MODEL_LARGE,
307 };
308 memory_model_t memory_model = MODEL_SMALL;
309
310 unsigned GetCodeSegmentFlags() const;
311 unsigned GetDataSegmentFlags() const;
312 void AddSegment(const Segment& segment);
313 uint16_t FetchModule(std::string name);
314 uint16_t FetchImportedName(std::string name);
315 std::string MakeProcedureName(std::string name);
316 uint16_t MakeEntry(Linker::Position value);
317 uint16_t MakeEntry(uint16_t ordinal, Linker::Position value);
318 uint8_t CountBundles(size_t entry_index);
319
320 using LinkerManager::SetLinkScript;
321 void SetModel(std::string model) override;
322 void SetOptions(std::map<std::string, std::string>& options) override;
323 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
324 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
325 void Link(Linker::Module& module);
326 void ProcessModule(Linker::Module& module) override;
327 void CalculateValues() override;
328 void WriteFile(Linker::Writer& wr) override;
329 void GenerateFile(std::string filename, Linker::Module& module) override;
330 std::string GetDefaultExtension(Linker::Module& module, std::string filename) override;
331 };
332}
333
334#endif /* NEEXE_H */
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
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, encapsulating functionality needed to export binary data.
Definition writer.h:15
Definition mzexe.h:279
Definition neexe.h:106
Definition neexe.h:242
Definition neexe.h:148
NE .EXE new executable file format.
Definition neexe.h:23
void WriteFile(Linker::Writer &wr) override
Stores data in memory to file.
Definition neexe.cc:760
std::string GetDefaultExtension(Linker::Module &module, std::string filename) override
Appends a default extension to the filename.
Definition neexe.cc:912
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition neexe.cc:319
bool FormatSupportsSegmentation() const override
Whether the format supports multiple segments.
Definition neexe.cc:12
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition neexe.cc:663
bool FormatIs16bit() const override
Whether the format is 16-bit or not.
Definition neexe.cc:17
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition neexe.cc:7
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition neexe.cc:22
void SetModel(std::string model) override
Sets the way memory is organized, typically modifying a built-in script.
Definition neexe.cc:879
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition neexe.cc:896
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition neexe.cc:453
Definition neexe.h:235
Version number.
Definition neexe.h:249