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(¬e, 0, sizeof(note));
543 fi->seek(offset, SEEK_SET);
544 fi->readx(¬e, sizeof(note));
545 fi->seek(0, SEEK_SET);
546 if (4==get_te32(¬e.descsz)
547 && 1==get_te32(¬e.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