Subversion Repositories Kolibri OS

Rev

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

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