Coverage Report

Created: 2025-11-16 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/upx/src/p_lx_exc.cpp
Line
Count
Source
1
/* p_lx_exc.cpp --
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
   Copyright (C) 2001-2025 John F. Reiser
8
   All Rights Reserved.
9
10
   UPX and the UCL library are free software; you can redistribute them
11
   and/or modify them under the terms of the GNU General Public License as
12
   published by the Free Software Foundation; either version 2 of
13
   the License, or (at your option) any later version.
14
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program; see the file COPYING.
22
   If not, write to the Free Software Foundation, Inc.,
23
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25
   Markus F.X.J. Oberhumer              Laszlo Molnar
26
   <markus@oberhumer.com>               <ezerotven+github@gmail.com>
27
28
   John F. Reiser
29
   <jreiser@users.sourceforge.net>
30
 */
31
32
33
#include "conf.h"
34
35
#include "file.h"
36
#include "filter.h"
37
#include "linker.h"
38
#include "packer.h"
39
#include "p_elf.h"
40
#include "p_unix.h"
41
#include "p_lx_exc.h"
42
43
0
#define PT_LOAD     Elf32_Phdr::PT_LOAD
44
#define PT_DYNAMIC  Elf32_Phdr::PT_DYNAMIC
45
#if 0 // UNUSED
46
#define DT_NULL     Elf32_Dyn::DT_NULL
47
#define DT_NEEDED   Elf32_Dyn::DT_NEEDED
48
#define DT_STRTAB   Elf32_Dyn::DT_STRTAB
49
#define DT_STRSZ    Elf32_Dyn::DT_STRSZ
50
#endif
51
52
53
/*************************************************************************
54
// linux/386 (generic "execve" format)
55
**************************************************************************/
56
57
41.4k
PackLinuxI386::PackLinuxI386(InputFile *f) : super(f),
58
41.4k
    ei_osabi(Elf32_Ehdr::ELFOSABI_LINUX), osabi_note(nullptr)
59
41.4k
{
60
41.4k
    bele = &N_BELE_RTP::le_policy;
61
41.4k
}
62
63
13.9k
PackBSDI386::PackBSDI386(InputFile *f) : super(f)
64
13.9k
{
65
    // Shell scripts need help specifying the target operating system.
66
    // Elf input will override this with .e_ident[EI_OSABI] or PT_NOTE.
67
    // [2006-09-27: Today's only runtime stub for shell is for linux.]
68
13.9k
    if (Elf32_Ehdr::ELFOSABI_LINUX==opt->o_unix.osabi0) {
69
        // Disallow an incompatibility.
70
13.9k
        ei_osabi = Elf32_Ehdr::ELFOSABI_NONE;
71
13.9k
    }
72
0
    else {
73
0
        ei_osabi = opt->o_unix.osabi0;  // might be ELFOSABI_NONE
74
0
    }
75
13.9k
}
76
77
static const CLANG_FORMAT_DUMMY_STATEMENT
78
#include "stub/i386-linux.elf.execve-entry.h"
79
static const CLANG_FORMAT_DUMMY_STATEMENT
80
#include "stub/i386-linux.elf.execve-fold.h"
81
82
static const CLANG_FORMAT_DUMMY_STATEMENT
83
#include "stub/i386-bsd.elf.execve-entry.h"
84
static const CLANG_FORMAT_DUMMY_STATEMENT
85
#include "stub/i386-bsd.elf.execve-fold.h"
86
87
88
const int *PackLinuxI386::getCompressionMethods(int method, int level) const
89
0
{
90
0
    return Packer::getDefaultCompressionMethods_le32(method, level);
91
0
}
92
93
const int *PackLinuxI386::getFilters() const
94
0
{
95
0
    static const int filters[] = {
96
0
        0x49, 0x46,
97
0
        0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
98
#if 0
99
// 0x80..0x87 are regarded as "untested".
100
        0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85,
101
        0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
102
#endif
103
0
    FT_END };
104
0
    return filters;
105
0
}
106
107
static void
108
set_stub_brk(Elf_LE32_Phdr *const phdr1, unsigned brka)
109
0
{
110
0
#define PAGE_MASK (~0ul<<12)
111
        // linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary
112
0
        unsigned const brkb = brka | ((0==(~PAGE_MASK & brka)) ? 0x20 : 0);
113
0
        phdr1->p_type = PT_LOAD;  // be sure
114
0
        phdr1->p_offset = ~PAGE_MASK & brkb;
115
0
        phdr1->p_vaddr = brkb;
116
0
        phdr1->p_paddr = brkb;
117
0
        phdr1->p_filesz = 0;
118
0
        phdr1->p_memsz =  0;
119
0
        if (0==phdr1->p_flags) {
120
0
            phdr1->p_flags = Elf32_Phdr::PF_R|Elf32_Phdr::PF_W;
121
0
        }
122
0
        if (0==phdr1->p_align) {
123
0
            phdr1->p_align = 0x1000;
124
0
        }
125
0
#undef PAGE_MASK
126
0
}
127
128
void
129
PackLinuxI386::generateElfHdr(
130
    OutputFile *fo,
131
    void const *proto,
132
    unsigned const brka
133
)
134
0
{
135
0
    cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout;
136
0
    cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout;
137
0
    memcpy(h3, proto, sizeof(*h3));  // reads beyond, but OK
138
139
0
    assert(h2->ehdr.e_phoff     == sizeof(Elf32_Ehdr));
140
0
    assert(h2->ehdr.e_shoff     == 0);
141
0
    assert(h2->ehdr.e_ehsize    == sizeof(Elf32_Ehdr));
142
0
    assert(h2->ehdr.e_phentsize == sizeof(Elf32_Phdr));
143
0
    assert(h2->ehdr.e_shnum     == 0);
144
145
#if 0  //{
146
    unsigned identsize;
147
    char const *const ident = getIdentstr(&identsize);
148
#endif  //}
149
0
    h2->phdr[0].p_filesz = sizeof(*h2);  // + identsize;
150
0
    h2->phdr[0].p_memsz  = h2->phdr[0].p_filesz;
151
152
    // Info for OS kernel to set the brk()
153
0
    if (brka) {
154
0
        set_stub_brk(&h2->phdr[1], brka);
155
0
    }
156
157
0
    if (ph.format==UPX_F_LINUX_i386
158
0
    ||  ph.format==UPX_F_LINUX_SH_i386
159
0
    ||  ph.format==UPX_F_BSD_i386
160
0
    ) {
161
        // SELinux, PAx, grSecurity demand no PF_W if PF_X.
162
        // kernel-2.6.12-2.3.legacy_FC3 has a bug which demands
163
        // a PT_LOAD with PF_W, else SIGSEGV when clearing page fragment
164
        // on low page of ".bss", which is the high page of .text.
165
        // So the minimum number of PT_LOAD is 2.
166
0
        assert(h2->ehdr.e_phnum==2);
167
0
        memset(&h2->linfo, 0, sizeof(h2->linfo));
168
0
        fo->write(h2, sizeof(*h2));
169
0
    }
170
0
    else if (ph.format==UPX_F_LINUX_ELFI_i386) {
171
0
        assert(h3->ehdr.e_phnum==3);
172
0
        memset(&h3->linfo, 0, sizeof(h3->linfo));
173
0
        fo->write(h3, sizeof(*h3));
174
0
    }
175
0
    else {
176
0
        assert(false);  // unknown ph.format, PackUnix::generateElfHdr
177
0
    }
178
0
}
179
180
void
181
PackLinuxI386::pack1(OutputFile *fo, Filter &)
182
0
{
183
    // create a pseudo-unique program id for our paranoid stub
184
0
    progid = getRandomId();
185
186
0
    generateElfHdr(fo, stub_i386_linux_elf_execve_fold, 0);
187
0
}
188
189
void
190
PackBSDI386::pack1(OutputFile *fo, Filter &)
191
0
{
192
    // create a pseudo-unique program id for our paranoid stub
193
0
    progid = getRandomId();
194
195
0
    generateElfHdr(fo, stub_i386_bsd_elf_execve_fold, 0);
196
0
}
197
198
void
199
PackLinuxI386::pack4(OutputFile *fo, Filter &ft)
200
0
{
201
0
    overlay_offset = sizeof(elfout.ehdr) +
202
0
        (elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
203
0
        sizeof(l_info) +
204
0
        ((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) ;
205
0
    unsigned nw = fo->getBytesWritten();
206
0
    elfout.phdr[0].p_filesz = nw;
207
0
    nw = 0u-((0u-elfout.phdr[0].p_align) & (0u-nw));  // ALIGN_UP
208
0
    super::pack4(fo, ft);  // write PackHeader and overlay_offset
209
0
    set_stub_brk(&elfout.phdr[1], nw + elfout.phdr[0].p_vaddr);
210
211
#if 0  // {
212
    // /usr/bin/strip from RedHat 8.0 (binutils-2.13.90.0.2-2)
213
    // generates a 92-byte [only] output, because the "linking view"
214
    // is empty.  This code supplies a "linking view".
215
    // However, 'strip' then generates _plausible_ junk that gets
216
    // "Illegal instruction"  because 'strip' changes p_hdr[1].p_align,
217
    // .p_offset, and .p_vaddr incorrectly.  So the "cure" is worse than
218
    // the disease.  It is obvious that a 92-byte file is bad,
219
    // but it is not obvious that the changed .p_align is bad.
220
    // Also, having a totally empty "linking view" is easier for 'strip'
221
    // to fix: just detect that, and do nothing.
222
    // So, we don't use this code for now [2003-01-11].
223
224
    // Supply a "linking view" that covers everything,
225
    // so that 'strip' does not omit everything.
226
    Elf_LE32_Shdr shdr;
227
    // The section header string table.
228
    char const shstrtab[] = "\0.\0.shstrtab";
229
230
    unsigned eod = elfout.phdr[0].p_filesz;
231
    elfout.ehdr.e_shoff = eod;
232
    elfout.ehdr.e_shentsize = sizeof(shdr);
233
    elfout.ehdr.e_shnum = 3;
234
    elfout.ehdr.e_shstrndx = 2;
235
236
    // An empty Elf32_Shdr for space as a null index.
237
    memset(&shdr, 0, sizeof(shdr));
238
    shdr.sh_type = Elf32_Shdr::SHT_NULL;
239
    fo->write(&shdr, sizeof(shdr));
240
241
    // Cover all the bits we need at runtime.
242
    memset(&shdr, 0, sizeof(shdr));
243
    shdr.sh_name = 1;
244
    shdr.sh_type = Elf32_Shdr::SHT_PROGBITS;
245
    shdr.sh_flags = Elf32_Shdr::SHF_ALLOC;
246
    shdr.sh_addr = elfout.phdr[0].p_vaddr;
247
    shdr.sh_offset = overlay_offset;
248
    shdr.sh_size = eod - overlay_offset;
249
    shdr.sh_addralign = 4096;
250
    fo->write(&shdr, sizeof(shdr));
251
252
    // A section header for the section header string table.
253
    memset(&shdr, 0, sizeof(shdr));
254
    shdr.sh_name = 3;
255
    shdr.sh_type = Elf32_Shdr::SHT_STRTAB;
256
    shdr.sh_offset = 3*sizeof(shdr) + eod;
257
    shdr.sh_size = sizeof(shstrtab);
258
    fo->write(&shdr, sizeof(shdr));
259
260
    fo->write(shstrtab, sizeof(shstrtab));
261
#endif  // }
262
263
264
    // Cannot pre-round .p_memsz.  If .p_filesz < .p_memsz, then kernel
265
    // tries to make .bss, which requires PF_W.
266
    // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
267
#if 0  /*{*/
268
#undef PAGE_MASK
269
#define PAGE_MASK (~0u<<12)
270
    // pre-calculate for benefit of runtime disappearing act via munmap()
271
    elfout.phdr[0].p_memsz =  PAGE_MASK & (~PAGE_MASK + elfout.phdr[0].p_filesz);
272
#undef PAGE_MASK
273
#else  /*}{*/
274
0
    elfout.phdr[0].p_memsz =  elfout.phdr[0].p_filesz;
275
0
#endif  /*}*/
276
277
    // rewrite Elf header
278
0
    fo->seek(0, SEEK_SET);
279
0
    fo->rewrite(&elfout, overlay_offset);
280
0
}
281
282
Linker *PackLinuxI386::newLinker() const
283
0
{
284
0
    return new ElfLinkerX86;
285
0
}
286
287
void
288
PackLinuxI386::buildLinuxLoader(
289
    upx_byte const *const proto,
290
    unsigned        const szproto,
291
    upx_byte const *const fold,
292
    unsigned        const szfold,
293
    Filter const *ft
294
)
295
0
{
296
0
    initLoader(proto, szproto);
297
298
0
    unsigned fold_hdrlen = 0;
299
0
  if (0 < szfold) {
300
0
    cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
301
0
    fold_hdrlen = usizeof(hf->ehdr) + hf->ehdr.e_phentsize * hf->ehdr.e_phnum +
302
0
         usizeof(l_info);
303
0
    if (0 == get_le32(fold_hdrlen + fold)) {
304
        // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils)
305
0
        fold_hdrlen = upx::umax(0x80u, fold_hdrlen);
306
0
    }
307
0
  }
308
    // This adds the definition to the "library", to be used later.
309
    // NOTE: the stub is NOT compressed!  The savings is not worth it.
310
0
    linker->addSection("FOLDEXEC", fold + fold_hdrlen, szfold - fold_hdrlen, 0);
311
312
0
    n_mru = ft->n_mru;
313
314
// Rely on "+80CXXXX" [etc] in getDecompressorSections() packer_c.cpp */
315
//    // Here is a quick summary of the format of the output file:
316
//    linker->setLoaderAlignOffset(
317
//            // Elf32_Edhr
318
//        sizeof(elfout.ehdr) +
319
//            // Elf32_Phdr: 1 for exec86, 2 for sh86, 3 for elf86
320
//        (elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
321
//            // checksum UPX! lsize version format
322
//        sizeof(l_info) +
323
//            // PT_DYNAMIC with DT_NEEDED "forwarded" from original file
324
//        ((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) +
325
//            // p_progid, p_filesize, p_blocksize
326
//        sizeof(p_info) +
327
//            // compressed data
328
//        b_len + ph.c_len );
329
//            // entry to stub
330
0
    addLoader("LEXEC000", nullptr);
331
332
0
    if (ft->id) {
333
0
        if (n_mru) {
334
0
            addLoader("LEXEC009", nullptr);
335
0
        }
336
0
    }
337
0
    addLoader("LEXEC010", nullptr);
338
0
    linker->defineSymbol("filter_cto", ft->cto);
339
0
    linker->defineSymbol("filter_length",
340
0
                         (ft->id & 0xf) % 3 == 0 ? ft->calls :
341
0
                         ft->lastcall - ft->calls * 4);
342
0
    addLoader(getDecompressorSections(), nullptr);
343
0
    addLoader("LEXEC015", nullptr);
344
0
    if (ft->id) {
345
0
        {  // decompr, unfilter not separate
346
0
            if (0x80==(ft->id & 0xF0)) {
347
0
                addLoader("LEXEC110", nullptr);
348
0
                if (n_mru) {
349
0
                    addLoader("LEXEC100", nullptr);
350
0
                }
351
                // bug in APP: jmp and label must be in same .asx/.asy
352
0
                addLoader("LEXEC016", nullptr);
353
0
            }
354
0
        }
355
0
        addFilter32(ft->id);
356
0
        {  // decompr always unfilters
357
0
            addLoader("LEXEC017", nullptr);
358
0
        }
359
0
    }
360
0
    else {
361
0
        addLoader("LEXEC017", nullptr);
362
0
    }
363
364
0
    addLoader("IDENTSTR", nullptr);
365
0
    addLoader("LEXEC020", nullptr);
366
0
    addLoader("FOLDEXEC", nullptr);
367
0
    if (M_IS_LZMA(ph.method)) {
368
0
        const lzma_compress_result_t *res = &ph.compress_result.result_lzma;
369
0
        upx_uint32_t properties = // lc, lp, pb, dummy
370
0
            (res->lit_context_bits << 0) |
371
0
            (res->lit_pos_bits << 8) |
372
0
            (res->pos_bits << 16);
373
0
        if (bele->isBE()) // big endian - bswap32
374
0
            properties = bswap32(properties);
375
0
        linker->defineSymbol("lzma_properties", properties);
376
377
        // These lengths assume only one block (typ. 524288 bytes: 0.5 MiB).
378
        // i386 handles more than one block, and computes the lengths
379
        // dynamically from struct b_info.  Why do others need these?
380
0
        if (linker->findSymbol("lzma_c_len", false)) {
381
            // -2 for properties
382
0
            linker->defineSymbol("lzma_c_len", ph.c_len - 2);
383
0
        }
384
0
        if (linker->findSymbol("lzma_u_len", false)) {
385
0
            linker->defineSymbol("lzma_u_len", ph.c_len);
386
0
        }
387
388
0
        unsigned const stack = getDecompressorWrkmemSize();
389
0
        linker->defineSymbol("lzma_stack_adjust", 0u - stack);
390
0
    }
391
0
    if (0x80==(ft->id & 0xF0)) {
392
0
        int const mru = ft->n_mru ? 1+ ft->n_mru : 0;
393
0
        if (mru && mru!=256) {
394
0
            unsigned const is_pwr2 = (0==((mru -1) & mru));
395
0
            linker->defineSymbol("NMRU", mru - is_pwr2);
396
0
        }
397
0
    }
398
0
    relocateLoader();
399
0
}
400
401
void
402
PackLinuxI386::buildLoader(Filter const *ft)
403
0
{
404
0
    unsigned const sz_fold = sizeof(stub_i386_linux_elf_execve_fold);
405
0
    MemBuffer buf(sz_fold);
406
0
    memcpy(buf, stub_i386_linux_elf_execve_fold, sz_fold);
407
408
    // patch loader
409
    // note: we only can use /proc/<pid>/fd when exetype > 0.
410
    //   also, we sleep much longer when compressing a script.
411
0
    checkPatch(nullptr, 0, 0, 0);  // reset
412
0
    patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15);   // sleep time
413
0
    patch_le32(buf,sz_fold,"UPX3",progid);
414
0
    patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
415
416
0
    buildLinuxLoader(
417
0
        stub_i386_linux_elf_execve_entry, sizeof(stub_i386_linux_elf_execve_entry),
418
0
        buf, sz_fold, ft );
419
0
}
420
421
void
422
PackBSDI386::buildLoader(Filter const *ft)
423
0
{
424
0
    unsigned const sz_fold = sizeof(stub_i386_bsd_elf_execve_fold);
425
0
    MemBuffer buf(sz_fold);
426
0
    memcpy(buf, stub_i386_bsd_elf_execve_fold, sz_fold);
427
428
    // patch loader
429
    // note: we only can use /proc/<pid>/fd when exetype > 0.
430
    //   also, we sleep much longer when compressing a script.
431
0
    checkPatch(nullptr, 0, 0, 0);  // reset
432
0
    patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15);   // sleep time
433
0
    patch_le32(buf,sz_fold,"UPX3",progid);
434
0
    patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
435
436
0
    buildLinuxLoader(
437
0
        stub_i386_bsd_elf_execve_entry, sizeof(stub_i386_bsd_elf_execve_entry),
438
0
        buf, sz_fold, ft );
439
0
}
440
441
// FIXME: getLoaderPrefixSize is unused?
442
int PackLinuxI386::getLoaderPrefixSize() const
443
0
{
444
0
    return 116;
445
0
}
446
447
448
/*************************************************************************
449
// some ELF utility functions
450
**************************************************************************/
451
452
// basic check of a Linux ELF Ehdr
453
int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const
454
0
{
455
0
    const unsigned char * const buf = ehdr->e_ident;
456
457
0
    if (memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB
458
0
        return -1;
459
460
    // now check the ELF header
461
0
    if (!memcmp(buf+8, "FreeBSD", 7))                  // branded
462
0
        return 1;
463
0
    if (ehdr->e_type != Elf32_Ehdr::ET_EXEC
464
0
    &&  ehdr->e_type != Elf32_Ehdr::ET_DYN )           // executable
465
0
        return 2;
466
0
    if (ehdr->e_machine != Elf32_Ehdr::EM_386)         // Intel 80386
467
0
        return 3;
468
0
    if (ehdr->e_version != Elf32_Ehdr::EV_CURRENT)     // version
469
0
        return 4;
470
0
    if (ehdr->e_phnum < 1)
471
0
        return 5;
472
0
    if (ehdr->e_phentsize != sizeof(Elf32_Phdr))
473
0
        return 6;
474
475
    // check for Linux kernels
476
0
    if (ehdr->e_entry == 0xC0100000)                    // uncompressed vmlinux
477
0
        return 1000;
478
0
    if (ehdr->e_entry == 0x00001000)                    // compressed vmlinux
479
0
        return 1001;
480
0
    if (ehdr->e_entry == 0x00100000)                    // compressed bvmlinux
481
0
        return 1002;
482
483
    // FIXME: add more checks for kernels
484
485
    // FIXME: add special checks for other ELF i386 formats, like
486
    //        NetBSD, OpenBSD, Solaris, ....
487
488
    // success
489
0
    return 0;
490
0
}
491
492
493
494
/*************************************************************************
495
//
496
**************************************************************************/
497
498
tribool PackLinuxI386::canPack()
499
0
{
500
0
    if (exetype != 0)
501
0
        return super::canPack();
502
503
0
    Elf_LE32_Ehdr ehdr;
504
0
    unsigned char *buf = ehdr.e_ident;
505
506
0
    fi->seek(0, SEEK_SET);
507
0
    fi->readx(&ehdr, sizeof(ehdr));
508
0
    fi->seek(0, SEEK_SET);
509
510
0
    exetype = 0;
511
0
    const unsigned l = get_le32(buf);
512
513
0
    int elf = checkEhdr(&ehdr);
514
0
    if (elf >= 0) {
515
        // NOTE: ELF executables are now handled by p_lx_elf.cpp,
516
        //   so we only handle them here if force_execve
517
0
        if (elf == 0 && opt->o_unix.force_execve) {
518
0
            exetype = 1;
519
520
0
            unsigned osabi0 = ehdr.e_ident[Elf32_Ehdr::EI_OSABI];
521
0
            switch (osabi0) {
522
0
            case Elf32_Ehdr::ELFOSABI_LINUX:
523
0
            case Elf32_Ehdr::ELFOSABI_FREEBSD:
524
0
            case Elf32_Ehdr::ELFOSABI_NETBSD:
525
0
            case Elf32_Ehdr::ELFOSABI_OPENBSD:
526
0
                ei_osabi = osabi0;  // Proudly declares its osabi in Ehdr.
527
0
                break;
528
0
            default:
529
0
            unsigned const e_phnum = get_te16(&ehdr.e_phnum);
530
0
            if (e_phnum<=(512/sizeof(Elf32_Phdr))) {
531
0
                union {
532
0
                    unsigned char buf2[512];
533
                    //Elf32_Phdr phdr;
534
0
                } u;
535
0
                fi->seek(get_te32(&ehdr.e_phoff), SEEK_SET);
536
0
                fi->readx(u.buf2, sizeof(u.buf2));
537
0
                fi->seek(0, SEEK_SET);
538
0
                Elf32_Phdr const *phdr = (Elf32_Phdr *) u.buf2;
539
0
                for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
540
0
                    if (phdr->PT_NOTE == get_te32(&phdr->p_type)) {
541
0
                        unsigned const offset = get_te32(&phdr->p_offset);
542
0
                        struct Elf32_Note note; memset(&note, 0, sizeof(note));
543
0
                        fi->seek(offset, SEEK_SET);
544
0
                        fi->readx(&note, sizeof(note));
545
0
                        fi->seek(0, SEEK_SET);
546
0
                        if (4==get_te32(&note.descsz)
547
0
                        &&  1==get_te32(&note.type)
548
0
                        &&  0==note.end ) {
549
0
                            if (0==strcmp("NetBSD", (char const *)note.text)) {
550
0
                                ei_osabi = Elf32_Ehdr::ELFOSABI_NETBSD;
551
0
                                break;
552
0
                            }
553
0
                            if (0==strcmp("OpenBSD", (char const *)note.text)) {
554
0
                                ei_osabi = Elf32_Ehdr::ELFOSABI_OPENBSD;
555
0
                                break;
556
0
                            }
557
0
                        }
558
0
                    }
559
0
                }
560
0
            }
561
0
            }
562
0
        }
563
0
        if (UPX_F_BSD_i386==getFormat()
564
0
        && !(Elf32_Ehdr::ELFOSABI_FREEBSD==ei_osabi
565
0
          || Elf32_Ehdr::ELFOSABI_NETBSD ==ei_osabi
566
0
          || Elf32_Ehdr::ELFOSABI_OPENBSD==ei_osabi )) {
567
0
            return false;
568
0
        }
569
0
    }
570
0
    else if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
571
0
    {
572
        // OMAGIC / NMAGIC / ZMAGIC / QMAGIC
573
0
        exetype = 2;
574
        // FIXME: N_TRSIZE, N_DRSIZE
575
        // FIXME: check for aout shared libraries
576
0
    }
577
0
    else { // shell scripts and other interpreters
578
0
        if (Elf32_Ehdr::ELFOSABI_LINUX!=ei_osabi) {
579
0
            return false;  // so far, only Linux has runtime stub for shell
580
0
        }
581
0
        else if (!memcmp(buf, "#!/", 3))                    // #!/bin/sh
582
0
            exetype = -1;
583
0
        else if (!memcmp(buf, "#! /", 4))                   // #! /bin/sh
584
0
            exetype = -1;
585
0
        else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4))       // Java bytecode
586
0
            exetype = -2;
587
0
    }
588
589
0
    return super::canPack();
590
0
}
591
592
593
0
void PackLinuxI386::patchLoader() { }
594
595
596
void PackLinuxI386::patchLoaderChecksum()
597
0
{
598
0
    unsigned char *const ptr = getLoader();
599
0
    l_info *const lp = (l_info *)(sizeof(elfout.ehdr) +
600
0
        (elfout.ehdr.e_phnum * elfout.ehdr.e_phentsize) + (char *)&elfout );
601
    // checksum for loader + p_info
602
0
    lp->l_checksum = 0;
603
0
    lp->l_magic = UPX_ELF_MAGIC;
604
0
    set_te16(&lp->l_lsize, (upx_uint16_t) lsize);
605
0
    lp->l_version = (unsigned char) ph.version;
606
0
    lp->l_format  = (unsigned char) ph.format;
607
    // INFO: lp->l_checksum is currently unused
608
0
    set_te32(&lp->l_checksum, upx_adler32(ptr, lsize));
609
0
}
610
611
612
void PackLinuxI386::updateLoader(OutputFile *fo)
613
0
{
614
0
    elfout.ehdr.e_entry = fo->getBytesWritten() + elfout.phdr[0].p_vaddr;
615
0
}
616
617
/* vim:set ts=4 sw=4 et: */