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