RetroLinker
Linker for several 8-bit, 16-bit and 32-bit formats
Loading...
Searching...
No Matches
leexe.h
1#ifndef LEEXE_H
2#define LEEXE_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{
24 class LEFormat : public virtual Linker::OutputFormat, public Linker::LinkerManager, protected Microsoft::MZStubWriter, public std::enable_shared_from_this<LEFormat>
25 {
26 public:
27 void ReadFile(Linker::Reader& rd) override;
28
29 bool FormatSupportsSegmentation() const override;
30
31 bool FormatSupportsLibraries() const override;
32
33 unsigned FormatAdditionalSectionFlags(std::string section_name) const override;
34
35 ::EndianType endiantype = ::LittleEndian;
36
37 enum system_type
38 {
39 OS2 = 1, /* OS/2 2.0+ */
40 Windows, /* Windows 386 */
41 MSDOS4, /* ? */
42 Windows386, /* ? */
43
44 DOS4G = -1, /* not a real system type */
45 } system;
46
47 bool IsOS2() const;
48
49 enum
50 {
51 PreProcessInitialization = 0x00000004,
52 NoInternalFixup = 0x00000010,
53 NoExternalFixup = 0x00000020,
54 FullScreen = 0x00000100,
55 GUIAware = 0x00000200,
56 GUI = 0x00000300,
57 ErrorInImage = 0x00002000,
58 Library = 0x00008000,
59 ProtectedMemoryLibrary = 0x00018000,
60 PhysicalDriver = 0x00020000,
61 VirtualDriver = 0x00028000,
62 PerProcessTermination = 0x40000000,
63 };
64 uint32_t module_flags;
65
66 bool IsLibrary() const;
67
68 bool IsDriver() const;
69
70 bool extended_format;
71
72 /* https://faydoc.tripod.com/formats/exe-LE.htm */
73 enum cpu_type
74 {
75 I286 = 0x01,
76 I386 = 0x02, /* only value used */
77 I486 = 0x03,
78 I860_N10 = 0x20,
79 I860_N11 = 0x21,
80 MIPS1 = 0x40,
81 MIPS2 = 0x41,
82 MIPS3 = 0x42,
83 };
84 cpu_type cpu = I386;
85
86 enum compatibility_type
87 {
88 CompatibleNone,
89 CompatibleWatcom,
90 CompatibleMicrosoft, /* TODO??? */
91 CompatibleGNU, /* TODO: emx extender */
92 };
93 compatibility_type compatibility = CompatibleNone;
94
95 //protected:
96 LEFormat(unsigned system, unsigned module_flags, bool extended_format)
97 : system((system_type)system), module_flags(module_flags), extended_format(extended_format), last_page_size(0)
98 {
99 }
100
101 public:
102 static std::shared_ptr<LEFormat> CreateConsoleApplication(system_type system = OS2);
103
104 static std::shared_ptr<LEFormat> CreateGUIApplication(system_type system = OS2);
105
106 static std::shared_ptr<LEFormat> CreateLibraryModule(system_type system = OS2);
107
108 std::shared_ptr<LEFormat> SimulateLinker(compatibility_type compatibility);
109
110 /*std::string stub_file;*/
111 std::string program_name, module_name;
112
113 uint32_t page_count = 0;
114 uint32_t eip_object = 0, eip_value = 0, esp_object = 0, esp_value = 0;
115 union
116 {
117 uint32_t last_page_size; /* LE */
118 uint32_t page_offset_shift; /* LX */
119 };
120 uint32_t fixup_section_size = 0, loader_section_size = 0;
121 uint32_t object_table_offset = 0, object_page_table_offset = 0, object_iterated_pages_offset = 0;
122 uint32_t resource_table_offset = 0, resource_table_entry_count = 0, resident_name_table_offset = 0;
123 uint32_t entry_table_offset = 0, fixup_page_table_offset = 0, fixup_record_table_offset = 0;
124 uint32_t imported_module_table_offset = 0, imported_procedure_table_offset = 0;
125 uint32_t data_pages_offset = 0, nonresident_name_table_offset = 0, nonresident_name_table_size = 0;
126 uint32_t automatic_data = 0, stack_size = 0, heap_size = 0;
127
128 class Object
129 {
130 public:
131 std::shared_ptr<Linker::Segment> image;
132 enum flag_type
133 {
134 Readable = 0x0001,
135 Writable = 0x0002,
136 Execable = 0x0004,
137 Resource = 0x0008,
138 Discardable = 0x0010,
139 Shared = 0x0020,
140 PreloadPages = 0x0040,
141 InvalidPages = 0x0080,
142 ZeroFilledPages = 0x0100,
143 Resident = 0x0200,
144 ResidentContiguous = 0x0300,
145 ResidentLongLockable = 0x0400,
146 Alias16_16 = 0x1000, /* x86 */
147 BigSegment = 0x2000, /* x86 */
148 Conforming = 0x4000, /* x86 */
149 IOPrivilege = 0x8000, /* x86 */
150 };
151 flag_type flags;
152 uint32_t page_table_index = 0;
153 uint32_t page_entry_count = 0;
154 uint32_t data_pages_offset = 0;
155
156 Object(std::shared_ptr<Linker::Segment> segment, unsigned flags)
157 : image(segment), flags((flag_type)flags)
158 {
159 }
160 };
161
162 void AddRelocation(Object& object, unsigned type, unsigned flags, size_t offset, uint16_t module, uint32_t target = 0, uint32_t addition = 0);
163
164 class Page
165 {
166 public:
167 union
168 {
169 struct
170 {
171 uint32_t fixup_table_index;
172 uint8_t type;
173 } le;
174 struct
175 {
176 uint32_t offset;
177 uint16_t size;
178 uint16_t flags;
179 } lx;
180 };
181
182 enum
183 {
184 /* LE types */
185 NoRelocations = 0,
186 Relocations = 3,
187
188 /* LX flags */
189 Preload = 0,
190 Iterated,
191 Invalid,
192 ZeroFilled,
193 Range,
194 };
195
196 uint32_t fixup_offset = 0;
197
199 {
200 public:
201 enum source_type
202 {
203 Offset8 = 0,
204 Selector16 = 2,
205 Pointer32 = 3,
206 Offset16 = 5,
207 Pointer48 = 6,
208 Offset32 = 7,
209 Relative32 = 8,
210
211 SourceTypeMask = 0x0F,
212
213 Alias = 0x10,
214 SourceList = 0x20,
215 };
216 source_type type = source_type(0);
217 enum flag_type
218 {
219 Internal = 0,
220 ImportOrdinal = 1,
221 ImportName = 2,
222 Entry = 3,
223
224 FlagTypeMask = 3,
225
226 Additive = 4,
227 Target32 = 0x10,
228 Additive32 = 0x20,
229 Module16 = 0x40,
230 Ordinal8 = 0x80,
231 };
232 flag_type flags = flag_type(0);
233 uint16_t module = 0;
234 uint32_t target = 0;
235 uint32_t addition = 0;
236
237 Relocation()
238 : Writer(::LittleEndian)
239 {
240 }
241
242 Relocation(unsigned type, unsigned flags, uint16_t offset, uint16_t module, uint32_t target = 0, uint32_t addition = 0)
243 : Writer(::LittleEndian), type((source_type)type), flags((flag_type)flags), module(module), target(target), addition(addition)
244 {
245 sources.push_back(offset);
246 }
247
248 static source_type GetType(Linker::Relocation& rel);
249
250 bool IsExternal() const;
251
252 bool IsSelectorOrOffset() const;
253
254 bool ComesBefore() const;
255
256 size_t GetSourceSize() const;
257
258 private:
259 std::vector<uint16_t> sources;
260
261 public:
262 /* do not call this */
263 void DecrementSingleSourceOffset(size_t amount);
264
265 bool IsSelector() const;
266 bool IsSourceList() const;
267 bool IsAdditive() const;
268 size_t GetTargetSize() const;
269 size_t GetAdditiveSize() const;
270 size_t GetModuleSize() const;
271 size_t GetOrdinalSize() const;
272
273 void CalculateSizes(compatibility_type compatibility);
274
275 size_t GetSize() const;
276
277 void WriteFile(Linker::Writer& wr, compatibility_type compatibility);
278 };
279 std::map<uint16_t, Relocation> relocations;
280
281 Page()
282 : lx{0, 0, 0}
283 {
284 }
285
286 protected:
287 Page(uint16_t fixup_table_index, uint8_t type)
288 : le{fixup_table_index, type}
289 {
290 }
291
292 Page(uint32_t offset, uint16_t size, uint8_t flags)
293 : lx{offset, size, flags}
294 {
295 }
296
297 public:
298 static Page LEPage(uint16_t fixup_table_index, uint8_t type);
299
300 static Page LXPage(uint32_t offset, uint16_t size, uint8_t flags);
301 };
302
304 {
305 /* TODO */
306 };
307
308 struct Name
309 {
310 public:
311 std::string name;
312 uint16_t ordinal;
313 };
314
315 class Entry : public Linker::Writer
316 {
317 public:
318 enum entry_type
319 {
320 Unused,
321 Entry16,
322 CallGate286,
323 Entry32,
324 Forwarder,
325 };
326 entry_type type = Unused;
327 uint16_t object = 0;
328 enum flag_type
329 {
330 Exported = 1,
331 SharedData = 2,
332 };
333 flag_type flags = flag_type(0);
334 uint32_t offset = 0;
335
336 Entry()
337 : Writer(::LittleEndian)
338 {
339 }
340
341 Entry(unsigned type, uint16_t object, unsigned flags, uint32_t offset)
342 : Writer(::LittleEndian), type((entry_type)type), object(object), flags((flag_type)flags), offset(offset)
343 {
344 }
345
346 bool SameBundle(const Entry& other) const;
347
348 offset_t GetEntryHeadSize() const;
349
350 offset_t GetEntryBodySize() const;
351
352 void WriteEntryHead(Linker::Writer& wr);
353
354 void WriteEntryBody(Linker::Writer& wr);
355 };
356
357 static const uint32_t page_size = 0x1000;
358
359 std::shared_ptr<Linker::Segment> stack, heap;
360 std::vector<Object> objects;
361 std::map<std::shared_ptr<Linker::Segment>, size_t> object_index;
362 std::vector<Page> pages;
363 std::vector<Resource> resources;
364 std::vector<Name> resident_names, nonresident_names;
365 std::vector<Entry> entries;
366 std::vector<std::string> imported_modules, imported_procedures;
367 std::map<std::string, uint32_t> imported_procedure_name_offsets;
368 offset_t imported_procedure_names_length = 0;
369
370 unsigned GetDefaultObjectFlags() const;
371 void AddObject(const Object& object);
372 uint16_t FetchImportedModuleName(std::string name);
373 uint16_t FetchImportedProcedureName(std::string name);
374 uint16_t MakeEntry(Linker::Position value);
375 uint16_t MakeEntry(uint16_t index, Linker::Position value);
376 uint8_t CountBundles(size_t entry_index);
377
378 using LinkerManager::SetLinkScript;
379 void SetOptions(std::map<std::string, std::string>& options) override;
380 void OnNewSegment(std::shared_ptr<Linker::Segment> segment) override;
381 std::unique_ptr<Script::List> GetScript(Linker::Module& module);
382 void Link(Linker::Module& module);
383 void ProcessModule(Linker::Module& module) override;
384 void CalculateValues() override;
385 void WriteFile(Linker::Writer& wr) override;
386 void GenerateFile(std::string filename, Linker::Module& module) override;
387 std::string GetDefaultExtension(Linker::Module& module, std::string filename) override;
388
389 };
390
391}
392
393#endif /* LEEXE_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 leexe.h:316
Definition leexe.h:129
Definition leexe.h:165
Definition leexe.h:304
LE/LX .EXE linear executable file format.
Definition leexe.h:25
void CalculateValues() override
Intermediate step between processing module and generating output file to set up headers and manageme...
Definition leexe.cc:885
void WriteFile(Linker::Writer &wr) override
Stores data in memory to file.
Definition leexe.cc:1031
void SetOptions(std::map< std::string, std::string > &options) override
Passes command line parameters as settings over to format object.
Definition leexe.cc:562
std::string GetDefaultExtension(Linker::Module &module, std::string filename) override
Appends a default extension to the filename.
Definition leexe.cc:1275
void GenerateFile(std::string filename, Linker::Module &module) override
The main function that handles processing, calculating and generating the final image.
Definition leexe.cc:1259
void ReadFile(Linker::Reader &rd) override
Loads file into memory.
Definition leexe.cc:7
bool FormatSupportsSegmentation() const override
Whether the format supports multiple segments.
Definition leexe.cc:12
void ProcessModule(Linker::Module &module) override
Processes the module object and initializes format fields.
Definition leexe.cc:646
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 leexe.cc:568
bool FormatSupportsLibraries() const override
Whether the format supports libraries.
Definition leexe.cc:17
Definition mzexe.h:279
Definition leexe.h:309