Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
8097 maxcodehac 4
    Copyright (c) 2018-2020, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE PE32;
9
 
7983 leency 10
IMPORT BIN, LISTS, UTILS, WR := WRITER, CHL := CHUNKLISTS;
7597 akron1 11
 
12
 
13
CONST
14
 
15
    SIZE_OF_DWORD = 4;
16
    SIZE_OF_WORD  = 2;
17
 
18
    SIZE_OF_IMAGE_EXPORT_DIRECTORY = 40;
19
 
20
    IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
21
 
22
    IMAGE_SIZEOF_SHORT_NAME = 8;
23
 
24
    SIZE_OF_IMAGE_FILE_HEADER* = 20;
25
 
26
    SIZE_OF_IMAGE_SECTION_HEADER* = 40;
27
 
28
    (* SectionHeader.Characteristics *)
29
 
30
    SHC_text  = 060000020H;
7696 akron1 31
    SHC_data  = 040000040H;
32
    SHC_bss   = 0C0000080H;
7597 akron1 33
 
34
    SectionAlignment = 1000H;
35
    FileAlignment    =  200H;
36
 
37
 
38
TYPE
39
 
40
    WORD  = WCHAR;
41
    DWORD = INTEGER;
42
 
43
    NAME* = ARRAY IMAGE_SIZEOF_SHORT_NAME OF CHAR;
44
 
45
 
46
    IMAGE_DATA_DIRECTORY = RECORD
47
 
48
        VirtualAddress:  DWORD;
49
        Size:            DWORD
50
 
51
    END;
52
 
53
 
54
    IMAGE_OPTIONAL_HEADER = RECORD
55
 
56
        Magic:                        WORD;
57
        MajorLinkerVersion:           BYTE;
58
        MinorLinkerVersion:           BYTE;
59
        SizeOfCode:                   DWORD;
60
        SizeOfInitializedData:        DWORD;
61
        SizeOfUninitializedData:      DWORD;
62
        AddressOfEntryPoint:          DWORD;
63
        BaseOfCode:                   DWORD;
64
        BaseOfData:                   DWORD;
65
        ImageBase:                    DWORD;
66
        SectionAlignment:             DWORD;
67
        FileAlignment:                DWORD;
68
        MajorOperatingSystemVersion:  WORD;
69
        MinorOperatingSystemVersion:  WORD;
70
        MajorImageVersion:            WORD;
71
        MinorImageVersion:            WORD;
72
        MajorSubsystemVersion:        WORD;
73
        MinorSubsystemVersion:        WORD;
74
        Win32VersionValue:            DWORD;
75
        SizeOfImage:                  DWORD;
76
        SizeOfHeaders:                DWORD;
77
        CheckSum:                     DWORD;
78
        Subsystem:                    WORD;
79
        DllCharacteristics:           WORD;
80
        SizeOfStackReserve:           DWORD;
81
        SizeOfStackCommit:            DWORD;
82
        SizeOfHeapReserve:            DWORD;
83
        SizeOfHeapCommit:             DWORD;
84
        LoaderFlags:                  DWORD;
85
        NumberOfRvaAndSizes:          DWORD;
86
 
87
        DataDirectory: ARRAY IMAGE_NUMBEROF_DIRECTORY_ENTRIES OF IMAGE_DATA_DIRECTORY
88
 
89
    END;
90
 
91
 
92
    IMAGE_FILE_HEADER* = RECORD
93
 
94
        Machine*:               WORD;
95
        NumberOfSections*:      WORD;
96
        TimeDateStamp*:         DWORD;
97
        PointerToSymbolTable*:  DWORD;
98
        NumberOfSymbols*:       DWORD;
99
        SizeOfOptionalHeader*:  WORD;
100
        Characteristics*:       WORD
101
 
102
    END;
103
 
104
 
105
    IMAGE_SECTION_HEADER* = RECORD
106
 
107
        Name*: NAME;
108
 
109
        VirtualSize*,
110
        VirtualAddress*,
111
        SizeOfRawData*,
112
        PointerToRawData*,
113
        PointerToRelocations*,
114
        PointerToLinenumbers*:   DWORD;
115
 
116
        NumberOfRelocations*,
117
        NumberOfLinenumbers*:    WORD;
118
 
119
        Characteristics*:        DWORD
120
 
121
    END;
122
 
123
 
124
    IMAGE_EXPORT_DIRECTORY = RECORD
125
 
126
        Characteristics:       DWORD;
127
        TimeDateStamp:         DWORD;
128
        MajorVersion:          WORD;
129
        MinorVersion:          WORD;
130
        Name,
131
        Base,
132
        NumberOfFunctions,
133
        NumberOfNames,
134
        AddressOfFunctions,
135
        AddressOfNames,
136
        AddressOfNameOrdinals: DWORD
137
 
138
    END;
139
 
140
 
8097 maxcodehac 141
    VIRTUAL_ADDR* = RECORD
7597 akron1 142
 
8097 maxcodehac 143
        Code*, Data*, Bss*, Import*: INTEGER
7597 akron1 144
 
145
    END;
146
 
147
 
8097 maxcodehac 148
VAR
7597 akron1 149
 
8097 maxcodehac 150
    Signature:       ARRAY 4 OF BYTE;
151
    FileHeader:      IMAGE_FILE_HEADER;
152
    OptionalHeader:  IMAGE_OPTIONAL_HEADER;
7597 akron1 153
 
154
    msdos:           ARRAY 128 OF BYTE;
155
    SectionHeaders:  ARRAY 16 OF IMAGE_SECTION_HEADER;
156
    libcnt:          INTEGER;
7983 leency 157
    SizeOfWord:      INTEGER;
7597 akron1 158
 
159
 
8097 maxcodehac 160
PROCEDURE Export (program: BIN.PROGRAM; name: INTEGER; VAR ExportDir: IMAGE_EXPORT_DIRECTORY): INTEGER;
7597 akron1 161
BEGIN
162
 
163
    ExportDir.Characteristics        :=  0;
8097 maxcodehac 164
    ExportDir.TimeDateStamp          :=  FileHeader.TimeDateStamp;
7597 akron1 165
    ExportDir.MajorVersion           :=  0X;
166
    ExportDir.MinorVersion           :=  0X;
8097 maxcodehac 167
    ExportDir.Name                   :=  name;
7597 akron1 168
    ExportDir.Base                   :=  0;
169
    ExportDir.NumberOfFunctions      :=  LISTS.count(program.exp_list);
170
    ExportDir.NumberOfNames          :=  ExportDir.NumberOfFunctions;
171
    ExportDir.AddressOfFunctions     :=  SIZE_OF_IMAGE_EXPORT_DIRECTORY;
172
    ExportDir.AddressOfNames         :=  ExportDir.AddressOfFunctions + ExportDir.NumberOfFunctions * SIZE_OF_DWORD;
173
    ExportDir.AddressOfNameOrdinals  :=  ExportDir.AddressOfNames     + ExportDir.NumberOfFunctions * SIZE_OF_DWORD
174
 
175
    RETURN SIZE_OF_IMAGE_EXPORT_DIRECTORY + ExportDir.NumberOfFunctions * (2 * SIZE_OF_DWORD + SIZE_OF_WORD)
176
END Export;
177
 
178
 
179
PROCEDURE GetProcCount (lib: BIN.IMPRT): INTEGER;
180
VAR
8097 maxcodehac 181
    imp: BIN.IMPRT;
182
    res: INTEGER;
7597 akron1 183
 
184
BEGIN
185
    res := 0;
8097 maxcodehac 186
    imp := lib.next(BIN.IMPRT);
187
    WHILE (imp # NIL) & (imp.label # 0) DO
7597 akron1 188
        INC(res);
8097 maxcodehac 189
        imp := imp.next(BIN.IMPRT)
7597 akron1 190
    END
191
 
192
    RETURN res
193
END GetProcCount;
194
 
195
 
196
PROCEDURE GetImportSize (imp_list: LISTS.LIST): INTEGER;
197
VAR
8097 maxcodehac 198
    imp: BIN.IMPRT;
7597 akron1 199
    proccnt: INTEGER;
200
    procoffs: INTEGER;
201
    OriginalCurrentThunk,
202
    CurrentThunk: INTEGER;
203
 
204
BEGIN
205
    libcnt  := 0;
206
    proccnt := 0;
8097 maxcodehac 207
    imp  := imp_list.first(BIN.IMPRT);
208
    WHILE imp # NIL DO
209
        IF imp.label = 0 THEN
7597 akron1 210
            INC(libcnt)
211
        ELSE
212
            INC(proccnt)
213
        END;
8097 maxcodehac 214
        imp := imp.next(BIN.IMPRT)
7597 akron1 215
    END;
216
 
217
    procoffs := 0;
218
 
8097 maxcodehac 219
    imp  := imp_list.first(BIN.IMPRT);
220
    WHILE imp # NIL DO
221
        IF imp.label = 0 THEN
222
            imp.OriginalFirstThunk := procoffs;
223
            imp.FirstThunk := procoffs + (GetProcCount(imp) + 1);
224
            OriginalCurrentThunk := imp.OriginalFirstThunk;
225
            CurrentThunk := imp.FirstThunk;
226
            INC(procoffs, (GetProcCount(imp) + 1) * 2)
7597 akron1 227
        ELSE
8097 maxcodehac 228
            imp.OriginalFirstThunk := OriginalCurrentThunk;
229
            imp.FirstThunk := CurrentThunk;
7597 akron1 230
            INC(OriginalCurrentThunk);
231
            INC(CurrentThunk)
232
        END;
8097 maxcodehac 233
        imp := imp.next(BIN.IMPRT)
7597 akron1 234
    END
235
 
7983 leency 236
    RETURN (libcnt + 1) * 5 * SIZE_OF_DWORD + (proccnt + libcnt) * 2 * SizeOfWord
7597 akron1 237
END GetImportSize;
238
 
239
 
8097 maxcodehac 240
PROCEDURE fixup* (program: BIN.PROGRAM; Address: VIRTUAL_ADDR; amd64: BOOLEAN);
7597 akron1 241
VAR
7983 leency 242
    reloc: BIN.RELOC;
243
    iproc: BIN.IMPRT;
244
    code:  CHL.BYTELIST;
8097 maxcodehac 245
    L, delta, delta0, AdrImp, offset: INTEGER;
7597 akron1 246
 
247
BEGIN
248
    AdrImp := Address.Import + (libcnt + 1) * 5 * SIZE_OF_DWORD;
7983 leency 249
    code := program.code;
250
    reloc := program.rel_list.first(BIN.RELOC);
8097 maxcodehac 251
    delta0 := 3 - 7 * ORD(amd64) - Address.Code;
7597 akron1 252
 
253
    WHILE reloc # NIL DO
254
 
8097 maxcodehac 255
        offset := reloc.offset;
256
        L := BIN.get32le(code, offset);
257
        delta := delta0 - offset;
7597 akron1 258
 
259
        CASE reloc.opcode OF
260
        |BIN.PICDATA:
8097 maxcodehac 261
            INC(delta, L + Address.Data)
7597 akron1 262
 
263
        |BIN.PICCODE:
8097 maxcodehac 264
            INC(delta, BIN.GetLabel(program, L) + Address.Code)
7597 akron1 265
 
266
        |BIN.PICBSS:
8097 maxcodehac 267
            INC(delta, L + Address.Bss)
7597 akron1 268
 
269
        |BIN.PICIMP:
8097 maxcodehac 270
            iproc := BIN.GetIProc(program, L);
271
            INC(delta, iproc.FirstThunk * SizeOfWord + AdrImp)
7597 akron1 272
        END;
8097 maxcodehac 273
        BIN.put32le(code, offset, delta);
7597 akron1 274
 
275
        reloc := reloc.next(BIN.RELOC)
276
    END
277
END fixup;
278
 
279
 
8097 maxcodehac 280
PROCEDURE WriteWord (w: WORD);
7597 akron1 281
BEGIN
8097 maxcodehac 282
    WR.Write16LE(ORD(w))
7597 akron1 283
END WriteWord;
284
 
285
 
8097 maxcodehac 286
PROCEDURE WriteName* (name: NAME);
7597 akron1 287
VAR
288
    i, nameLen: INTEGER;
289
 
290
BEGIN
291
    nameLen := LENGTH(name);
292
 
293
    FOR i := 0 TO nameLen - 1 DO
8097 maxcodehac 294
        WR.WriteByte(ORD(name[i]))
7597 akron1 295
    END;
296
 
297
    i := LEN(name) - nameLen;
298
    WHILE i > 0 DO
8097 maxcodehac 299
        WR.WriteByte(0);
7597 akron1 300
        DEC(i)
301
    END
302
 
303
END WriteName;
304
 
305
 
8097 maxcodehac 306
PROCEDURE WriteSectionHeader* (h: IMAGE_SECTION_HEADER);
7597 akron1 307
VAR
308
    i, nameLen: INTEGER;
309
 
310
BEGIN
311
    nameLen := LENGTH(h.Name);
312
 
313
    FOR i := 0 TO nameLen - 1 DO
8097 maxcodehac 314
        WR.WriteByte(ORD(h.Name[i]))
7597 akron1 315
    END;
316
 
317
    i := LEN(h.Name) - nameLen;
318
    WHILE i > 0 DO
8097 maxcodehac 319
        WR.WriteByte(0);
7597 akron1 320
        DEC(i)
321
    END;
322
 
8097 maxcodehac 323
    WR.Write32LE(h.VirtualSize);
324
    WR.Write32LE(h.VirtualAddress);
325
    WR.Write32LE(h.SizeOfRawData);
326
    WR.Write32LE(h.PointerToRawData);
327
    WR.Write32LE(h.PointerToRelocations);
328
    WR.Write32LE(h.PointerToLinenumbers);
7597 akron1 329
 
8097 maxcodehac 330
    WriteWord(h.NumberOfRelocations);
331
    WriteWord(h.NumberOfLinenumbers);
7597 akron1 332
 
8097 maxcodehac 333
    WR.Write32LE(h.Characteristics)
7597 akron1 334
END WriteSectionHeader;
335
 
336
 
8097 maxcodehac 337
PROCEDURE WriteFileHeader* (h: IMAGE_FILE_HEADER);
7597 akron1 338
BEGIN
8097 maxcodehac 339
    WriteWord(h.Machine);
340
    WriteWord(h.NumberOfSections);
7597 akron1 341
 
8097 maxcodehac 342
    WR.Write32LE(h.TimeDateStamp);
343
    WR.Write32LE(h.PointerToSymbolTable);
344
    WR.Write32LE(h.NumberOfSymbols);
7597 akron1 345
 
8097 maxcodehac 346
    WriteWord(h.SizeOfOptionalHeader);
347
    WriteWord(h.Characteristics)
7597 akron1 348
END WriteFileHeader;
349
 
350
 
7696 akron1 351
PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; console, dll, amd64: BOOLEAN);
7597 akron1 352
VAR
8097 maxcodehac 353
    i, n, temp: INTEGER;
7597 akron1 354
 
355
    Size: RECORD
356
 
8097 maxcodehac 357
        Code, Data, Bss, Import, Reloc, Export: INTEGER
7597 akron1 358
 
359
    END;
360
 
7696 akron1 361
    BaseAddress: INTEGER;
362
 
7597 akron1 363
    Address: VIRTUAL_ADDR;
364
 
8097 maxcodehac 365
    _import:      BIN.IMPRT;
7597 akron1 366
    ImportTable:  CHL.INTLIST;
367
 
368
    ExportDir:  IMAGE_EXPORT_DIRECTORY;
369
    export:     BIN.EXPRT;
370
 
371
 
8097 maxcodehac 372
    PROCEDURE WriteExportDir (e: IMAGE_EXPORT_DIRECTORY);
7597 akron1 373
    BEGIN
8097 maxcodehac 374
        WR.Write32LE(e.Characteristics);
375
        WR.Write32LE(e.TimeDateStamp);
7597 akron1 376
 
8097 maxcodehac 377
        WriteWord(e.MajorVersion);
378
        WriteWord(e.MinorVersion);
7597 akron1 379
 
8097 maxcodehac 380
        WR.Write32LE(e.Name);
381
        WR.Write32LE(e.Base);
382
        WR.Write32LE(e.NumberOfFunctions);
383
        WR.Write32LE(e.NumberOfNames);
384
        WR.Write32LE(e.AddressOfFunctions);
385
        WR.Write32LE(e.AddressOfNames);
386
        WR.Write32LE(e.AddressOfNameOrdinals)
7597 akron1 387
    END WriteExportDir;
388
 
389
 
8097 maxcodehac 390
    PROCEDURE WriteOptHeader (h: IMAGE_OPTIONAL_HEADER; amd64: BOOLEAN);
7597 akron1 391
    VAR
392
        i: INTEGER;
393
 
394
    BEGIN
8097 maxcodehac 395
        WriteWord(h.Magic);
7597 akron1 396
 
8097 maxcodehac 397
        WR.WriteByte(h.MajorLinkerVersion);
398
        WR.WriteByte(h.MinorLinkerVersion);
7597 akron1 399
 
8097 maxcodehac 400
        WR.Write32LE(h.SizeOfCode);
401
        WR.Write32LE(h.SizeOfInitializedData);
402
        WR.Write32LE(h.SizeOfUninitializedData);
403
        WR.Write32LE(h.AddressOfEntryPoint);
404
        WR.Write32LE(h.BaseOfCode);
7597 akron1 405
 
8097 maxcodehac 406
        IF amd64 THEN
407
            WR.Write64LE(h.ImageBase)
7597 akron1 408
        ELSE
8097 maxcodehac 409
            WR.Write32LE(h.BaseOfData);
410
            WR.Write32LE(h.ImageBase)
7597 akron1 411
        END;
412
 
8097 maxcodehac 413
        WR.Write32LE(h.SectionAlignment);
414
        WR.Write32LE(h.FileAlignment);
7597 akron1 415
 
8097 maxcodehac 416
        WriteWord(h.MajorOperatingSystemVersion);
417
        WriteWord(h.MinorOperatingSystemVersion);
418
        WriteWord(h.MajorImageVersion);
419
        WriteWord(h.MinorImageVersion);
420
        WriteWord(h.MajorSubsystemVersion);
421
        WriteWord(h.MinorSubsystemVersion);
7597 akron1 422
 
8097 maxcodehac 423
        WR.Write32LE(h.Win32VersionValue);
424
        WR.Write32LE(h.SizeOfImage);
425
        WR.Write32LE(h.SizeOfHeaders);
426
        WR.Write32LE(h.CheckSum);
7597 akron1 427
 
8097 maxcodehac 428
        WriteWord(h.Subsystem);
429
        WriteWord(h.DllCharacteristics);
7597 akron1 430
 
8097 maxcodehac 431
        IF amd64 THEN
432
            WR.Write64LE(h.SizeOfStackReserve);
433
            WR.Write64LE(h.SizeOfStackCommit);
434
            WR.Write64LE(h.SizeOfHeapReserve);
435
            WR.Write64LE(h.SizeOfHeapCommit)
7597 akron1 436
        ELSE
8097 maxcodehac 437
            WR.Write32LE(h.SizeOfStackReserve);
438
            WR.Write32LE(h.SizeOfStackCommit);
439
            WR.Write32LE(h.SizeOfHeapReserve);
440
            WR.Write32LE(h.SizeOfHeapCommit)
7597 akron1 441
        END;
442
 
8097 maxcodehac 443
        WR.Write32LE(h.LoaderFlags);
444
        WR.Write32LE(h.NumberOfRvaAndSizes);
7597 akron1 445
 
446
        FOR i := 0 TO LEN(h.DataDirectory) - 1 DO
8097 maxcodehac 447
            WR.Write32LE(h.DataDirectory[i].VirtualAddress);
448
            WR.Write32LE(h.DataDirectory[i].Size)
7597 akron1 449
        END
450
 
451
    END WriteOptHeader;
452
 
453
 
8097 maxcodehac 454
    PROCEDURE InitSection (VAR section: IMAGE_SECTION_HEADER; Name: NAME; VirtualSize: INTEGER; Characteristics: DWORD);
7597 akron1 455
    BEGIN
456
        section.Name                  :=  Name;
8097 maxcodehac 457
        section.VirtualSize           :=  VirtualSize;
458
        section.SizeOfRawData         :=  WR.align(VirtualSize, FileAlignment);
7597 akron1 459
        section.PointerToRelocations  :=  0;
460
        section.PointerToLinenumbers  :=  0;
461
        section.NumberOfRelocations   :=  0X;
462
        section.NumberOfLinenumbers   :=  0X;
463
        section.Characteristics       :=  Characteristics
464
    END InitSection;
465
 
466
 
467
BEGIN
8097 maxcodehac 468
    SizeOfWord := SIZE_OF_DWORD * (ORD(amd64) + 1);
7597 akron1 469
 
470
    Size.Code  := CHL.Length(program.code);
471
    Size.Data  := CHL.Length(program.data);
472
    Size.Bss   := program.bss;
473
 
7696 akron1 474
    IF dll THEN
475
        BaseAddress := 10000000H
476
    ELSE
477
        BaseAddress := 400000H
478
    END;
479
 
8097 maxcodehac 480
    Signature[0] := 50H;
481
    Signature[1] := 45H;
482
    Signature[2] := 0;
483
    Signature[3] := 0;
7597 akron1 484
 
485
    IF amd64 THEN
8097 maxcodehac 486
        FileHeader.Machine := 08664X
7597 akron1 487
    ELSE
8097 maxcodehac 488
        FileHeader.Machine := 014CX
7597 akron1 489
    END;
490
 
8097 maxcodehac 491
    FileHeader.NumberOfSections := WCHR(4 + ORD(dll));
7597 akron1 492
 
8097 maxcodehac 493
    FileHeader.TimeDateStamp         :=  UTILS.UnixTime();
494
    FileHeader.PointerToSymbolTable  :=  0H;
495
    FileHeader.NumberOfSymbols       :=  0H;
496
    FileHeader.SizeOfOptionalHeader  :=  WCHR(0E0H + 10H * ORD(amd64));
497
    FileHeader.Characteristics       :=  WCHR(010EH + (20H - 100H) * ORD(amd64) + 2000H * ORD(dll));
7597 akron1 498
 
8097 maxcodehac 499
    OptionalHeader.Magic                        :=  WCHR(010BH + 100H * ORD(amd64));
500
    OptionalHeader.MajorLinkerVersion           :=  UTILS.vMajor;
501
    OptionalHeader.MinorLinkerVersion           :=  UTILS.vMinor;
502
    OptionalHeader.SizeOfCode                   :=  WR.align(Size.Code, FileAlignment);
503
    OptionalHeader.SizeOfInitializedData        :=  0;
504
    OptionalHeader.SizeOfUninitializedData      :=  0;
505
    OptionalHeader.AddressOfEntryPoint          :=  SectionAlignment;
506
    OptionalHeader.BaseOfCode                   :=  SectionAlignment;
507
    OptionalHeader.BaseOfData                   :=  OptionalHeader.BaseOfCode + WR.align(Size.Code, SectionAlignment);
508
    OptionalHeader.ImageBase                    :=  BaseAddress;
509
    OptionalHeader.SectionAlignment             :=  SectionAlignment;
510
    OptionalHeader.FileAlignment                :=  FileAlignment;
511
    OptionalHeader.MajorOperatingSystemVersion  :=  1X;
512
    OptionalHeader.MinorOperatingSystemVersion  :=  0X;
513
    OptionalHeader.MajorImageVersion            :=  0X;
514
    OptionalHeader.MinorImageVersion            :=  0X;
515
    OptionalHeader.MajorSubsystemVersion        :=  4X;
516
    OptionalHeader.MinorSubsystemVersion        :=  0X;
517
    OptionalHeader.Win32VersionValue            :=  0H;
518
    OptionalHeader.SizeOfImage                  :=  SectionAlignment;
519
    OptionalHeader.SizeOfHeaders                :=  400H;
520
    OptionalHeader.CheckSum                     :=  0;
521
    OptionalHeader.Subsystem                    :=  WCHR((2 + ORD(console)) * ORD(~dll));
522
    OptionalHeader.DllCharacteristics           :=  0040X;
523
    OptionalHeader.SizeOfStackReserve           :=  100000H;
524
    OptionalHeader.SizeOfStackCommit            :=  10000H;
525
    OptionalHeader.SizeOfHeapReserve            :=  100000H;
526
    OptionalHeader.SizeOfHeapCommit             :=  10000H;
527
    OptionalHeader.LoaderFlags                  :=  0;
528
    OptionalHeader.NumberOfRvaAndSizes          :=  IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
7597 akron1 529
 
8097 maxcodehac 530
    FOR i := 0 TO IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1 DO
531
        OptionalHeader.DataDirectory[i].VirtualAddress := 0;
532
        OptionalHeader.DataDirectory[i].Size := 0
533
    END;
534
 
535
    InitSection(SectionHeaders[0], ".text", Size.Code, SHC_text);
7983 leency 536
    SectionHeaders[0].VirtualAddress   := SectionAlignment;
8097 maxcodehac 537
    SectionHeaders[0].PointerToRawData := OptionalHeader.SizeOfHeaders;
7597 akron1 538
 
8097 maxcodehac 539
    InitSection(SectionHeaders[1], ".data", Size.Data, SHC_data);
540
    SectionHeaders[1].VirtualAddress   := WR.align(SectionHeaders[0].VirtualAddress + SectionHeaders[0].VirtualSize, SectionAlignment);
7983 leency 541
    SectionHeaders[1].PointerToRawData := SectionHeaders[0].PointerToRawData + SectionHeaders[0].SizeOfRawData;
7597 akron1 542
 
8097 maxcodehac 543
    InitSection(SectionHeaders[2], ".bss", Size.Bss, SHC_bss);
544
    SectionHeaders[2].VirtualAddress   := WR.align(SectionHeaders[1].VirtualAddress + SectionHeaders[1].VirtualSize, SectionAlignment);
545
    SectionHeaders[2].PointerToRawData := SectionHeaders[1].PointerToRawData + SectionHeaders[1].SizeOfRawData;
7983 leency 546
    SectionHeaders[2].SizeOfRawData    := 0;
7597 akron1 547
 
548
    Size.Import := GetImportSize(program.imp_list);
549
 
8097 maxcodehac 550
    InitSection(SectionHeaders[3], ".idata", Size.Import + CHL.Length(program._import), SHC_data);
551
    SectionHeaders[3].VirtualAddress   := WR.align(SectionHeaders[2].VirtualAddress + SectionHeaders[2].VirtualSize, SectionAlignment);
7983 leency 552
    SectionHeaders[3].PointerToRawData := SectionHeaders[2].PointerToRawData + SectionHeaders[2].SizeOfRawData;
7597 akron1 553
 
8097 maxcodehac 554
    Address.Code   := SectionHeaders[0].VirtualAddress + OptionalHeader.ImageBase;
555
    Address.Data   := SectionHeaders[1].VirtualAddress + OptionalHeader.ImageBase;
556
    Address.Bss    := SectionHeaders[2].VirtualAddress + OptionalHeader.ImageBase;
557
    Address.Import := SectionHeaders[3].VirtualAddress + OptionalHeader.ImageBase;
7597 akron1 558
 
8097 maxcodehac 559
    fixup(program, Address, amd64);
7597 akron1 560
 
561
    IF dll THEN
8097 maxcodehac 562
        Size.Export := Export(program, SectionHeaders[1].VirtualAddress + program.modname, ExportDir);
7597 akron1 563
 
8097 maxcodehac 564
        InitSection(SectionHeaders[4], ".edata", Size.Export + CHL.Length(program.export), SHC_data);
565
        SectionHeaders[4].VirtualAddress   := WR.align(SectionHeaders[3].VirtualAddress + SectionHeaders[3].VirtualSize, SectionAlignment);
7983 leency 566
        SectionHeaders[4].PointerToRawData := SectionHeaders[3].PointerToRawData + SectionHeaders[3].SizeOfRawData;
7597 akron1 567
 
8097 maxcodehac 568
        OptionalHeader.DataDirectory[0].VirtualAddress := SectionHeaders[4].VirtualAddress;
569
        OptionalHeader.DataDirectory[0].Size := SectionHeaders[4].VirtualSize
7597 akron1 570
    END;
571
 
8097 maxcodehac 572
    OptionalHeader.DataDirectory[1].VirtualAddress := SectionHeaders[3].VirtualAddress;
573
    OptionalHeader.DataDirectory[1].Size := SectionHeaders[3].VirtualSize;
7597 akron1 574
 
8097 maxcodehac 575
    FOR i := 1 TO ORD(FileHeader.NumberOfSections) - 1 DO
576
        INC(OptionalHeader.SizeOfInitializedData, SectionHeaders[i].SizeOfRawData)
7597 akron1 577
    END;
578
 
8097 maxcodehac 579
    OptionalHeader.SizeOfUninitializedData := WR.align(SectionHeaders[2].VirtualSize, FileAlignment);
7597 akron1 580
 
8097 maxcodehac 581
    FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO
582
        INC(OptionalHeader.SizeOfImage, WR.align(SectionHeaders[i].VirtualSize, SectionAlignment))
7597 akron1 583
    END;
584
 
585
    n := 0;
586
    BIN.InitArray(msdos, n, "4D5A80000100000004001000FFFF000040010000000000004000000000000000");
587
    BIN.InitArray(msdos, n, "0000000000000000000000000000000000000000000000000000000080000000");
588
    BIN.InitArray(msdos, n, "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F");
589
    BIN.InitArray(msdos, n, "742062652072756E20696E20444F53206D6F64652E0D0A240000000000000000");
590
 
8097 maxcodehac 591
    WR.Create(FileName);
7597 akron1 592
 
8097 maxcodehac 593
    WR.Write(msdos, LEN(msdos));
7597 akron1 594
 
8097 maxcodehac 595
    WR.Write(Signature, LEN(Signature));
596
    WriteFileHeader(FileHeader);
597
    WriteOptHeader(OptionalHeader, amd64);
7597 akron1 598
 
8097 maxcodehac 599
    FOR i := 0 TO ORD(FileHeader.NumberOfSections) - 1 DO
600
        WriteSectionHeader(SectionHeaders[i])
7597 akron1 601
    END;
602
 
8097 maxcodehac 603
    WR.Padding(FileAlignment);
7597 akron1 604
 
8097 maxcodehac 605
    CHL.WriteToFile(program.code);
606
    WR.Padding(FileAlignment);
7597 akron1 607
 
8097 maxcodehac 608
    CHL.WriteToFile(program.data);
609
    WR.Padding(FileAlignment);
7597 akron1 610
 
611
    n := (libcnt + 1) * 5;
612
    ImportTable := CHL.CreateIntList();
613
 
7983 leency 614
    FOR i := 0 TO (Size.Import - n * SIZE_OF_DWORD) DIV SizeOfWord + n - 1 DO
7597 akron1 615
        CHL.PushInt(ImportTable, 0)
616
    END;
617
 
618
    i := 0;
8097 maxcodehac 619
    _import := program.imp_list.first(BIN.IMPRT);
620
    WHILE _import # NIL DO
621
        IF _import.label = 0 THEN
622
            CHL.SetInt(ImportTable, i + 0, _import.OriginalFirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD);
7597 akron1 623
            CHL.SetInt(ImportTable, i + 1, 0);
624
            CHL.SetInt(ImportTable, i + 2, 0);
8097 maxcodehac 625
            CHL.SetInt(ImportTable, i + 3, _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress);
626
            CHL.SetInt(ImportTable, i + 4, _import.FirstThunk * SizeOfWord + SectionHeaders[3].VirtualAddress + n * SIZE_OF_DWORD);
627
            INC(i, 5)
7597 akron1 628
        END;
8097 maxcodehac 629
        _import := _import.next(BIN.IMPRT)
7597 akron1 630
    END;
631
 
632
    CHL.SetInt(ImportTable, i + 0, 0);
633
    CHL.SetInt(ImportTable, i + 1, 0);
634
    CHL.SetInt(ImportTable, i + 2, 0);
635
    CHL.SetInt(ImportTable, i + 3, 0);
636
    CHL.SetInt(ImportTable, i + 4, 0);
637
 
8097 maxcodehac 638
    _import := program.imp_list.first(BIN.IMPRT);
639
    WHILE _import # NIL DO
640
        IF _import.label # 0 THEN
641
            temp := _import.nameoffs + Size.Import + SectionHeaders[3].VirtualAddress - 2;
642
            CHL.SetInt(ImportTable, _import.OriginalFirstThunk + n, temp);
643
            CHL.SetInt(ImportTable, _import.FirstThunk + n,         temp)
7597 akron1 644
        END;
8097 maxcodehac 645
        _import := _import.next(BIN.IMPRT)
7597 akron1 646
    END;
647
 
648
    FOR i := 0 TO n - 1 DO
8097 maxcodehac 649
        WR.Write32LE(CHL.GetInt(ImportTable, i))
7597 akron1 650
    END;
651
 
652
    FOR i := n TO CHL.Length(ImportTable) - 1 DO
653
        IF amd64 THEN
8097 maxcodehac 654
            WR.Write64LE(CHL.GetInt(ImportTable, i))
7597 akron1 655
        ELSE
8097 maxcodehac 656
            WR.Write32LE(CHL.GetInt(ImportTable, i))
7597 akron1 657
        END
658
    END;
659
 
8097 maxcodehac 660
    CHL.WriteToFile(program._import);
661
    WR.Padding(FileAlignment);
7597 akron1 662
 
663
    IF dll THEN
664
 
665
        INC(ExportDir.AddressOfFunctions,    SectionHeaders[4].VirtualAddress);
666
        INC(ExportDir.AddressOfNames,        SectionHeaders[4].VirtualAddress);
667
        INC(ExportDir.AddressOfNameOrdinals, SectionHeaders[4].VirtualAddress);
668
 
8097 maxcodehac 669
        WriteExportDir(ExportDir);
7597 akron1 670
 
671
        export := program.exp_list.first(BIN.EXPRT);
672
        WHILE export # NIL DO
8097 maxcodehac 673
            WR.Write32LE(export.label + SectionHeaders[0].VirtualAddress);
7597 akron1 674
            export := export.next(BIN.EXPRT)
675
        END;
676
 
677
        export := program.exp_list.first(BIN.EXPRT);
678
        WHILE export # NIL DO
8097 maxcodehac 679
            WR.Write32LE(export.nameoffs + Size.Export + SectionHeaders[4].VirtualAddress);
7597 akron1 680
            export := export.next(BIN.EXPRT)
681
        END;
682
 
683
        FOR i := 0 TO ExportDir.NumberOfFunctions - 1 DO
8097 maxcodehac 684
            WriteWord(WCHR(i))
7597 akron1 685
        END;
686
 
8097 maxcodehac 687
        CHL.WriteToFile(program.export);
688
        WR.Padding(FileAlignment)
7597 akron1 689
    END;
690
 
8097 maxcodehac 691
    WR.Close
7597 akron1 692
END write;
693
 
694
 
7983 leency 695
END PE32.