Coverage Report

Created: 2025-07-23 06:39

/src/upx/src/pefile.h
Line
Count
Source (jump to first uncovered line)
1
/* pefile.h --
2
3
   This file is part of the UPX executable compressor.
4
5
   Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
6
   Copyright (C) 1996-2025 Laszlo Molnar
7
   All Rights Reserved.
8
9
   UPX and the UCL library are free software; you can redistribute them
10
   and/or modify them under the terms of the GNU General Public License as
11
   published by the Free Software Foundation; either version 2 of
12
   the License, or (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program; see the file COPYING.
21
   If not, write to the Free Software Foundation, Inc.,
22
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24
   Markus F.X.J. Oberhumer              Laszlo Molnar
25
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26
 */
27
28
#pragma once
29
30
/*************************************************************************
31
// general/pe handling
32
**************************************************************************/
33
34
class PeFile : public Packer {
35
    typedef Packer super;
36
public:
37
78.3k
    virtual int getVersion() const override { return 13; }
38
protected:
39
    class Interval;
40
    class Reloc;
41
    class Resource;
42
    class Export;
43
    class ImportLinker;
44
    struct pe_section_t;
45
46
    explicit PeFile(InputFile *f);
47
    virtual ~PeFile() noexcept;
48
49
    void readSectionHeaders(unsigned objs, unsigned sizeof_ih);
50
    unsigned readSections(unsigned objs, unsigned usize, unsigned ih_filealign,
51
                          unsigned ih_datasize);
52
    void checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_entry,
53
                           unsigned ih_filealign);
54
    unsigned handleStripRelocs(upx_uint64_t ih_imagebase, upx_uint64_t default_imagebase,
55
                               LE16 &dllflags);
56
57
    virtual bool needForceOption() const = 0;
58
    virtual void callCompressWithFilters(Filter &, int filter_strategy, unsigned ih_codebase);
59
    virtual void defineSymbols(unsigned ncsection, unsigned upxsection, unsigned sizeof_oh,
60
                               unsigned isize_isplit, unsigned s1addr) = 0;
61
0
    virtual void addNewRelocations(Reloc &, unsigned) {}
62
    void callProcessStubRelocs(Reloc &rel, unsigned &ic);
63
    void callProcessResources(Resource &res, unsigned &ic);
64
0
    virtual unsigned getProcessImportParam(unsigned) { return 0; }
65
    virtual void setOhDataBase(const pe_section_t *osection) = 0;
66
    virtual void setOhHeaderSize(const pe_section_t *osection) = 0;
67
68
    template <typename LEXX, typename ht>
69
    void pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
70
               upx_uint64_t default_imagebase, bool last_section_rsrc_only);
71
72
    template <typename ht, typename LEXX, typename ord_mask_t>
73
    void unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, bool set_oft);
74
75
    // unpacker capabilities
76
244
    virtual bool canUnpackVersion(int version) const override {
77
244
        return (version >= 12 && version <= 13);
78
244
    }
79
80
    int canUnpack0(unsigned max_sections, unsigned objs, unsigned ih_entry, unsigned ih_size);
81
82
protected:
83
    static int checkMachine(unsigned cpu);
84
    virtual int readFileHeader();
85
    virtual bool testUnpackVersion(int version) const override;
86
    virtual void readPeHeader() = 0;
87
88
    unsigned pe_offset;
89
90
    template <typename LEXX, typename ord_mask_t>
91
    unsigned processImports0(ord_mask_t ord_mask);
92
93
    template <typename LEXX, typename ord_mask_t>
94
    void rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool set_oft);
95
    virtual unsigned processImports() = 0;
96
    virtual void processImports2(unsigned, unsigned);
97
    MemBuffer mb_oimport;
98
    SPAN_0(byte) oimport = nullptr;
99
    unsigned soimport;
100
    byte *oimpdlls = nullptr;
101
    unsigned soimpdlls;
102
    ImportLinker *ilinker = nullptr;
103
0
    virtual const char *kernelDll() const { return "KERNEL32.DLL"; }
104
    void addKernelImport(const char *);
105
    virtual void addStubImports();
106
    upx_uint64_t ilinkerGetAddress(const char *, const char *) const;
107
108
    virtual void processRelocs() = 0;
109
    void rebuildRelocs(SPAN_S(byte) &, unsigned bits, unsigned flags, upx_uint64_t imagebase);
110
    MemBuffer mb_orelocs;
111
    SPAN_0(byte) orelocs = nullptr;
112
    unsigned sorelocs;
113
    byte *oxrelocs = nullptr;
114
    unsigned soxrelocs;
115
116
    void processExports(Export *);
117
    void processExports(Export *, unsigned);
118
    void rebuildExports();
119
    MemBuffer mb_oexport;
120
    SPAN_0(byte) oexport = nullptr;
121
    unsigned soexport;
122
123
    void processResources(Resource *);
124
    void processResources(Resource *, unsigned);
125
    void rebuildResources(SPAN_S(byte) &, unsigned);
126
    MemBuffer mb_oresources;
127
    SPAN_0(byte) oresources = nullptr;
128
    unsigned soresources;
129
130
    template <typename>
131
    struct tls_traits;
132
    template <typename LEXX>
133
    void processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t imagebase,
134
                     unsigned imagesize); // pass 1
135
    template <typename LEXX>
136
    void processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
137
                     typename tls_traits<LEXX>::cb_value_t imagebase); // pass 2
138
    virtual void processTls(Interval *iv) = 0;
139
    virtual void processTls(Reloc *r, const Interval *iv, unsigned a) = 0;
140
141
    void rebuildTls();
142
    MemBuffer mb_otls;
143
    SPAN_0(byte) otls = nullptr;
144
    unsigned sotls;
145
    unsigned tlsindex;
146
    unsigned tlscb_ptr;
147
    unsigned tls_handler_offset = 0;
148
    bool use_tls_callbacks = false;
149
150
    void processLoadConf(Reloc *, const Interval *, unsigned);
151
    void processLoadConf(Interval *);
152
    MemBuffer mb_oloadconf;
153
    byte *oloadconf = nullptr;
154
    unsigned soloadconf;
155
156
    unsigned stripDebug(unsigned);
157
158
    unsigned icondir_offset;
159
    int icondir_count;
160
161
    bool importbyordinal = false;
162
    bool kernel32ordinal = false;
163
    unsigned rvamin;
164
    unsigned cimports; // rva of preprocessed imports
165
    unsigned crelocs;  // rva of preprocessed fixups
166
    int big_relocs;
167
168
    struct alignas(1) ddirs_t {
169
        LE32 vaddr;
170
        LE32 size;
171
    };
172
    ddirs_t *iddirs = nullptr;
173
    ddirs_t *oddirs = nullptr;
174
175
    LE32 &IDSIZE(unsigned x);
176
    LE32 &IDADDR(unsigned x);
177
    LE32 &ODSIZE(unsigned x);
178
    LE32 &ODADDR(unsigned x);
179
    const LE32 &IDSIZE(unsigned x) const;
180
    const LE32 &IDADDR(unsigned x) const;
181
182
    struct alignas(1) import_desc {
183
        LE32 oft; // orig first thunk
184
        byte _[8];
185
        LE32 dllname;
186
        LE32 iat; // import address table
187
    };
188
189
    struct alignas(1) pe_section_t {
190
        char name[8];
191
        LE32 vsize;
192
        LE32 vaddr;
193
        LE32 size;
194
        LE32 rawdataptr;
195
        byte _[12];
196
        LE32 flags;
197
    };
198
199
    MemBuffer mb_isection;
200
    SPAN_0(pe_section_t) isection = nullptr;
201
    bool isdll = false;
202
    bool isrtm = false;
203
    bool isefi = false;
204
    bool use_dep_hack = true;
205
    bool use_clear_dirty_stack = true;
206
    bool use_stub_relocs = true;
207
208
    static unsigned virta2objnum(unsigned, SPAN_0(pe_section_t), unsigned);
209
    unsigned tryremove(unsigned, unsigned);
210
211
    enum {
212
        IMAGE_FILE_MACHINE_UNKNOWN = 0,
213
        IMAGE_FILE_MACHINE_AMD64 = 0x8664,   // win64/pe (amd64)
214
        IMAGE_FILE_MACHINE_ARM = 0x01c0,     // wince/arm (Windows CE)
215
        IMAGE_FILE_MACHINE_ARMNT = 0x01c4,   // win32/arm
216
        IMAGE_FILE_MACHINE_ARM64 = 0xaa64,   // win64/arm64
217
        IMAGE_FILE_MACHINE_ARM64EC = 0xa641, // win64/arm64ec
218
        IMAGE_FILE_MACHINE_I386 = 0x014c,    // win32/pe (i386)
219
        IMAGE_FILE_MACHINE_IA64 = 0x200,
220
        IMAGE_FILE_MACHINE_LOONGARCH32 = 0x6232,
221
        IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264,
222
        IMAGE_FILE_MACHINE_RISCV32 = 0x5032,
223
        IMAGE_FILE_MACHINE_RISCV64 = 0x5064,
224
        IMAGE_FILE_MACHINE_RISCV128 = 0x5128,
225
        IMAGE_FILE_MACHINE_THUMB = 0x01c2, // wince/arm (Windows CE)
226
    };
227
228
    enum {
229
        PEDIR_EXPORT = 0,
230
        PEDIR_IMPORT = 1,
231
        PEDIR_RESOURCE = 2,
232
        PEDIR_EXCEPTION = 3, // Exception table
233
        PEDIR_SECURITY = 4,  // Certificate table (file pointer)
234
        PEDIR_BASERELOC = 5,
235
        PEDIR_DEBUG = 6,
236
        PEDIR_ARCHITECTURE = 7, // Architecture-specific data
237
        PEDIR_GLOBALPTR = 8,    // Global pointer
238
        PEDIR_TLS = 9,
239
        PEDIR_LOAD_CONFIG = 10, // Load Config Table
240
        PEDIR_BOUND_IMPORT = 11,
241
        PEDIR_IAT = 12,
242
        PEDIR_DELAY_IMPORT = 13,   // Delay Import Descriptor
243
        PEDIR_COM_DESCRIPTOR = 14, // Com+ Runtime Header
244
    };
245
246
    // section flags
247
    enum : unsigned {
248
        IMAGE_SCN_CNT_CODE = 0x00000020,
249
        IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
250
        IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
251
        IMAGE_SCN_LNK_OTHER = 0x00000100,
252
        IMAGE_SCN_LNK_INFO = 0x00000200,
253
        IMAGE_SCN_LNK_REMOVE = 0x00000800,
254
        IMAGE_SCN_LNK_COMDAT = 0x00001000,
255
        IMAGE_SCN_GPREL = 0x00008000,
256
        IMAGE_SCN_MEM_PURGEABLE = 0x00020000,
257
        IMAGE_SCN_MEM_16BIT = 0x00020000,
258
        IMAGE_SCN_MEM_LOCKED = 0x00040000,
259
        IMAGE_SCN_MEM_PRELOAD = 0x00080000,
260
        IMAGE_SCN_ALIGN_1BYTES = 0x00100000,
261
        IMAGE_SCN_ALIGN_2BYTES = 0x00200000,
262
        IMAGE_SCN_ALIGN_4BYTES = 0x00300000,
263
        IMAGE_SCN_ALIGN_8BYTES = 0x00400000,
264
        IMAGE_SCN_ALIGN_16BYTES = 0x00500000,
265
        IMAGE_SCN_ALIGN_32BYTES = 0x00600000,
266
        IMAGE_SCN_ALIGN_64BYTES = 0x00700000,
267
        IMAGE_SCN_ALIGN_128BYTES = 0x00800000,
268
        IMAGE_SCN_ALIGN_256BYTES = 0x00900000,
269
        IMAGE_SCN_ALIGN_512BYTES = 0x00A00000,
270
        IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000,
271
        IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000,
272
        IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000,
273
        IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000,
274
        IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000,
275
        IMAGE_SCN_MEM_DISCARDABLE = 0x02000000,
276
        IMAGE_SCN_MEM_NOT_CACHED = 0x04000000,
277
        IMAGE_SCN_MEM_NOT_PAGED = 0x08000000,
278
        IMAGE_SCN_MEM_SHARED = 0x10000000,
279
        IMAGE_SCN_MEM_EXECUTE = 0x20000000,
280
        IMAGE_SCN_MEM_READ = 0x40000000,
281
        IMAGE_SCN_MEM_WRITE = 0x80000000,
282
    };
283
284
    enum {
285
        IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
286
        IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
287
        IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
288
        IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
289
        IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010,
290
        IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
291
        IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
292
        IMAGE_FILE_32BIT_MACHINE = 0x0100,
293
        IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
294
        IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
295
        IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
296
        IMAGE_FILE_SYSTEM = 0x1000,
297
        IMAGE_FILE_DLL = 0x2000,
298
        IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
299
        IMAGE_FILE_BYTES_REVERSE_HI = 0x8000,
300
    };
301
302
    enum {
303
        IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020,
304
        IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
305
        IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
306
        IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
307
        IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
308
        IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
309
        IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
310
        IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000,
311
        IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
312
        IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000,
313
        IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000,
314
    };
315
316
    enum {
317
        IMAGE_SUBSYSTEM_UNKNOWN = 0,
318
        IMAGE_SUBSYSTEM_NATIVE = 1,
319
        IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical User Interface
320
        IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character User Interface
321
        IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5,
322
        IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7,
323
        IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8,
324
        IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
325
        IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
326
        IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
327
        IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
328
        IMAGE_SUBSYSTEM_EFI_ROM = 13,
329
        IMAGE_SUBSYSTEM_XBOX = 14,
330
        IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16,
331
    };
332
333
    // predefined Resource Types
334
    enum {
335
        RT_CURSOR = 1,
336
        RT_BITMAP,
337
        RT_ICON,
338
        RT_MENU,
339
        RT_DIALOG,
340
        RT_STRING,
341
        RT_FONTDIR,
342
        RT_FONT,
343
        RT_ACCELERATOR,
344
        RT_RCDATA,
345
        RT_MESSAGETABLE,
346
        RT_GROUP_CURSOR,
347
        RT_GROUP_ICON = 14,
348
        RT_VERSION = 16,
349
        RT_DLGINCLUDE,
350
        RT_PLUGPLAY = 19,
351
        RT_VXD,
352
        RT_ANICURSOR,
353
        RT_ANIICON,
354
        RT_HTML,
355
        RT_MANIFEST,
356
        RT_LAST
357
    };
358
359
    enum {                            // 4-bit reloc_type in IMAGE_BASE_RELOCATION relocations
360
        IMAGE_REL_BASED_ABSOLUTE = 0, // this relocation is ignored
361
        IMAGE_REL_BASED_IGNORE = 0,   // (unofficial UPX name)
362
        IMAGE_REL_BASED_HIGH = 1,
363
        IMAGE_REL_BASED_LOW = 2,
364
        IMAGE_REL_BASED_HIGHLOW = 3,
365
        IMAGE_REL_BASED_HIGHADJ = 4,
366
        IMAGE_REL_BASED_MIPS_JMPADDR = 5,
367
        IMAGE_REL_BASED_ARM_MOV32 = 5,
368
        IMAGE_REL_BASED_THUMB_MOV32 = 7,
369
        IMAGE_REL_BASED_MIPS_JMPADDR16 = 9,
370
        IMAGE_REL_BASED_IA64_IMM64 = 9,
371
        IMAGE_REL_BASED_DIR64 = 10,
372
    };
373
374
    class Interval final : private upx::noncopyable {
375
        SPAN_0(byte) base = nullptr;
376
        unsigned ivcapacity = 0; // for ivarr
377
    public:
378
        struct interval {
379
            unsigned start, len;
380
        };
381
        struct interval *ivarr = nullptr;
382
        unsigned ivnum = 0;
383
384
        explicit Interval(SPAN_P(byte));
385
        ~Interval() noexcept;
386
387
        void add_interval(unsigned start, unsigned len);
388
        void add_interval(const void *start, unsigned len);
389
        void add_interval(const void *start, const void *end);
390
        void add_interval(const Interval *other);
391
        void flatten();
392
393
        void clear();
394
        void dump() const;
395
396
    private:
397
        static int __acc_cdecl_qsort compare(const void *p1, const void *p2);
398
    };
399
400
    class Reloc final : private upx::noncopyable {
401
        // these are set in the constructor:
402
        byte *start = nullptr;
403
        unsigned start_size_in_bytes = 0;
404
        bool start_did_alloc = false;
405
        SPAN_0(byte) start_buf = nullptr;
406
407
        struct alignas(1) BaseReloc { // IMAGE_BASE_RELOCATION
408
            LE32 virtual_address;
409
            LE32 size_of_block;
410
            // LE16 rel1[COUNT]; // actual relocations; COUNT == (size_of_block - 8) / 2
411
        };
412
        struct RelocationBlock {
413
            SPAN_0(BaseReloc) rel = nullptr;
414
            SPAN_0(LE16) rel1 = nullptr;
415
            unsigned count = 0;
416
            void reset() noexcept;
417
        };
418
        RelocationBlock rb;                   // current RelocationBlock
419
        bool readFromRelocationBlock(byte *); // set rb
420
421
        unsigned counts[16] = {};
422
423
        void initSpans();
424
    public:
425
        explicit Reloc(byte *ptr, unsigned bytes);
426
        explicit Reloc(unsigned relocnum);
427
        ~Reloc() noexcept;
428
        //
429
        bool next(unsigned &result_pos, unsigned &result_reloc_type);
430
0
        const unsigned *getcounts() const { return counts; }
431
        //
432
        void add_reloc(unsigned pos, unsigned reloc_type);
433
        void finish(byte *(&result_ptr), unsigned &result_size); // => transfer ownership
434
    };
435
436
    class Resource final : private upx::noncopyable {
437
        struct res_dir_entry;
438
        struct res_dir;
439
        struct res_data;
440
        struct upx_rnode;
441
        struct upx_rbranch;
442
        struct upx_rleaf;
443
444
        MemBuffer mb_start;
445
        const byte *start = nullptr;
446
        byte *newstart = nullptr;
447
        upx_rnode *root = nullptr;
448
        upx_rleaf *head = nullptr;
449
        upx_rleaf *current = nullptr;
450
        unsigned dsize = 0;
451
        unsigned ssize = 0;
452
453
        const byte *ibufstart = nullptr;
454
        const byte *ibufend = nullptr;
455
456
        void check(const res_dir *, unsigned);
457
        upx_rnode *convert(const void *, upx_rnode *, unsigned);
458
        void build(const upx_rnode *, unsigned &, unsigned &, unsigned);
459
        void clear(byte *, unsigned, Interval *);
460
        void dump(const upx_rnode *, unsigned) const;
461
        void destroy(upx_rnode *urd, unsigned level) noexcept;
462
463
        void ibufcheck(const void *m, unsigned size);
464
465
    public:
466
        explicit Resource(const byte *ibufstart, const byte *ibufen);
467
        explicit Resource(const byte *p, const byte *ibufstart, const byte *ibufend);
468
        ~Resource() noexcept;
469
        void init(const byte *);
470
471
        unsigned dirsize() const;
472
        bool next();
473
474
        unsigned itype() const;
475
        const byte *ntype() const;
476
        unsigned size() const;
477
        unsigned offs() const;
478
        unsigned &newoffs();
479
480
        byte *build();
481
        bool clear();
482
483
        void dump() const;
484
        unsigned iname() const;
485
        const byte *nname() const;
486
        /*
487
         unsigned ilang() const {return current->id;}
488
         const byte *nlang() const {return current->name;}
489
         */
490
    };
491
492
    class Export final : private upx::noncopyable {
493
        struct alignas(1) export_dir_t {
494
            byte _[12]; // flags, timedate, version
495
            LE32 name;
496
            byte __[4]; // ordinal base
497
            LE32 functions;
498
            LE32 names;
499
            LE32 addrtable;
500
            LE32 nameptrtable;
501
            LE32 ordinaltable;
502
        };
503
504
        export_dir_t edir;
505
        char *ename;
506
        char *functionptrs;
507
        char *ordinals;
508
        char **names;
509
510
        char *base;
511
        unsigned size;
512
        Interval iv;
513
514
    public:
515
        explicit Export(char *_base);
516
        ~Export() noexcept;
517
518
        void convert(unsigned eoffs, unsigned esize);
519
        void build(char *base, unsigned newoffs);
520
0
        unsigned getsize() const { return size; }
521
    };
522
};
523
524
class PeFile32 : public PeFile {
525
    typedef PeFile super;
526
protected:
527
    explicit PeFile32(InputFile *f);
528
    virtual ~PeFile32() noexcept;
529
530
    void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase,
531
               bool last_section_rsrc_only);
532
    virtual void unpack(OutputFile *fo) override;
533
    virtual tribool canUnpack() override;
534
535
    virtual void readPeHeader() override;
536
537
    virtual unsigned processImports() override;
538
    virtual void processRelocs() override;
539
    virtual void processTls(Interval *) override;
540
    virtual void processTls(Reloc *, const Interval *, unsigned) override;
541
542
    struct alignas(1) pe_header_t {
543
        // 0x00
544
        byte _[4]; // pemagic
545
        // 0x04 IMAGE_FILE_HEADER
546
        LE16 cpu;        // IMAGE_FILE_MACHINE_xxx
547
        LE16 objects;    // NumberOfSections
548
        byte __[12];     // timestamp + reserved
549
        LE16 opthdrsize; // SizeOfOptionalHeader
550
        LE16 flags;      // IMAGE_FILE_xxx Characteristics
551
        // 0x18 IMAGE_OPTIONAL_HEADER32
552
        LE16 coffmagic; // NEW: Stefan Widmann
553
        byte ___[2];    // linkerversion
554
        LE32 codesize;
555
        // 0x20
556
        LE32 datasize;
557
        LE32 bsssize;
558
        LE32 entry;
559
        LE32 codebase;
560
        // 0x30
561
        LE32 database;
562
        // nt specific fields
563
        LE32 imagebase;
564
        LE32 objectalign;
565
        LE32 filealign; // should set to 0x200 ?
566
        // 0x40
567
        byte ____[16]; // versions
568
        // 0x50
569
        LE32 imagesize;
570
        LE32 headersize;
571
        LE32 chksum;    // should set to 0
572
        LE16 subsystem; // IMAGE_SUBSYSTEM_xxx
573
        LE16 dllflags;  // IMAGE_DLLCHARACTERISTICS_xxx
574
        // 0x60
575
        byte _____[20]; // stack + heap sizes
576
        // 0x74
577
        LE32 ddirsentries; // usually 16
578
        // 0x78
579
        ddirs_t ddirs[16];
580
    };
581
582
    pe_header_t ih = {}, oh = {};
583
};
584
585
class PeFile64 : public PeFile {
586
    typedef PeFile super;
587
protected:
588
    explicit PeFile64(InputFile *f);
589
    virtual ~PeFile64() noexcept;
590
591
    void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase);
592
593
    virtual void unpack(OutputFile *fo) override;
594
    virtual tribool canUnpack() override;
595
596
    virtual void readPeHeader() override;
597
598
    virtual unsigned processImports() override;
599
    virtual void processRelocs() override;
600
    virtual void processTls(Interval *) override;
601
    virtual void processTls(Reloc *, const Interval *, unsigned) override;
602
603
    struct alignas(1) pe_header_t {
604
        // 0x00
605
        byte _[4]; // pemagic
606
        // 0x04 IMAGE_FILE_HEADER
607
        LE16 cpu;        // IMAGE_FILE_MACHINE_xxx
608
        LE16 objects;    // NumberOfSections
609
        byte __[12];     // timestamp + reserved
610
        LE16 opthdrsize; // SizeOfOptionalHeader
611
        LE16 flags;      // IMAGE_FILE_xxx Characteristics
612
        // 0x18 IMAGE_OPTIONAL_HEADER64
613
        LE16 coffmagic; // NEW: Stefan Widmann
614
        byte ___[2];    // linkerversion
615
        LE32 codesize;
616
        // 0x20
617
        LE32 datasize;
618
        LE32 bsssize;
619
        LE32 entry; // still a 32 bit RVA
620
        LE32 codebase;
621
        // 0x30
622
        // LE32    database;         // field does not exist in PE+!
623
        // nt specific fields
624
        LE64 imagebase; // LE32 -> LE64 - Stefan Widmann standard is 0x0000000140000000
625
        LE32 objectalign;
626
        LE32 filealign; // should set to 0x200 ?
627
        // 0x40
628
        byte ____[16]; // versions
629
        // 0x50
630
        LE32 imagesize;
631
        LE32 headersize;
632
        LE32 chksum;    // should set to 0
633
        LE16 subsystem; // IMAGE_SUBSYSTEM_xxx
634
        LE16 dllflags;  // IMAGE_DLLCHARACTERISTICS_xxx
635
        // 0x60
636
        byte _____[36]; // stack + heap sizes + loader flag
637
        // 0x84
638
        LE32 ddirsentries; // usually 16
639
        // 0x88
640
        ddirs_t ddirs[16];
641
    };
642
643
    pe_header_t ih = {}, oh = {};
644
};
645
646
/* vim:set ts=4 sw=4 et: */