From 78185962719bc53fa75086ff15b9b7eef2b4979b Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sun, 20 Feb 2005 00:59:42 +0000 Subject: [PATCH] stub loader for Linux Elf PowerPC32 Added Files: m_lx_elfppc32.c l_lx_elfppc32.lds fold_elfppc32.S l_lx_elfppc32.S fold_elfppc32.h l_lx_elfppc32.h [these two created by Makefile] committer: jreiser 1108861182 +0000 --- src/stub/fold_elfppc32.S | 89 +++++++++ src/stub/fold_elfppc32.h | 181 ++++++++++++++++++ src/stub/l_lx_elfppc32.S | 97 ++++++++++ src/stub/l_lx_elfppc32.h | 60 ++++++ src/stub/l_lx_elfppc32.lds | 48 +++++ src/stub/m_lx_elfppc32.c | 364 +++++++++++++++++++++++++++++++++++++ 6 files changed, 839 insertions(+) create mode 100644 src/stub/fold_elfppc32.S create mode 100644 src/stub/fold_elfppc32.h create mode 100644 src/stub/l_lx_elfppc32.S create mode 100644 src/stub/l_lx_elfppc32.h create mode 100644 src/stub/l_lx_elfppc32.lds create mode 100644 src/stub/m_lx_elfppc32.c diff --git a/src/stub/fold_elfppc32.S b/src/stub/fold_elfppc32.S new file mode 100644 index 00000000..c85a0820 --- /dev/null +++ b/src/stub/fold_elfppc32.S @@ -0,0 +1,89 @@ +#include "ppc_regs.h" + +sz_b_info= 12 + sz_unc= 0 + sz_cpr= 4 + +sz_l_info= 12 +sz_p_info= 12 + +OVERHEAD= 2048 +LINKAREA= 2*4 # SysV C linkage area: (sp, lr) +/* In: + r31= &decompress; also 8+ (char *)&(offset to {l_info; p_info; b_info}) +*/ +fold_begin: + call L90 +#include "ppc_bxx.S" + +/* The SysV convention for argument registers after execve is nice: + a0= argc + a1= argv + a2= envp + a3= auxvp + a4= fini + sp= ~0xf & (-2*4 + (void *)&argc) # 0(sp): old_sp, pc + Instead, Linux gives only + sp= &{argc,argv...,0,env...,0,auxv...,strings} # 16-byte aligned? + We must figure out the rest, particularly auxvp. +*/ +zfind: + lwz t0,0(a6); addi a6,a6,4 + cmpi cr7,t0,0; bne+ cr7,zfind + ret +L90: + mflr a5 # &ppcbxx: f_unfilter + lwz a6,0(sp) # sp at execve + call zfind # a6= &env + call zfind # a6= &Elf32_auxv + mr a4,r31 # &decompress: f_expand + la a2,-OVERHEAD(sp) # &Elf32_Ehdr temporary space + lwz a1,-8(r31) # total size = offset to {l_info; p_info; b_info} + subf a0,a1,r31 # &l_info + lwz a3,sz_unc+sz_p_info+sz_l_info(a0) # sz_elf_headers + addi sp,sp,-(LINKAREA+OVERHEAD) + call upx_main # Out: a0= entry +/* entry= upx_main(l_info *, total_size, Elf32_Ehdr *, sz_ehdr, f_decomp, f_unf, Elf32_auxv_t *) */ + + mtlr a0 # entry address + lmw r2,4+LINKAREA+OVERHEAD(sp) # restore registers r2 thru r31 + lwz r1, LINKAREA+OVERHEAD(sp) # restore r1; deallocate space + trap # debugging + ret # enter /lib/ld.so.1 + +SYS_exit= 1 +SYS_fork= 2 +SYS_read= 3 +SYS_write= 4 +SYS_open= 5 +SYS_close= 6 + +SYS_brk= 45 +SYS_mmap= 90 +SYS_munmap= 91 +SYS_mprotect= 125 + +mmap: .globl mmap + li 0,SYS_mmap +sysgo: + sc + bns+ no_fail # 'bns': branch if No Summary[Overflow] + li a0,-1 # failure; IGNORE errno +no_fail: + ret + +exit: .globl exit + li 0,SYS_exit; b sysgo +read: .globl read + li 0,SYS_read; b sysgo +open: .globl open + li 0,SYS_open; b sysgo +close: .globl close + li 0,SYS_close; b sysgo +mprotect: .globl mprotect + li 0,SYS_mprotect; b sysgo +munmap: .globl munmap + li 0,SYS_munmap; b sysgo +brk: .globl brk + li 0,SYS_brk; b sysgo + diff --git a/src/stub/fold_elfppc32.h b/src/stub/fold_elfppc32.h new file mode 100644 index 00000000..e64128ce --- /dev/null +++ b/src/stub/fold_elfppc32.h @@ -0,0 +1,181 @@ +/* fold_elfppc32.h -- created from fold_elfppc32.bin, 2356 (0x934) bytes + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2005 Laszlo Molnar + All Rights Reserved. + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer Laszlo Molnar + + */ + + +#define LINUX_ELFPPC32_FOLD_ADLER32 0x15a29be0 +#define LINUX_ELFPPC32_FOLD_CRC32 0x2e07dd6d + +unsigned char linux_elfppc32_fold[2356] = { +127, 69, 76, 70, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 0 */ + 0, 2, 0, 20, 0, 0, 0, 1, 0, 16, 0,128, 0, 0, 0, 52, /* 0x 10 */ + 0, 0, 7,244, 0, 0, 0, 0, 0, 52, 0, 32, 0, 2, 0, 40, /* 0x 20 */ + 0, 8, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 16, 0, 0, /* 0x 30 */ + 0, 16, 0, 0, 0, 0, 7,164, 0, 0, 7,164, 0, 0, 0, 5, /* 0x 40 */ + 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 7,164, 0, 16, 7,164, /* 0x 50 */ + 0, 16, 7,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, /* 0x 60 */ + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 70 */ + 72, 0, 0,113, 40, 6, 0,208, 76,130, 0, 32, 84,132,240,191, /* 0x 80 */ + 77,130, 0, 32, 56,165, 1, 32,124,103, 27,120, 56, 99,255,252, /* 0x 90 */ +124,137, 3,166, 72, 0, 0, 32,125, 99, 16, 80,125,107, 58, 20, /* 0x a0 */ + 85,107, 80, 42,125,107, 86,112, 81, 98, 1,186,144, 67, 0, 0, /* 0x b0 */ + 78, 64, 0, 32,132, 67, 0, 4, 84, 75, 85,190,124, 11, 40, 64, /* 0x c0 */ + 65,162,255,216, 66, 0,255,240, 78,128, 0, 32,128, 73, 0, 0, /* 0x d0 */ + 57, 41, 0, 4, 47,130, 0, 0, 64,158,255,244, 78,128, 0, 32, /* 0x e0 */ +125, 8, 2,166,129, 33, 0, 0, 75,255,255,229, 75,255,255,225, /* 0x f0 */ +127,231,251,120, 56,161,248, 0,128,159,255,248,124,100,248, 80, /* 0x 100 */ +128,195, 0, 24, 56, 33,247,248, 72, 0, 5, 61,124,104, 3,166, /* 0x 110 */ +184, 65, 8, 12,128, 33, 8, 8,127,224, 0, 8, 78,128, 0, 32, /* 0x 120 */ + 56, 0, 0, 90, 68, 0, 0, 2, 64,163, 0, 8, 56, 96,255,255, /* 0x 130 */ + 78,128, 0, 32, 56, 0, 0, 1, 75,255,255,236, 56, 0, 0, 3, /* 0x 140 */ + 75,255,255,228, 56, 0, 0, 5, 75,255,255,220, 56, 0, 0, 6, /* 0x 150 */ + 75,255,255,212, 56, 0, 0,125, 75,255,255,204, 56, 0, 0, 91, /* 0x 160 */ + 75,255,255,196, 56, 0, 0, 45, 75,255,255,188,124, 8, 2,166, /* 0x 170 */ +148, 33,255,240,144, 1, 0, 20,128, 3, 0, 0,129, 35, 0, 4, /* 0x 180 */ +127,128, 40, 64, 64,188, 0, 12, 56, 96, 0,127, 75,255,255,169, /* 0x 190 */ + 47,133, 0, 0, 65,158, 0, 28,124,169, 3,166,136, 9, 0, 0, /* 0x 1a0 */ + 57, 41, 0, 1,152, 4, 0, 0, 56,132, 0, 1, 66, 0,255,240, /* 0x 1b0 */ +128, 3, 0, 0,129, 35, 0, 4,124, 5, 0, 80,144, 3, 0, 0, /* 0x 1c0 */ +125, 41, 42, 20,128, 1, 0, 20, 56, 33, 0, 16,145, 35, 0, 4, /* 0x 1d0 */ +124, 8, 3,166, 78,128, 0, 32,124, 8, 2,166,148, 33,255,192, /* 0x 1e0 */ +191,129, 0, 48,124,159, 35,120,124,126, 27,120,124,188, 43,120, /* 0x 1f0 */ +144, 1, 0, 68,124,221, 51,120,128, 4, 0, 0, 47,128, 0, 0, /* 0x 200 */ + 65,158, 1, 32, 56,160, 0, 12,127,195,243,120, 56,129, 0, 16, /* 0x 210 */ + 75,255,255, 93,129, 33, 0, 16,128,161, 0, 20, 47,137, 0, 0, /* 0x 220 */ + 64,190, 0, 36, 60, 0, 33, 88, 96, 0, 80, 85,127,133, 0, 0, /* 0x 230 */ + 64,190, 0, 28,128, 30, 0, 0, 47,128, 0, 0, 65,190, 0,228, /* 0x 240 */ + 72, 0, 0, 12, 47,133, 0, 0, 64,190, 0, 12, 56, 96, 0,127, /* 0x 250 */ + 75,255,254,229,127, 5, 72, 64, 65,185,255,244,128, 31, 0, 0, /* 0x 260 */ +127,137, 0, 64, 65,189,255,232,128, 31, 0, 4, 64,152, 0,132, /* 0x 270 */ +124,164, 43,120,128,126, 0, 4,124, 5, 3,120, 56,193, 0, 32, /* 0x 280 */ +136,225, 0, 24,127,136, 3,166, 78,128, 0, 33, 47,131, 0, 0, /* 0x 290 */ + 64,190,255,188,128,129, 0, 32,128, 1, 0, 16,127,132, 0, 0, /* 0x 2a0 */ + 64,190,255,172,136,193, 0, 25, 49, 61,255,255,124, 9,233, 16, /* 0x 2b0 */ +125, 38, 0,208, 85, 41, 15,254,125, 43, 0, 57, 65,162, 0, 20, /* 0x 2c0 */ +128,127, 0, 4,127,168, 3,166,136,161, 0, 26, 78,128, 0, 33, /* 0x 2d0 */ +128, 30, 0, 4,129, 97, 0, 20,129, 62, 0, 0,124, 0, 90, 20, /* 0x 2e0 */ +125, 43, 72, 80,144, 30, 0, 4,145, 62, 0, 0, 72, 0, 0, 16, /* 0x 2f0 */ +124, 4, 3,120,127,195,243,120, 75,255,254,117,129, 97, 0, 16, /* 0x 300 */ +129, 63, 0, 0,128, 31, 0, 4,125, 43, 72, 80, 47,137, 0, 0, /* 0x 310 */ +124, 0, 90, 20,144, 31, 0, 4,145, 63, 0, 0, 75,255,254,228, /* 0x 320 */ +128, 1, 0, 68,187,129, 0, 48, 56, 33, 0, 64,124, 8, 3,166, /* 0x 330 */ + 78,128, 0, 32,124,128, 35,121,124, 9, 3,166, 77,130, 0, 32, /* 0x 340 */ + 56, 0, 0, 0,152, 3, 0, 0, 56, 99, 0, 1, 66, 0,255,248, /* 0x 350 */ + 78,128, 0, 32, 44, 3, 0, 0, 77,130, 0, 32,112, 96, 0, 1, /* 0x 360 */ + 76,130, 0, 32, 49, 68,255,255,125,106, 33, 16,128, 3, 0, 0, /* 0x 370 */ +127,128, 32, 0,104, 9, 0, 1, 33, 73, 0, 0,125, 42, 73, 20, /* 0x 380 */ +125, 42, 88, 57, 65,158, 0, 8, 65,162, 0, 16,144,163, 0, 4, /* 0x 390 */ +144,131, 0, 0, 78,128, 0, 32, 56, 99, 0, 8, 75,255,255,208, /* 0x 3a0 */ +124, 8, 2,166,148, 33,255,160,125,128, 0, 38,190, 65, 0, 40, /* 0x 3b0 */ +124,122, 27,120,124,151, 35,120,144, 1, 0,100,124,178, 43,120, /* 0x 3c0 */ +161, 67, 0, 44,124,211, 51,120,160, 3, 0, 16,124,244, 59,120, /* 0x 3d0 */ + 53, 74,255,255,129, 35, 0, 28,104, 0, 0, 3,145,129, 0, 36, /* 0x 3e0 */ +124, 0, 0,208,127, 99, 74, 20, 84, 3, 46,246,125, 21, 67,120, /* 0x 3f0 */ + 56, 99, 0, 34,127,107,219,120, 59,128,255,255, 59,192, 0, 0, /* 0x 400 */ + 59,224, 0, 0, 65,128, 0, 72, 57, 74, 0, 1,125, 73, 3,166, /* 0x 410 */ +128, 11, 0, 0, 47,128, 0, 1, 64,190, 0, 44,129, 43, 0, 8, /* 0x 420 */ +127,137,224, 64, 64,156, 0, 12,131,235, 0, 16,125, 60, 75,120, /* 0x 430 */ +128, 11, 0, 20,124, 0, 74, 20,127,158, 0, 64, 64,156, 0, 8, /* 0x 440 */ +124, 30, 3,120, 57,107, 0, 32, 66, 0,255,200, 87,128, 5, 62, /* 0x 450 */ + 87,156, 0, 38,125, 60,240, 80,127,255, 2, 20, 57, 41, 15,255, /* 0x 460 */ + 56, 31, 15,255, 85, 62, 0, 38, 84, 31, 0, 38,124,102, 27,120, /* 0x 470 */ +127,196,243,120, 56,160, 0, 7, 56,224, 0, 0, 57, 0, 0, 0, /* 0x 480 */ +127,131,227,120, 75,255,252,157,124,159,240, 80,124, 3,242, 20, /* 0x 490 */ +124,125, 27,120,124, 99,250, 20,144, 1, 0, 8, 75,255,252,193, /* 0x 4a0 */ +160, 26, 0, 44, 58,192, 0, 0,127, 60,232, 80,127,150, 0, 0, /* 0x 4b0 */ + 64,156, 1, 84, 46, 23, 0, 0, 65,146, 0, 40,128, 27, 0, 0, /* 0x 4c0 */ + 47,128, 0, 6, 64,190, 0, 28,128,187, 0, 8,126, 99,155,120, /* 0x 4d0 */ + 56,128, 0, 3,124,165,202, 20, 75,255,254,125, 72, 0, 1, 20, /* 0x 4e0 */ +128, 27, 0, 0, 47,128, 0, 1, 64,190, 1, 8,129, 27, 0, 8, /* 0x 4f0 */ + 60, 0,115, 81,129, 59, 0, 24, 96, 0, 98, 64,129, 91, 0, 20, /* 0x 500 */ + 85, 30, 5, 62,129,123, 0, 16, 85, 41, 22,250,124, 0, 76, 48, /* 0x 510 */ +127,136, 82, 20,127,254, 64, 80, 84, 24, 7,126,145, 97, 0, 16, /* 0x 520 */ +127,171,242, 20,145, 1, 0, 20,127,255,202, 20,127,156,202, 20, /* 0x 530 */ + 65,146, 0, 12, 56,192, 0, 50, 72, 0, 0, 8, 56,192, 0, 18, /* 0x 540 */ +129, 27, 0, 4,127,227,251,120,127,164,235,120, 56,160, 0, 3, /* 0x 550 */ +125, 30, 64, 80,126, 71,147,120, 75,255,251,201,127,159, 24, 0, /* 0x 560 */ + 64,158, 0, 84, 65,178, 0, 24,126,227,187,120, 56,129, 0, 16, /* 0x 570 */ +126,133,163,120,126,166,171,120, 75,255,252, 97,127,196,243,120, /* 0x 580 */ +127,227,251,120, 75,255,253,177,124, 29, 0,208, 84, 30, 5, 62, /* 0x 590 */ +124,127,234, 20,127,196,243,120, 75,255,253,157,127,227,251,120, /* 0x 5a0 */ +127,164,235,120,127, 5,195,120, 75,255,251,173, 47,131, 0, 0, /* 0x 5b0 */ + 65,190, 0, 12, 56, 96, 0,127, 75,255,251,125,124, 29,242, 20, /* 0x 5c0 */ +127,255, 2, 20,127,159,224, 64, 64,188, 0, 40,124,159,224, 80, /* 0x 5d0 */ +127, 5,195,120,127,227,251,120, 56,192, 0, 50, 56,224, 0, 0, /* 0x 5e0 */ + 57, 0, 0, 0, 75,255,251, 61,127,159, 24, 0, 64,190,255,200, /* 0x 5f0 */ +160, 26, 0, 44, 58,214, 0, 1, 59,123, 0, 32,127,150, 0, 0, /* 0x 600 */ + 75,255,254,176, 47,151, 0, 0, 65,158, 0, 24,160, 26, 0, 16, /* 0x 610 */ + 47,128, 0, 3, 65,158, 0, 12,128, 97, 0, 8, 75,255,251, 73, /* 0x 620 */ +128,122, 0, 24,128, 1, 0,100,129,129, 0, 36,124, 99,202, 20, /* 0x 630 */ +124, 8, 3,166,186, 65, 0, 40,125,128,129, 32, 56, 33, 0, 96, /* 0x 640 */ + 78,128, 0, 32,124, 8, 2,166,148, 33,255,192, 56,132,255,232, /* 0x 650 */ +191, 97, 0, 44,144,129, 0, 8,124,191, 43,120,144, 1, 0, 68, /* 0x 660 */ + 56, 3, 0, 24,144, 1, 0, 12,124,229, 59,120,128, 3, 0, 24, /* 0x 670 */ + 56,192, 0, 0,200, 1, 0, 8, 56, 97, 0, 8, 56,129, 0, 16, /* 0x 680 */ + 59,223, 0, 52,125, 61, 75,120,124,251, 59,120,144, 1, 0, 16, /* 0x 690 */ +125, 28, 67,120,216, 1, 0, 24,147,225, 0, 20, 75,255,251, 61, /* 0x 6a0 */ +128,190, 0, 8,127,163,235,120, 56,128, 0, 3, 56,165, 0, 52, /* 0x 6b0 */ + 75,255,252,165,160,191, 0, 44,127,163,235,120, 56,128, 0, 5, /* 0x 6c0 */ + 75,255,252,149,128,191, 0, 24,127,163,235,120, 56,128, 0, 9, /* 0x 6d0 */ + 75,255,252,133,127,103,219,120,127,136,227,120,127,227,251,120, /* 0x 6e0 */ +127,166,235,120, 56,129, 0, 24, 56,160, 0, 0, 59, 96, 0, 0, /* 0x 6f0 */ + 75,255,252,177,160, 31, 0, 44,124,124, 27,120,127,155, 0, 0, /* 0x 700 */ + 64,156, 0,124,128, 30, 0, 0, 59,123, 0, 1, 56,128, 0, 0, /* 0x 710 */ + 56,160, 0, 0, 47,128, 0, 3, 64,190, 0, 88,128,126, 0, 8, /* 0x 720 */ + 75,255,250, 37,127,228,251,120,124,125, 27,121, 56,160, 2, 0, /* 0x 730 */ + 65,128, 0, 40, 75,255,250, 9, 56,128, 0, 0, 47,131, 2, 0, /* 0x 740 */ +127,165,235,120,127,227,251,120, 56,192, 0, 0, 56,224, 0, 0, /* 0x 750 */ + 57, 0, 0, 0, 65,190, 0, 12, 56, 96, 0,127, 75,255,249,217, /* 0x 760 */ + 75,255,252, 65,124,124, 27,120,127,163,235,120, 75,255,249,225, /* 0x 770 */ +160, 31, 0, 44, 59,222, 0, 32, 75,255,255,132,128, 1, 0, 68, /* 0x 780 */ +127,131,227,120,187, 97, 0, 44, 56, 33, 0, 64,124, 8, 3,166, /* 0x 790 */ + 78,128, 0, 32, 0, 71, 67, 67, 58, 32, 40, 71, 78, 85, 41, 32, /* 0x 7a0 */ + 51, 46, 52, 46, 49, 0, 0, 46,115,104,115,116,114,116, 97, 98, /* 0x 7b0 */ + 0, 46,116,101,120,116, 0, 46, 98,115,115, 0, 46,115,100, 97, /* 0x 7c0 */ +116, 97, 0, 46,115,100, 97,116, 97, 50, 0, 46,110,111,116,101, /* 0x 7d0 */ + 46, 71, 78, 85, 45,115,116, 97, 99,107, 0, 46, 99,111,109,109, /* 0x 7e0 */ +101,110,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 7f0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 800 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, /* 0x 810 */ + 0, 0, 0, 1, 0, 0, 0, 6, 0, 16, 0,128, 0, 0, 0,128, /* 0x 820 */ + 0, 0, 7, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, /* 0x 830 */ + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 8, 0, 0, 0, 3, /* 0x 840 */ + 0, 16, 7,164, 0, 0, 7,164, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 850 */ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 22, /* 0x 860 */ + 0, 0, 0, 1, 0, 0, 0, 3, 0, 16, 7,164, 0, 0, 7,164, /* 0x 870 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, /* 0x 880 */ + 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 1, 0, 0, 0, 2, /* 0x 890 */ + 0, 16, 7,164, 0, 0, 7,164, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 8a0 */ + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 37, /* 0x 8b0 */ + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,164, /* 0x 8c0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0x 8d0 */ + 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 0, 1, 0, 0, 0, 0, /* 0x 8e0 */ + 0, 0, 0, 0, 0, 0, 7,164, 0, 0, 0, 18, 0, 0, 0, 0, /* 0x 8f0 */ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 0x 900 */ + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,182, /* 0x 910 */ + 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0x 920 */ + 0, 0, 0, 0 /* 0x 930 */ +}; diff --git a/src/stub/l_lx_elfppc32.S b/src/stub/l_lx_elfppc32.S new file mode 100644 index 00000000..1fdecf7e --- /dev/null +++ b/src/stub/l_lx_elfppc32.S @@ -0,0 +1,97 @@ +/* l_lx_elfppc.S -- Linux program entry point & decompressor (Elf binary) +* +* This file is part of the UPX executable compressor. +* +* Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer +* Copyright (C) 1996-2004 Laszlo Molnar +* Copyright (C) 2000-2005 John F. Reiser +* All Rights Reserved. +* +* UPX and the UCL library are free software; you can redistribute them +* and/or modify them under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; see the file COPYING. +* If not, write to the Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Markus F.X.J. Oberhumer Laszlo Molnar +* +* +* John F. Reiser +* +*/ + +#include "ppc_regs.h" + +/*__MACOS000__*/ +_start: .globl _start + call main # must be exactly 1 instruction; link_register= &decompress +#include "ppc_d_nrv2e.S" + +sz_b_info= 12 + sz_unc= 0 + sz_cpr= 4 + +PROT_READ= 1 +PROT_WRITE= 2 +PROT_EXEC= 4 + +MAP_PRIVATE= 2 +MAP_FIXED= 0x10 +MAP_ANONYMOUS= 0x20 + +SYS_mmap= 90 + +PAGE_SHIFT= 12 +PAGE_SIZE = -(~0< + */ + + +#define LINUX_ELFPPC32_LOADER_ADLER32 0xf2b08e0d +#define LINUX_ELFPPC32_LOADER_CRC32 0x2364b765 + +unsigned char linux_elfppc32_loader[432] = { + 72, 0, 1,161,144,166, 0, 0,124,132, 26, 20, 60, 0,128, 0, /* 0x 0 */ + 61, 32,128, 0, 56, 99,255,255, 56,165,255,255, 57, 64,255,255, /* 0x 10 */ +125,168, 2,166, 72, 0, 0, 40, 57, 32, 0, 1,125, 41, 28, 44, /* 0x 20 */ + 56, 99, 0, 4,124, 9, 0, 64,125, 41, 72, 20, 97, 41, 0, 1, /* 0x 30 */ + 78,128, 0, 32,141, 3, 0, 1,157, 5, 0, 1,124, 9, 0, 64, /* 0x 40 */ +125, 41, 74, 20, 65,162,255,213, 65,129,255,236, 56,224, 0, 1, /* 0x 50 */ + 72, 0, 0, 20, 56,231,255,255,125, 41, 72, 21, 65,162,255,189, /* 0x 60 */ +124,231, 57, 20,125, 41, 72, 21, 65,162,255,177,124,231, 57, 20, /* 0x 70 */ +124, 9, 0, 64,125, 41, 74, 20, 65,162,255,161, 65,160,255,216, /* 0x 80 */ + 57, 0, 0, 0, 52,231,255,253, 84,231, 64, 46, 65,128, 0, 32, /* 0x 90 */ +140, 67, 0, 1,124,234, 16,249,125, 74, 14,112, 65,130, 0,136, /* 0x a0 */ +112, 66, 0, 1, 65,162, 0, 80, 72, 0, 0, 20,124, 9, 0, 64, /* 0x b0 */ +125, 41, 74, 20, 65,162,255,101, 65,161, 0, 60, 57, 0, 0, 1, /* 0x c0 */ +124, 9, 0, 64,125, 41, 74, 20, 65,162,255, 81, 65,161, 0, 40, /* 0x d0 */ +125, 41, 72, 21, 65,162,255, 69,125, 8, 65, 20,124, 9, 0, 64, /* 0x e0 */ +125, 41, 74, 20, 65,162,255, 53, 65,160,255,232, 57, 8, 0, 2, /* 0x f0 */ + 72, 0, 0, 16,125, 41, 72, 21, 65,162,255, 33,125, 8, 65, 20, /* 0x 100 */ + 32,234,250,255, 57, 8, 0, 2,125, 8, 1,148,124,234, 42, 20, /* 0x 110 */ +125, 9, 3,166,141, 7, 0, 1,157, 5, 0, 1, 66, 0,255,248, /* 0x 120 */ + 75,255,255, 28,128, 6, 0, 0,125,168, 3,166, 56,165, 0, 1, /* 0x 130 */ + 56, 99, 0, 1,124,160, 40, 80,124,100, 24, 80,144,166, 0, 0, /* 0x 140 */ + 78,128, 0, 32,127,200, 2,166, 56,192, 0, 50,128,126, 0, 4, /* 0x 150 */ + 56,160, 0, 7,124, 99,242, 20, 56,128, 16, 0, 56, 99, 16, 11, /* 0x 160 */ + 56, 0, 0, 90, 84, 99, 0, 38, 68, 0, 0, 2, 65,131, 0, 32, /* 0x 170 */ +124,104, 3,166, 56,193, 0,124,124,101, 27,120,127,233, 3,166, /* 0x 180 */ +128,158, 0, 4, 56,126, 0, 12, 78,128, 4, 32,127,224, 0, 8, /* 0x 190 */ +148, 33,255,128,188, 65, 0, 4,127,232, 2,166, 75,255,255,169 /* 0x 1a0 */ +}; diff --git a/src/stub/l_lx_elfppc32.lds b/src/stub/l_lx_elfppc32.lds new file mode 100644 index 00000000..e3e741c7 --- /dev/null +++ b/src/stub/l_lx_elfppc32.lds @@ -0,0 +1,48 @@ +/* l_lx_elfppc.lds -- + + This file is part of the UPX executable compressor. + + Copyright (C) 2000-2005 John F. Reiser + All Rights Reserved. + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer Laszlo Molnar + + + John F. Reiser + + */ + + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +/*ENTRY(_start)*/ +PHDRS +{ + text PT_LOAD FILEHDR PHDRS ; + data PT_LOAD ; /* for setting brk(0) */ +} +SECTIONS +{ + . = 0x00100000 + SIZEOF_HEADERS + 12; /* 12==sizeof(l_info) */ + .text : { + *(.text) + *(.data) + } : text + .data : { + } : data +} diff --git a/src/stub/m_lx_elfppc32.c b/src/stub/m_lx_elfppc32.c new file mode 100644 index 00000000..777c7bcc --- /dev/null +++ b/src/stub/m_lx_elfppc32.c @@ -0,0 +1,364 @@ +/* m_lx_elfppc32.c -- stub loader for Linux ELF PowerPC32 executable + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2004 Laszlo Molnar + Copyright (C) 2000-2004 John F. Reiser + All Rights Reserved. + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer Laszlo Molnar + + + John F. Reiser + + */ + + +#include "linux.hh" + +/************************************************************************* +// configuration section +**************************************************************************/ + +// In order to make it much easier to move this code at runtime and execute +// it at an address different from it load address: there must be no +// static data, and no string constants. + +#define MAX_ELF_HDR 512 // Elf32_Ehdr + n*Elf32_Phdr must fit in this + + +/************************************************************************* +// "file" util +**************************************************************************/ + +typedef struct { + size_t size; // must be first to match size[0] uncompressed size + char *buf; +} Extent; + + +static void +xread(Extent *x, char *buf, size_t count) +{ + char *p=x->buf, *q=buf; + size_t j; + if (x->size < count) { + exit(127); + } + for (j = count; 0!=j--; ++p, ++q) { + *q = *p; + } + x->buf += count; + x->size -= count; +} + + +/************************************************************************* +// util +**************************************************************************/ + +#if 1 //{ save space +#define ERR_LAB error: exit(127); +#define err_exit(a) goto error +#else //}{ save debugging time +#define ERR_LAB +static void +err_exit(int a) +{ + (void)a; // debugging convenience + exit(127); +} +#endif //} + +/************************************************************************* +// UPX & NRV stuff +**************************************************************************/ + +typedef void f_unfilter( + nrv_byte *, // also addvalue + nrv_uint, + unsigned cto8, // junk in high 24 bits + unsigned ftid +); +typedef int f_expand( + const nrv_byte *, nrv_uint, + nrv_byte *, nrv_uint *, unsigned ); + +static void +unpackExtent( + Extent *const xi, // input + Extent *const xo, // output + f_expand *const f_decompress, + f_unfilter *f_unf +) +{ + while (xo->size) { + struct b_info h; + // Note: if h.sz_unc == h.sz_cpr then the block was not + // compressible and is stored in its uncompressed form. + + // Read and check block sizes. + xread(xi, (char *)&h, sizeof(h)); + if (h.sz_unc == 0) { // uncompressed size 0 -> EOF + if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic + err_exit(2); + if (xi->size != 0) // all bytes must be written + err_exit(3); + break; + } + if (h.sz_cpr <= 0) { + err_exit(4); +ERR_LAB + } + if (h.sz_cpr > h.sz_unc + || h.sz_unc > xo->size ) { + err_exit(5); + } + // Now we have: + // assert(h.sz_cpr <= h.sz_unc); + // assert(h.sz_unc > 0 && h.sz_unc <= blocksize); + // assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize); + + if (h.sz_cpr < h.sz_unc) { // Decompress block + nrv_uint out_len; + int const j = (*f_decompress)(xi->buf, h.sz_cpr, xo->buf, &out_len, + h.b_method); + if (j != 0 || out_len != (nrv_uint)h.sz_unc) + err_exit(7); + if (h.b_ftid!=0 && f_unf) { // have filter + (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid); + } + xi->buf += h.sz_cpr; + xi->size -= h.sz_cpr; + } + else { // copy literal block + xread(xi, xo->buf, h.sz_cpr); + } + xo->buf += h.sz_unc; + xo->size -= h.sz_unc; + } +} + +// Create (or find) an escape hatch to use when munmapping ourselves the stub. +// Called by do_xmap to create it, and by assembler code to find it. +static void * +make_hatch(Elf32_Phdr const *const phdr) +{ + return 0; +} + +static void +upx_bzero(char *p, size_t len) +{ + if (len) do { + *p++= 0; + } while (--len); +} +#define bzero upx_bzero + + +static void +auxv_up(Elf32_auxv_t *av, int const type, unsigned const value) +{ + if (av && 0==(1&(int)av)) /* PT_INTERP usually inhibits, except for hatch */ + for (;; ++av) { + if (av->a_type==type || (av->a_type==AT_IGNORE && type!=AT_NULL)) { + av->a_type = type; + av->a_un.a_val = value; + return; + } + } +} + +// The PF_* and PROT_* bits are {1,2,4}; the conversion table fits in 32 bits. +#define REP8(x) \ + ((x)|((x)<<4)|((x)<<8)|((x)<<12)|((x)<<16)|((x)<<20)|((x)<<24)|((x)<<28)) +#define EXP8(y) \ + ((1&(y)) ? 0xf0f0f0f0 : (2&(y)) ? 0xff00ff00 : (4&(y)) ? 0xffff0000 : 0) +#define PF_TO_PROT(pf) \ + ((PROT_READ|PROT_WRITE|PROT_EXEC) & ( \ + ( (REP8(PROT_EXEC ) & EXP8(PF_X)) \ + |(REP8(PROT_READ ) & EXP8(PF_R)) \ + |(REP8(PROT_WRITE) & EXP8(PF_W)) \ + ) >> ((pf & (PF_R|PF_W|PF_X))<<2) )) + + +// Find convex hull of PT_LOAD (the minimal interval which covers all PT_LOAD), +// and mmap that much, to be sure that a kernel using exec-shield-randomize +// won't place the first piece in a way that leaves no room for the rest. +static unsigned long // returns relocation constant +xfind_pages(unsigned mflags, Elf32_Phdr const *phdr, int phnum, + char **const p_brk +) +{ + size_t lo= ~0, hi= 0, szlo= 0; + char *addr; + mflags += MAP_PRIVATE | MAP_ANONYMOUS; // '+' can optimize better than '|' + for (; --phnum>=0; ++phdr) if (PT_LOAD==phdr->p_type) { + if (phdr->p_vaddr < lo) { + lo = phdr->p_vaddr; + szlo = phdr->p_filesz; + } + if (hi < (phdr->p_memsz + phdr->p_vaddr)) { + hi = phdr->p_memsz + phdr->p_vaddr; + } + } + szlo += ~PAGE_MASK & lo; // page fragment on lo edge + lo -= ~PAGE_MASK & lo; // round down to page boundary + hi = PAGE_MASK & (hi - lo - PAGE_MASK -1); // page length + szlo = PAGE_MASK & (szlo - PAGE_MASK -1); // page length + addr = mmap((void *)lo, hi, PROT_READ|PROT_WRITE|PROT_EXEC, mflags, 0, 0); + *p_brk = hi + addr; // the logical value of brk(0) + munmap(szlo + addr, hi - szlo); // desirable if PT_LOAD non-contiguous + return (unsigned long)addr - lo; +} + +static Elf32_Addr // entry address +do_xmap( + Elf32_Ehdr const *const ehdr, + Extent *const xi, + int const fdi, + Elf32_auxv_t *const av, + f_expand *const f_decompress, + f_unfilter *const f_unf +) +{ + Elf32_Phdr const *phdr = (Elf32_Phdr const *) (ehdr->e_phoff + + (char const *)ehdr); + char *v_brk; + unsigned long const reloc = xfind_pages( + ((ET_DYN!=ehdr->e_type) ? MAP_FIXED : 0), phdr, ehdr->e_phnum, &v_brk); + int j; + for (j=0; j < ehdr->e_phnum; ++phdr, ++j) + if (xi && PT_PHDR==phdr->p_type) { + auxv_up(av, AT_PHDR, phdr->p_vaddr + reloc); + } else + if (PT_LOAD==phdr->p_type) { + unsigned const prot = PF_TO_PROT(phdr->p_flags); + Extent xo; + size_t mlen = xo.size = phdr->p_filesz; + char *addr = xo.buf = (char *)phdr->p_vaddr; + char *haddr = phdr->p_memsz + addr; + size_t frag = (int)addr &~ PAGE_MASK; + mlen += frag; + addr -= frag; + addr += reloc; + haddr += reloc; + + if (addr != mmap(addr, mlen, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | (xi ? MAP_ANONYMOUS : 0), + fdi, phdr->p_offset - frag) ) { + err_exit(8); + } + if (xi) { + unpackExtent(xi, &xo, f_decompress, f_unf); + } + bzero(addr, frag); // fragment at lo end + frag = (-mlen) &~ PAGE_MASK; // distance to next page boundary + bzero(mlen+addr, frag); // fragment at hi end + if (xi) { + void *const hatch = make_hatch(phdr); + if (0!=hatch) { + /* always update AT_NULL, especially for compressed PT_INTERP */ + auxv_up((Elf32_auxv_t *)(~1 & (int)av), AT_NULL, (unsigned)hatch); + } + } + if (0!=mprotect(addr, mlen, prot)) { + err_exit(10); +ERR_LAB + } + addr += mlen + frag; /* page boundary on hi end */ + if (addr < haddr) { // need pages for .bss + if (addr != mmap(addr, haddr - addr, prot, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ) ) { + err_exit(9); + } + } + } + if (xi) { // 1st call (main); also have (0!=av) here + if (ET_DYN!=ehdr->e_type) { + // Needed only if compressed shell script invokes compressed shell. + brk(v_brk); + } + } + return ehdr->e_entry + reloc; +} + + +/************************************************************************* +// upx_main - called by our entry code +**************************************************************************/ + +void *upx_main( + struct l_info const *const li, + size_t const sz_compressed, // total length + Elf32_Ehdr *const ehdr, // temp char[sz_ehdr] for decompressing + size_t const sz_ehdr, + f_expand *const f_decompress, + f_unfilter *const f_unf, + Elf32_auxv_t *const av +) +{ + Elf32_Phdr const *phdr = (Elf32_Phdr const *)(1+ ehdr); + Elf32_Addr entry; + + Extent xi, xo, xi0; + xi.buf = (char *)(1+ (struct p_info const *)(1+ li)); // &b_info + xi.size = sz_compressed - (sizeof(struct l_info) + sizeof(struct p_info)); + xo.buf = (char *)ehdr; + xo.size = ((struct b_info const *)xi.buf)->sz_unc; + xi0 = xi; + + // ehdr = Uncompress Ehdr and Phdrs + unpackExtent(&xi, &xo, f_decompress, 0); // never filtered? + + // AT_PHDR.a_un.a_val is set again by do_xmap if PT_PHDR is present. + auxv_up(av, AT_PHDR , (unsigned)(1+(Elf32_Ehdr *)phdr->p_vaddr)); + auxv_up(av, AT_PHNUM , ehdr->e_phnum); + auxv_up(av, AT_ENTRY , (unsigned)ehdr->e_entry); + //auxv_up(av, AT_PHENT , ehdr->e_phentsize); /* this can never change */ + //auxv_up(av, AT_PAGESZ, PAGE_SIZE); /* ld-linux.so.2 does not need this */ + + entry = do_xmap(ehdr, &xi0, 0, av, f_decompress, f_unf); + + { // Map PT_INTERP program interpreter + int j; + for (j=0; j < ehdr->e_phnum; ++phdr, ++j) if (PT_INTERP==phdr->p_type) { + char const *const iname = (char const *)phdr->p_vaddr; + int const fdi = open(iname, O_RDONLY, 0); + if (0 > fdi) { + err_exit(18); + } + if (MAX_ELF_HDR!=read(fdi, (void *)ehdr, MAX_ELF_HDR)) { +ERR_LAB + err_exit(19); + } + entry = do_xmap(ehdr, 0, fdi, 0, 0, 0); + close(fdi); + } + } + + return (void *)entry; +} + + +/* +vi:ts=4:et:nowrap +*/ +