1 /* p_lx_exc.cpp --
2 
3    This file is part of the UPX executable compressor.
4 
5    Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer
6    Copyright (C) 1996-2020 Laszlo Molnar
7    Copyright (C) 2001-2020 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 #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 
PackLinuxI386(InputFile * f)57 PackLinuxI386::PackLinuxI386(InputFile *f) : super(f),
58     ei_osabi(Elf32_Ehdr::ELFOSABI_LINUX), osabi_note(NULL)
59 {
60     bele = &N_BELE_RTP::le_policy;
61 }
62 
PackBSDI386(InputFile * f)63 PackBSDI386::PackBSDI386(InputFile *f) : super(f)
64 {
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     if (Elf32_Ehdr::ELFOSABI_LINUX==opt->o_unix.osabi0) {
69         // Disallow an incompatibility.
70         ei_osabi = Elf32_Ehdr::ELFOSABI_NONE;
71     }
72     else {
73         ei_osabi = opt->o_unix.osabi0;  // might be ELFOSABI_NONE
74     }
75 }
76 
77 static const
78 #include "stub/i386-linux.elf.execve-entry.h"
79 static const
80 #include "stub/i386-linux.elf.execve-fold.h"
81 
82 static const
83 #include "stub/i386-bsd.elf.execve-entry.h"
84 static const
85 #include "stub/i386-bsd.elf.execve-fold.h"
86 
87 
getCompressionMethods(int method,int level) const88 const int *PackLinuxI386::getCompressionMethods(int method, int level) const
89 {
90     return Packer::getDefaultCompressionMethods_le32(method, level);
91 }
92 
getFilters() const93 const int *PackLinuxI386::getFilters() const
94 {
95     static const int filters[] = {
96         0x49, 0x46,
97         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     FT_END };
104     return filters;
105 }
106 
107 static void
set_stub_brk(Elf_LE32_Phdr * const phdr1,unsigned brka)108 set_stub_brk(Elf_LE32_Phdr *const phdr1, unsigned brka)
109 {
110 #define PAGE_MASK (~0ul<<12)
111         // linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary
112         unsigned const brkb = brka | ((0==(~PAGE_MASK & brka)) ? 0x20 : 0);
113         phdr1->p_type = PT_LOAD;  // be sure
114         phdr1->p_offset = ~PAGE_MASK & brkb;
115         phdr1->p_vaddr = brkb;
116         phdr1->p_paddr = brkb;
117         phdr1->p_filesz = 0;
118         phdr1->p_memsz =  0;
119         if (0==phdr1->p_flags) {
120             phdr1->p_flags = Elf32_Phdr::PF_R|Elf32_Phdr::PF_W;
121         }
122         if (0==phdr1->p_align) {
123             phdr1->p_align = 0x1000;
124         }
125 #undef PAGE_MASK
126 }
127 
128 void
generateElfHdr(OutputFile * fo,void const * proto,unsigned const brka)129 PackLinuxI386::generateElfHdr(
130     OutputFile *fo,
131     void const *proto,
132     unsigned const brka
133 )
134 {
135     cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout;
136     cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout;
137     memcpy(h3, proto, sizeof(*h3));  // reads beyond, but OK
138 
139     assert(h2->ehdr.e_phoff     == sizeof(Elf32_Ehdr));
140     assert(h2->ehdr.e_shoff     == 0);
141     assert(h2->ehdr.e_ehsize    == sizeof(Elf32_Ehdr));
142     assert(h2->ehdr.e_phentsize == sizeof(Elf32_Phdr));
143     assert(h2->ehdr.e_shnum     == 0);
144 
145 #if 0  //{
146     unsigned identsize;
147     char const *const ident = getIdentstr(&identsize);
148 #endif  //}
149     h2->phdr[0].p_filesz = sizeof(*h2);  // + identsize;
150     h2->phdr[0].p_memsz  = h2->phdr[0].p_filesz;
151 
152     // Info for OS kernel to set the brk()
153     if (brka) {
154         set_stub_brk(&h2->phdr[1], brka);
155     }
156 
157     if (ph.format==UPX_F_LINUX_i386
158     ||  ph.format==UPX_F_LINUX_SH_i386
159     ||  ph.format==UPX_F_BSD_i386
160     ) {
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         assert(h2->ehdr.e_phnum==2);
167         memset(&h2->linfo, 0, sizeof(h2->linfo));
168         fo->write(h2, sizeof(*h2));
169     }
170     else if (ph.format==UPX_F_LINUX_ELFI_i386) {
171         assert(h3->ehdr.e_phnum==3);
172         memset(&h3->linfo, 0, sizeof(h3->linfo));
173         fo->write(h3, sizeof(*h3));
174     }
175     else {
176         assert(false);  // unknown ph.format, PackUnix::generateElfHdr
177     }
178 }
179 
180 void
pack1(OutputFile * fo,Filter &)181 PackLinuxI386::pack1(OutputFile *fo, Filter &)
182 {
183     // create a pseudo-unique program id for our paranoid stub
184     progid = getRandomId();
185 
186     generateElfHdr(fo, stub_i386_linux_elf_execve_fold, 0);
187 }
188 
189 void
pack1(OutputFile * fo,Filter &)190 PackBSDI386::pack1(OutputFile *fo, Filter &)
191 {
192     // create a pseudo-unique program id for our paranoid stub
193     progid = getRandomId();
194 
195     generateElfHdr(fo, stub_i386_bsd_elf_execve_fold, 0);
196 }
197 
198 void
pack4(OutputFile * fo,Filter & ft)199 PackLinuxI386::pack4(OutputFile *fo, Filter &ft)
200 {
201     overlay_offset = sizeof(elfout.ehdr) +
202         (elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
203         sizeof(l_info) +
204         ((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) ;
205     unsigned nw = fo->getBytesWritten();
206     elfout.phdr[0].p_filesz = nw;
207     nw = 0u-((0u-elfout.phdr[0].p_align) & (0u-nw));  // ALIGN_UP
208     super::pack4(fo, ft);  // write PackHeader and overlay_offset
209     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     elfout.phdr[0].p_memsz =  elfout.phdr[0].p_filesz;
275 #endif  /*}*/
276 
277     // rewrite Elf header
278     fo->seek(0, SEEK_SET);
279     fo->rewrite(&elfout, overlay_offset);
280 }
281 
282 static unsigned
umax(unsigned a,unsigned b)283 umax(unsigned a, unsigned b)
284 {
285     if (a <= b) {
286         return b;
287     }
288     return a;
289 }
290 
newLinker() const291 Linker *PackLinuxI386::newLinker() const
292 {
293     return new ElfLinkerX86;
294 }
295 
296 void
buildLinuxLoader(upx_byte const * const proto,unsigned const szproto,upx_byte const * const fold,unsigned const szfold,Filter const * ft)297 PackLinuxI386::buildLinuxLoader(
298     upx_byte const *const proto,
299     unsigned        const szproto,
300     upx_byte const *const fold,
301     unsigned        const szfold,
302     Filter const *ft
303 )
304 {
305     initLoader(proto, szproto);
306 
307     unsigned fold_hdrlen = 0;
308   if (0 < szfold) {
309     cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
310     fold_hdrlen = sizeof(hf->ehdr) + hf->ehdr.e_phentsize * hf->ehdr.e_phnum +
311          sizeof(l_info);
312     if (0 == get_le32(fold_hdrlen + fold)) {
313         // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils)
314         fold_hdrlen = umax(0x80, fold_hdrlen);
315     }
316   }
317     // This adds the definition to the "library", to be used later.
318     // NOTE: the stub is NOT compressed!  The savings is not worth it.
319     linker->addSection("FOLDEXEC", fold + fold_hdrlen, szfold - fold_hdrlen, 0);
320 
321     n_mru = ft->n_mru;
322 
323 // Rely on "+80CXXXX" [etc] in getDecompressorSections() packer_c.cpp */
324 //    // Here is a quick summary of the format of the output file:
325 //    linker->setLoaderAlignOffset(
326 //            // Elf32_Edhr
327 //        sizeof(elfout.ehdr) +
328 //            // Elf32_Phdr: 1 for exec86, 2 for sh86, 3 for elf86
329 //        (elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
330 //            // checksum UPX! lsize version format
331 //        sizeof(l_info) +
332 //            // PT_DYNAMIC with DT_NEEDED "forwarded" from original file
333 //        ((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) +
334 //            // p_progid, p_filesize, p_blocksize
335 //        sizeof(p_info) +
336 //            // compressed data
337 //        b_len + ph.c_len );
338 //            // entry to stub
339     addLoader("LEXEC000", NULL);
340 
341     if (ft->id) {
342         if (n_mru) {
343             addLoader("LEXEC009", NULL);
344         }
345     }
346     addLoader("LEXEC010", NULL);
347     linker->defineSymbol("filter_cto", ft->cto);
348     linker->defineSymbol("filter_length",
349                          (ft->id & 0xf) % 3 == 0 ? ft->calls :
350                          ft->lastcall - ft->calls * 4);
351     addLoader(getDecompressorSections(), NULL);
352     addLoader("LEXEC015", NULL);
353     if (ft->id) {
354         {  // decompr, unfilter not separate
355             if (0x80==(ft->id & 0xF0)) {
356                 addLoader("LEXEC110", NULL);
357                 if (n_mru) {
358                     addLoader("LEXEC100", NULL);
359                 }
360                 // bug in APP: jmp and label must be in same .asx/.asy
361                 addLoader("LEXEC016", NULL);
362             }
363         }
364         addFilter32(ft->id);
365         {  // decompr always unfilters
366             addLoader("LEXEC017", NULL);
367         }
368     }
369     else {
370         addLoader("LEXEC017", NULL);
371     }
372 
373     addLoader("IDENTSTR", NULL);
374     addLoader("LEXEC020", NULL);
375     addLoader("FOLDEXEC", NULL);
376     if (M_IS_LZMA(ph.method)) {
377         const lzma_compress_result_t *res = &ph.compress_result.result_lzma;
378         upx_uint32_t properties = // lc, lp, pb, dummy
379             (res->lit_context_bits << 0) |
380             (res->lit_pos_bits << 8) |
381             (res->pos_bits << 16);
382         if (linker->bele->isBE()) // big endian - bswap32
383             acc_swab32s(&properties);
384         linker->defineSymbol("lzma_properties", properties);
385         // -2 for properties
386         linker->defineSymbol("lzma_c_len", ph.c_len - 2);
387         linker->defineSymbol("lzma_u_len", ph.u_len);
388         unsigned const stack = getDecompressorWrkmemSize();
389         linker->defineSymbol("lzma_stack_adjust", 0u - stack);
390     }
391     if (0x80==(ft->id & 0xF0)) {
392         int const mru = ft->n_mru ? 1+ ft->n_mru : 0;
393         if (mru && mru!=256) {
394             unsigned const is_pwr2 = (0==((mru -1) & mru));
395             linker->defineSymbol("NMRU", mru - is_pwr2);
396         }
397     }
398     relocateLoader();
399 }
400 
401 void
buildLoader(Filter const * ft)402 PackLinuxI386::buildLoader(Filter const *ft)
403 {
404     unsigned const sz_fold = sizeof(stub_i386_linux_elf_execve_fold);
405     MemBuffer buf(sz_fold);
406     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     checkPatch(NULL, 0, 0, 0);  // reset
412     patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15);   // sleep time
413     patch_le32(buf,sz_fold,"UPX3",progid);
414     patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
415 
416     buildLinuxLoader(
417         stub_i386_linux_elf_execve_entry, sizeof(stub_i386_linux_elf_execve_entry),
418         buf, sz_fold, ft );
419 }
420 
421 void
buildLoader(Filter const * ft)422 PackBSDI386::buildLoader(Filter const *ft)
423 {
424     unsigned const sz_fold = sizeof(stub_i386_bsd_elf_execve_fold);
425     MemBuffer buf(sz_fold);
426     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     checkPatch(NULL, 0, 0, 0);  // reset
432     patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15);   // sleep time
433     patch_le32(buf,sz_fold,"UPX3",progid);
434     patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
435 
436     buildLinuxLoader(
437         stub_i386_bsd_elf_execve_entry, sizeof(stub_i386_bsd_elf_execve_entry),
438         buf, sz_fold, ft );
439 }
440 
441 // FIXME: getLoaderPrefixSize is unused?
getLoaderPrefixSize() const442 int PackLinuxI386::getLoaderPrefixSize() const
443 {
444     return 116;
445 }
446 
447 
448 /*************************************************************************
449 // some ELF utitlity functions
450 **************************************************************************/
451 
452 // basic check of a Linux ELF Ehdr
checkEhdr(const Elf_LE32_Ehdr * ehdr) const453 int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const
454 {
455     const unsigned char * const buf = ehdr->e_ident;
456 
457     if (memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB
458         return -1;
459 
460     // now check the ELF header
461     if (!memcmp(buf+8, "FreeBSD", 7))                  // branded
462         return 1;
463     if (ehdr->e_type != Elf32_Ehdr::ET_EXEC
464     &&  ehdr->e_type != Elf32_Ehdr::ET_DYN )           // executable
465         return 2;
466     if (ehdr->e_machine != Elf32_Ehdr::EM_386)         // Intel 80386
467         return 3;
468     if (ehdr->e_version != Elf32_Ehdr::EV_CURRENT)     // version
469         return 4;
470     if (ehdr->e_phnum < 1)
471         return 5;
472     if (ehdr->e_phentsize != sizeof(Elf32_Phdr))
473         return 6;
474 
475     // check for Linux kernels
476     if (ehdr->e_entry == 0xC0100000)                    // uncompressed vmlinux
477         return 1000;
478     if (ehdr->e_entry == 0x00001000)                    // compressed vmlinux
479         return 1001;
480     if (ehdr->e_entry == 0x00100000)                    // compressed bvmlinux
481         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     return 0;
490 }
491 
492 
493 
494 /*************************************************************************
495 //
496 **************************************************************************/
497 
canPack()498 bool PackLinuxI386::canPack()
499 {
500     if (exetype != 0)
501         return super::canPack();
502 
503     Elf_LE32_Ehdr ehdr;
504     unsigned char *buf = ehdr.e_ident;
505 
506     fi->seek(0, SEEK_SET);
507     fi->readx(&ehdr, sizeof(ehdr));
508     fi->seek(0, SEEK_SET);
509 
510     exetype = 0;
511     const unsigned l = get_le32(buf);
512 
513     int elf = checkEhdr(&ehdr);
514     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         if (elf == 0 && opt->o_unix.force_execve) {
518             exetype = 1;
519 
520             unsigned osabi0 = ehdr.e_ident[Elf32_Ehdr::EI_OSABI];
521             switch (osabi0) {
522             case Elf32_Ehdr::ELFOSABI_LINUX:
523             case Elf32_Ehdr::ELFOSABI_FREEBSD:
524             case Elf32_Ehdr::ELFOSABI_NETBSD:
525             case Elf32_Ehdr::ELFOSABI_OPENBSD:
526                 ei_osabi = osabi0;  // Proudly declares its osabi in Ehdr.
527                 break;
528             default:
529             unsigned const e_phnum = get_te16(&ehdr.e_phnum);
530             if (e_phnum<=(512/sizeof(Elf32_Phdr))) {
531                 union {
532                     unsigned char buf2[512];
533                     //Elf32_Phdr phdr;
534                 } u;
535                 fi->seek(get_te32(&ehdr.e_phoff), SEEK_SET);
536                 fi->readx(u.buf2, sizeof(u.buf2));
537                 fi->seek(0, SEEK_SET);
538                 Elf32_Phdr const *phdr = (Elf32_Phdr *) u.buf2;
539                 for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
540                     if (phdr->PT_NOTE == get_te32(&phdr->p_type)) {
541                         unsigned const offset = get_te32(&phdr->p_offset);
542                         struct Elf32_Note note; memset(&note, 0, sizeof(note));
543                         fi->seek(offset, SEEK_SET);
544                         fi->readx(&note, sizeof(note));
545                         fi->seek(0, SEEK_SET);
546                         if (4==get_te32(&note.descsz)
547                         &&  1==get_te32(&note.type)
548                         &&  0==note.end ) {
549                             if (0==strcmp("NetBSD", (char const *)note.text)) {
550                                 ei_osabi = Elf32_Ehdr::ELFOSABI_NETBSD;
551                                 break;
552                             }
553                             if (0==strcmp("OpenBSD", (char const *)note.text)) {
554                                 ei_osabi = Elf32_Ehdr::ELFOSABI_OPENBSD;
555                                 break;
556                             }
557                         }
558                     }
559                 }
560             }
561             }
562         }
563         if (UPX_F_BSD_i386==getFormat()
564         && !(Elf32_Ehdr::ELFOSABI_FREEBSD==ei_osabi
565           || Elf32_Ehdr::ELFOSABI_NETBSD ==ei_osabi
566           || Elf32_Ehdr::ELFOSABI_OPENBSD==ei_osabi )) {
567             return false;
568         }
569     }
570     else if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
571     {
572         // OMAGIC / NMAGIC / ZMAGIC / QMAGIC
573         exetype = 2;
574         // FIXME: N_TRSIZE, N_DRSIZE
575         // FIXME: check for aout shared libraries
576     }
577     else { // shell scripts and other interpreters
578         if (Elf32_Ehdr::ELFOSABI_LINUX!=ei_osabi) {
579             return false;  // so far, only Linux has runtime stub for shell
580         }
581         else if (!memcmp(buf, "#!/", 3))                    // #!/bin/sh
582             exetype = -1;
583         else if (!memcmp(buf, "#! /", 4))                   // #! /bin/sh
584             exetype = -1;
585         else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4))       // Java bytecode
586             exetype = -2;
587     }
588 
589     return super::canPack();
590 }
591 
592 
patchLoader()593 void PackLinuxI386::patchLoader() { }
594 
595 
patchLoaderChecksum()596 void PackLinuxI386::patchLoaderChecksum()
597 {
598     unsigned char *const ptr = getLoader();
599     l_info *const lp = (l_info *)(sizeof(elfout.ehdr) +
600         (elfout.ehdr.e_phnum * elfout.ehdr.e_phentsize) + (char *)&elfout );
601     // checksum for loader + p_info
602     lp->l_checksum = 0;
603     lp->l_magic = UPX_ELF_MAGIC;
604     set_te16(&lp->l_lsize, (upx_uint16_t) lsize);
605     lp->l_version = (unsigned char) ph.version;
606     lp->l_format  = (unsigned char) ph.format;
607     // INFO: lp->l_checksum is currently unused
608     set_te32(&lp->l_checksum, upx_adler32(ptr, lsize));
609 }
610 
611 
updateLoader(OutputFile * fo)612 void PackLinuxI386::updateLoader(OutputFile *fo)
613 {
614     elfout.ehdr.e_entry = fo->getBytesWritten() + elfout.phdr[0].p_vaddr;
615 }
616 
617 /* vim:set ts=4 sw=4 et: */
618