diff --git a/src/stub/fold_machppc32.S b/src/stub/fold_machppc32.S new file mode 100644 index 00000000..00d446fc --- /dev/null +++ b/src/stub/fold_machppc32.S @@ -0,0 +1,123 @@ +/* fold_machppc32.S -- linkage to C code to process Mach-o 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" + +sz_b_info= 12 + sz_unc= 0 + sz_cpr= 4 + +sz_l_info= 12 +sz_p_info= 12 + +/* Mach_ppc_thread_state */ +srr0 = 0*4 +srr1 = 1*4 +reg0 = 2*4 + +reg_cr = 34*4 +reg_xer = 35*4 +reg_lr = 36*4 +reg_ctr = 37*4 +reg_mq = 38*4 +reg_vrsave = 39*4 + + +/* In: + r31= &decompress; also 8+ (char *)&(offset to {l_info; p_info; b_info}) +*/ +fold_begin: + call L90 +#include "ppc_bxx.S" + +L90: + li a6,0 + stwu a6,-4(sp) # default value + movr a6,sp # &mhdrp + mflr a5 # &ppcbxx: f_unfilter + + lwz a1,-8(r31) # 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_mach_headers + cmpli 0,a3,2048; bgt L100; li a3,2048 # at least 2KB for /usr/bin/dyld +L100: + movr r29,sp # remember for restoring later + subf sp,a3,sp # alloca + movr a2,sp # &temp char[sz_mach_headers] + addi sp,sp,-4*6 # linkage area assumed by C code (sp,cr,lr, xx,yy,zz) + movr a4,r31 # f_decompress + call upx_main # Out: a0= &Mach_ppc_thread_state of dyld + + movr sp,r29 # restore stack pointer + lwz t0, srr0(a0); mtctr t0 # entry address + /* Next 3 lines probably are not needed, but ... */ + lwz t0, reg_cr(a0); mtcr t0 # condition code + lwz t0,reg_xer(a0); mtxer t0 # extended error reg (CArry, etc.) + lwz t0, reg_lr(a0); mtlr t0 # link register + + lmw 4,4*4+reg0(3) # reg 4 thru 31 + lwz 0,0*4+reg0(3) + lwz 2,2*4+reg0(3) + lwz 3,3*4+reg0(3) + bctr # goto dyld + +SYS_exit =1 +SYS_fork =2 +SYS_read =3 +SYS_write =4 +SYS_open =5 +SYS_close =6 + +SYS_mmap =197 +SYS_mprotect= 74 + +/* SYS_mmap takes a 64-bit off_t, but gcc-3.4.1-20040827 passes long long + in wrong registers. So change C interface to use size_t (32-bits) instead + of off_t (64 bits), and convert here. +*/ +mmap: .globl mmap + movr a6,a5; li a5,0 # zero extend 6th arg size_t to off_t + li 0,SYS_mmap +sysgo: + sc + li a0,-1 # failure return + 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 + diff --git a/src/stub/fold_machppc32.h b/src/stub/fold_machppc32.h new file mode 100644 index 00000000..23c587b2 --- /dev/null +++ b/src/stub/fold_machppc32.h @@ -0,0 +1,129 @@ +/* fold_machppc32.h -- created from fold_machppc32.bin, 1532 (0x5fc) 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 FOLD_MACHPPC32_ADLER32 0x02240452 +#define FOLD_MACHPPC32_CRC32 0x810a39d7 + +unsigned char fold_machppc32[1532] = { + 72, 0, 0, 93, 40, 6, 0,208, 76,130, 0, 32, 84,132,240,191, /* 0x 0 */ + 77,130, 0, 32, 56,165, 1, 32,124,103, 27,120, 56, 99,255,252, /* 0x 10 */ +124,137, 3,166, 72, 0, 0, 32,125, 99, 16, 80,125,107, 58, 20, /* 0x 20 */ + 85,107, 80, 42,125,107, 86,112, 81, 98, 1,186,144, 67, 0, 0, /* 0x 30 */ + 78, 64, 0, 32,132, 67, 0, 4, 84, 75, 85,190,124, 11, 40, 64, /* 0x 40 */ + 65,162,255,216, 66, 0,255,240, 78,128, 0, 32, 57, 32, 0, 0, /* 0x 50 */ +149, 33,255,252,124, 41, 11,120,125, 8, 2,166,128,159,255,248, /* 0x 60 */ +124,100,248, 80,128,195, 0, 24, 40, 6, 8, 0, 65,129, 0, 8, /* 0x 70 */ + 56,192, 8, 0,124, 61, 11,120,124, 38, 8, 80,124, 37, 11,120, /* 0x 80 */ + 56, 33,255,232,127,231,251,120, 72, 0, 4, 37,127,161,235,120, /* 0x 90 */ +128, 67, 0, 0,124, 73, 3,166,128, 67, 0,136,124, 79,241, 32, /* 0x a0 */ +128, 67, 0,140,124, 65, 3,166,128, 67, 0,144,124, 72, 3,166, /* 0x b0 */ +184,131, 0, 24,128, 3, 0, 8,128, 67, 0, 16,128, 99, 0, 20, /* 0x c0 */ + 78,128, 4, 32,125, 9, 67,120, 57, 0, 0, 0, 56, 0, 0,197, /* 0x d0 */ + 68, 0, 0, 2, 56, 96,255,255, 78,128, 0, 32, 56, 0, 0, 1, /* 0x e0 */ + 75,255,255,240, 56, 0, 0, 3, 75,255,255,232, 56, 0, 0, 5, /* 0x f0 */ + 75,255,255,224, 56, 0, 0, 6, 75,255,255,216, 56, 0, 0, 74, /* 0x 100 */ + 75,255,255,208,124, 8, 2,166,148, 33,255,240,144, 1, 0, 20, /* 0x 110 */ +128, 3, 0, 0,129, 35, 0, 4,127,128, 40, 64, 64,188, 0, 12, /* 0x 120 */ + 56, 96, 0,127, 75,255,255,185, 47,133, 0, 0, 65,158, 0, 28, /* 0x 130 */ +124,169, 3,166,136, 9, 0, 0, 57, 41, 0, 1,152, 4, 0, 0, /* 0x 140 */ + 56,132, 0, 1, 66, 0,255,240,128, 3, 0, 0,129, 35, 0, 4, /* 0x 150 */ +124, 5, 0, 80,144, 3, 0, 0,125, 41, 42, 20,128, 1, 0, 20, /* 0x 160 */ + 56, 33, 0, 16,145, 35, 0, 4,124, 8, 3,166, 78,128, 0, 32, /* 0x 170 */ +124, 8, 2,166,148, 33,255,192,191,129, 0, 48,124,159, 35,120, /* 0x 180 */ +124,126, 27,120,124,188, 43,120,144, 1, 0, 68,124,221, 51,120, /* 0x 190 */ +128, 4, 0, 0, 47,128, 0, 0, 65,158, 1, 32, 56,160, 0, 12, /* 0x 1a0 */ +127,195,243,120, 56,129, 0, 16, 75,255,255, 93,129, 33, 0, 16, /* 0x 1b0 */ +128,161, 0, 20, 47,137, 0, 0, 64,190, 0, 36, 60, 0, 33, 88, /* 0x 1c0 */ + 96, 0, 80, 85,127,133, 0, 0, 64,190, 0, 28,128, 30, 0, 0, /* 0x 1d0 */ + 47,128, 0, 0, 65,190, 0,228, 72, 0, 0, 12, 47,133, 0, 0, /* 0x 1e0 */ + 64,190, 0, 12, 56, 96, 0,127, 75,255,254,245,127, 5, 72, 64, /* 0x 1f0 */ + 65,185,255,244,128, 31, 0, 0,127,137, 0, 64, 65,189,255,232, /* 0x 200 */ +128, 31, 0, 4, 64,152, 0,132,124,164, 43,120,128,126, 0, 4, /* 0x 210 */ +124, 5, 3,120, 56,193, 0, 32,136,225, 0, 24,127,136, 3,166, /* 0x 220 */ + 78,128, 0, 33, 47,131, 0, 0, 64,190,255,188,128,129, 0, 32, /* 0x 230 */ +128, 1, 0, 16,127,132, 0, 0, 64,190,255,172,136,193, 0, 25, /* 0x 240 */ + 49, 61,255,255,124, 9,233, 16,125, 38, 0,208, 85, 41, 15,254, /* 0x 250 */ +125, 43, 0, 57, 65,162, 0, 20,128,127, 0, 4,127,168, 3,166, /* 0x 260 */ +136,161, 0, 26, 78,128, 0, 33,129, 97, 0, 20,128, 30, 0, 4, /* 0x 270 */ +129, 62, 0, 0,124, 0, 90, 20,125, 43, 72, 80,144, 30, 0, 4, /* 0x 280 */ +145, 62, 0, 0, 72, 0, 0, 16,124, 4, 3,120,127,195,243,120, /* 0x 290 */ + 75,255,254,117,129, 97, 0, 16,129, 63, 0, 0,128, 31, 0, 4, /* 0x 2a0 */ +125, 43, 72, 80, 47,137, 0, 0,124, 0, 90, 20,144, 31, 0, 4, /* 0x 2b0 */ +145, 63, 0, 0, 75,255,254,228,128, 1, 0, 68,187,129, 0, 48, /* 0x 2c0 */ + 56, 33, 0, 64,124, 8, 3,166, 78,128, 0, 32,124, 8, 2,166, /* 0x 2d0 */ +148, 33,255,176,190, 97, 0, 28,125,128, 0, 38, 58,224, 0, 0, /* 0x 2e0 */ +124,122, 27,120,144, 1, 0, 84,124,155, 35,120,128, 3, 0, 16, /* 0x 2f0 */ +124,179, 43,120,145,129, 0, 24,124,212, 51,120,127,151, 0, 64, /* 0x 300 */ +124,245, 59,120,125, 22, 67,120, 59,195, 0, 28, 59, 0, 0, 0, /* 0x 310 */ + 64,156, 1,124,129, 62, 0, 0, 47,137, 0, 1, 64,190, 1, 48, /* 0x 320 */ +129, 62, 0, 24,129,126, 0, 36, 85, 61, 5, 62,128, 30, 0, 28, /* 0x 330 */ +127,139,234, 20,145, 97, 0, 8, 46, 28, 0, 0,127, 41, 2, 20, /* 0x 340 */ +145, 33, 0, 12,127,253, 72, 80, 65,146, 0, 72, 47,155, 0, 0, /* 0x 350 */ + 64,190, 0, 16, 47,139, 0, 0, 56,192, 0, 18, 64,158, 0, 8, /* 0x 360 */ + 56,192, 16, 18, 47,139, 0, 0,126,103,155,120, 64,158, 0, 8, /* 0x 370 */ + 56,224,255,255,129, 30, 0, 32,127,227,251,120,127,132,227,120, /* 0x 380 */ + 56,160, 0, 3, 75,255,253, 65,127,159, 24, 0, 64,158, 0,128, /* 0x 390 */ + 47,155, 0, 0, 65,158, 0, 52,128, 30, 0, 36, 47,128, 0, 0, /* 0x 3a0 */ + 65,158, 0, 40,128, 30, 0, 32, 47,128, 0, 0, 64,158, 0, 8, /* 0x 3b0 */ +147,244, 0, 0,127, 99,219,120, 56,129, 0, 8,126,165,171,120, /* 0x 3c0 */ +126,198,179,120, 75,255,253,173,124, 28, 0,208,125, 63,226, 20, /* 0x 3d0 */ +112, 29, 15,255, 65,130, 0, 24,127,169, 3,166, 56, 0, 0, 0, /* 0x 3e0 */ +152, 9, 0, 0, 57, 41, 0, 1, 66, 0,255,248, 65,178, 0, 40, /* 0x 3f0 */ +128,190, 0, 44,127,227,251,120,127,132,227,120, 76,198, 49,130, /* 0x 400 */ + 75,255,252,253, 47,131, 0, 0, 65,190, 0, 12, 56, 96, 0,127, /* 0x 410 */ + 75,255,252,205,124, 28,234, 20,127,255, 2, 20,127,159,200, 64, /* 0x 420 */ + 64,188, 0, 84,128,190, 0, 44,124,159,200, 80,127,227,251,120, /* 0x 430 */ + 56,192, 16, 18, 56,224,255,255, 57, 0, 0, 0, 75,255,252,137, /* 0x 440 */ +127,159, 24, 0, 65,190, 0, 48, 75,255,255,196, 56, 9,255,252, /* 0x 450 */ + 43,128, 0, 1, 65,157, 0, 32,128, 30, 0, 8, 47,128, 0, 1, /* 0x 460 */ + 64,190, 0, 20,128, 30, 0, 12, 47,128, 0, 40, 64,190, 0, 8, /* 0x 470 */ + 58,254, 0, 16,128, 26, 0, 16, 59, 24, 0, 1,127,152, 0, 64, /* 0x 480 */ +128, 30, 0, 4,127,222, 2, 20, 75,255,254,136,128, 1, 0, 84, /* 0x 490 */ +126,227,187,120,129,129, 0, 24,186, 97, 0, 28,124, 8, 3,166, /* 0x 4a0 */ + 56, 33, 0, 80,125,128,129, 32, 78,128, 0, 32,148, 33,255,176, /* 0x 4b0 */ +124, 8, 2,166,144,129, 0, 8,191, 65, 0, 56,129, 97, 0, 8, /* 0x 4c0 */ +124,191, 43,120,144, 1, 0, 84, 56, 3, 0, 24, 57,107,255,232, /* 0x 4d0 */ +144, 1, 0, 20,145, 97, 0, 16,124,253, 59,120,128, 3, 0, 24, /* 0x 4e0 */ +125, 60, 75,120,200, 1, 0, 16,125, 27, 67,120,124,229, 59,120, /* 0x 4f0 */ + 56, 97, 0, 16, 56,129, 0, 24,124,218, 51,120, 56,192, 0, 0, /* 0x 500 */ +144, 1, 0, 24,216, 1, 0, 32, 59,192, 0, 0,147,225, 0, 28, /* 0x 510 */ + 75,255,252, 97,127,167,235,120,127,104,219,120,127,227,251,120, /* 0x 520 */ +127,134,227,120, 56,129, 0, 32, 56,160,255,255, 75,255,253,161, /* 0x 530 */ +128, 31, 0, 16,124,123, 27,120, 59,191, 0, 28,127,158, 0, 64, /* 0x 540 */ + 64,156, 0,148,128, 29, 0, 0, 59,222, 0, 1, 56,128, 0, 0, /* 0x 550 */ + 56,160, 0, 0, 47,128, 0, 14, 64,190, 0,104,128,125, 0, 8, /* 0x 560 */ +124,125, 26, 20, 76,198, 49,130, 75,255,251,133,127,228,251,120, /* 0x 570 */ +124,124, 27,121,127, 69,211,120, 65,128, 0, 44, 76,198, 49,130, /* 0x 580 */ + 75,255,251,101, 56,128, 0, 0,127,154, 24, 0,127,133,227,120, /* 0x 590 */ +127,227,251,120, 56,192, 0, 0, 56,224, 0, 0, 57, 0, 0, 0, /* 0x 5a0 */ + 65,190, 0, 12, 56, 96, 0,127, 75,255,251, 53, 75,255,253, 33, /* 0x 5b0 */ +124,123, 27,120,127,131,227,120, 76,198, 49,130, 75,255,251, 57, /* 0x 5c0 */ +128, 31, 0, 16,129, 61, 0, 4,127,158, 0, 64,127,189, 74, 20, /* 0x 5d0 */ + 75,255,255,112,128, 1, 0, 84,127, 99,219,120,187, 65, 0, 56, /* 0x 5e0 */ + 56, 33, 0, 80,124, 8, 3,166, 78,128, 0, 32 /* 0x 5f0 */ +}; diff --git a/src/stub/l_mac_ppc32.S b/src/stub/l_mac_ppc32.S new file mode 100644 index 00000000..3f6159af --- /dev/null +++ b/src/stub/l_mac_ppc32.S @@ -0,0 +1,71 @@ +/* + * l_mac_ppc32.S -- program entry point & decompressor (PowerPC32 Mach-o) + * + * This file is part of the UPX executable compressor. + * + * Copyright (C) 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. + * + * 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 + +/* Decompress the rest of this loader, and jump to it. */ +unfold: + mflr t0 # -4+ &{ b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...} + + lwz lsrc,4+sz_cpr(t0); mtctr lsrc # length to copy (and decompress) + lwz ldst,4+sz_unc(t0) + add dst,lsrc,t0; addi dst,dst,4+sz_b_info + add src,ldst,t0; addi src,src,GAP+64 # defend against prefetch and overlap +movup: # descending copy moves folded_loader to higher address + lbzu r0,-1(dst) + stbu r0,-1(src) + bdnz+ movup # typical count is about 0x4cb(1227) bytes + + mtctr r31 # &decompress + addi dst,t0,GAP # &unfolded result + la ldst,-4(sp) # &sz_result [will be ignored] + bctr # call decompress: branch to counter register, return to link register + +main: + mflr r31 # r31= &decompress + call unfold +L100: GAP= 128 # > farthest_prefetch; must match ../p_mach.cpp + b GAP+L100 # 'isync' has trouble on Macintosh G4? + /* { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...} */ + +eof: +/*__XTHEENDX__*/ + +/* +vi:ts=8:et:nowrap +*/ + diff --git a/src/stub/l_mac_ppc32.h b/src/stub/l_mac_ppc32.h new file mode 100644 index 00000000..66af2be3 --- /dev/null +++ b/src/stub/l_mac_ppc32.h @@ -0,0 +1,59 @@ +/* l_mac_ppc32.h -- created from l_mac_ppc32.bin, 412 (0x19c) 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 L_MAC_PPC32_LOADER_ADLER32 0x30d18ea4 +#define L_MAC_PPC32_LOADER_CRC32 0x0293d040 + +unsigned char l_mac_ppc32_loader[412] = { + 72, 0, 1,145,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,124, 72, 2,166,128,130, 0, 8,124,137, 3,166, /* 0x 150 */ +128,194, 0, 4,124,164, 18, 20, 56,165, 0, 16,124,102, 18, 20, /* 0x 160 */ + 56, 99, 0,192,140, 5,255,255,156, 3,255,255, 66, 0,255,248, /* 0x 170 */ +127,233, 3,166, 56,162, 0,128, 56,193,255,252, 78,128, 4, 32, /* 0x 180 */ +127,232, 2,166, 75,255,255,193, 72, 0, 0,128 /* 0x 190 */ +}; diff --git a/src/stub/m_mac_mach32.c b/src/stub/m_mac_mach32.c new file mode 100644 index 00000000..460b7f8f --- /dev/null +++ b/src/stub/m_mac_mach32.c @@ -0,0 +1,430 @@ +/* m_mach_ppc32.c -- loader stub for Mach-o PowerPC32 + + 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 + +*/ + +typedef unsigned int size_t; +typedef unsigned long long off_t; +typedef unsigned char nrv_byte; +typedef unsigned int nrv_uint; + +#define UPX_MAGIC_LE32 0x21585055 // "UPX!" +#define PAGE_MASK (~0u<<12) +#define PAGE_SIZE -PAGE_MASK +#define O_RDONLY 0 + +/*extern int exit(int) __attribute__ ((__noreturn__));*/ + +/************************************************************************* +// 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. + +/************************************************************************* +// "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 +**************************************************************************/ + +struct l_info { // 12-byte trailer for loader (after macho headers) + unsigned l_checksum; + unsigned l_magic; // UPX_MAGIC_LE32 + unsigned short l_lsize; + unsigned char l_version; + unsigned char l_format; +}; +struct p_info { // 12-byte packed program header + unsigned p_progid; + unsigned p_filesize; + unsigned p_blocksize; +}; + +struct b_info { // 12-byte header before each compressed block + unsigned sz_unc; // uncompressed_size + unsigned sz_cpr; // compressed_size + unsigned char b_method; // compression algorithm + unsigned char b_ftid; // filter id + unsigned char b_cto8; // filter parameter + unsigned char b_unused; +}; + +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; + } +} + +static void +upx_bzero(char *p, size_t len) +{ + if (len) do { + *p++= 0; + } while (--len); +} +#define bzero upx_bzero + + +// 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) )) + +typedef struct { + unsigned magic; + unsigned cputype; + unsigned cpysubtype; + unsigned filetype; + unsigned ncmds; + unsigned sizeofcmds; + unsigned flags; +} Mach_header; + enum e0 { + MH_MAGIC = 0xfeedface + }; + enum e1 { + CPU_TYPE_POWERPC = 18 + }; + enum e2 { + MH_EXECUTE = 2 + }; + enum e3 { + MH_NOUNDEFS = 1 + }; + +typedef struct { + unsigned cmd; + unsigned cmdsize; +} Mach_load_command; + enum e4 { + LC_SEGMENT = 0x1, + LC_THREAD = 0x4, + LC_UNIXTHREAD = 0x5, + LC_LOAD_DYLINKER = 0xe + }; + +typedef struct { + unsigned cmd; + unsigned cmdsize; + char segname[16]; + unsigned vmaddr; + unsigned vmsize; + unsigned fileoff; + unsigned filesize; + unsigned maxprot; + unsigned initprot; + unsigned nsects; + unsigned flags; +} Mach_segment_command; + enum e5 { + VM_PROT_READ = 1, + VM_PROT_WRITE = 2, + VM_PROT_EXECUTE = 4 + }; + +typedef struct { + unsigned srr0; /* Instruction address register (PC; entry addr) */ + unsigned srr1; /* Machine state register (supervisor) */ + unsigned r0, r1, r2, r3, r4, r5, r6, r7; + unsigned r8, r9,r10,r11,r12,r13,r14,r15; + unsigned r16,r17,r18,r19,r20,r21,r22,r23; + unsigned r24,r25,r26,r27,r28,r29,r30,r31; + + unsigned cr; /* Condition register */ + unsigned xer; /* User's integer exception register */ + unsigned lr; /* Link register */ + unsigned ctr; /* Count register */ + unsigned mq; /* MQ register (601 only) */ + + unsigned vrsave; /* Vector Save Register */ +} Mach_ppc_thread_state; + +typedef struct { + unsigned cmd; /* LC_THREAD or LC_UNIXTHREAD */ + unsigned cmdsize; /* total size of this command */ + unsigned flavor; + unsigned count; /* sizeof(following_thread_state)/4 */ + Mach_ppc_thread_state state; +} Mach_thread_command; + enum e6 { + PPC_THREAD_STATE = 1 + }; + enum e7 { + PPC_THREAD_STATE_COUNT = sizeof(Mach_ppc_thread_state)/4 + }; + +typedef union { + unsigned long offset; /* from start of load command to string */ + char *ptr; +} Mach_lc_str; + +#define MAP_FIXED 0x10 +#define MAP_PRIVATE 0x02 +#define MAP_ANON 0x1000 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +/* bug in crosstool/powerpc-750-linux-gnu/gcc-3.4.1-glibc-20040827: + unsigned long long off_t goes into registers (9,10) instead of (8,9). + Adjust in mmap(). +*/ +extern char *mmap(char *, size_t, unsigned, unsigned, int, /*off_t*/size_t); + +static Mach_ppc_thread_state const * +do_xmap( + Mach_header const *const mhdr, + Extent *const xi, + int const fdi, + Mach_header **mhdrpp, + f_expand *const f_decompress, + f_unfilter *const f_unf +) +{ + Mach_segment_command const *sc = (Mach_segment_command const *)(1+ mhdr); + Mach_ppc_thread_state const *entry = 0; + int j; + + for ( j=0; j < mhdr->ncmds; ++j, + (sc = (Mach_segment_command const *)(sc->cmdsize + (char const *)sc)) + ) if (LC_SEGMENT==sc->cmd) { + Extent xo; + size_t mlen = xo.size = sc->filesize; + char *addr = xo.buf = (char *)sc->vmaddr; + char *haddr = sc->vmsize + addr; + size_t frag = (int)addr &~ PAGE_MASK; + addr -= frag; + mlen += frag; + + if (0!=mlen && addr != mmap(addr, mlen, VM_PROT_READ | VM_PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | + ((xi || 0==sc->filesize) ? MAP_ANON : 0), + ((0==sc->filesize) ? -1 : fdi), sc->fileoff) ) { + err_exit(8); + } + if (xi && 0!=sc->filesize) { + if (0==sc->fileoff /*&& 0!=mhdrpp*/) { + *mhdrpp = (Mach_header *)addr; + } + 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 (0!=mlen && 0!=mprotect(addr, mlen, sc->initprot)) { + 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, sc->initprot, + MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0 ) ) { + err_exit(9); + } + } + } + else if (LC_UNIXTHREAD==sc->cmd || LC_THREAD==sc->cmd) { + Mach_thread_command const *const thrc = (Mach_thread_command const *)sc; + if (PPC_THREAD_STATE ==thrc->flavor + && PPC_THREAD_STATE_COUNT==thrc->count ) { + entry = &thrc->state; + } + } + return entry; +} + + +/************************************************************************* +// upx_main - called by our entry code +// +**************************************************************************/ + +Mach_ppc_thread_state const * +upx_main( + struct l_info const *const li, + size_t volatile sz_compressed, // total length + Mach_header *const mhdr, // temp char[sz_mhdr] for decompressing + size_t const sz_mhdr, + f_expand *const f_decompress, + f_unfilter *const f_unf, + Mach_header **const mhdrpp // Out: *mhdrpp= &real Mach_header +) +{ + Mach_ppc_thread_state const *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 *)mhdr; + xo.size = ((struct b_info const *)xi.buf)->sz_unc; + xi0 = xi; + + // Uncompress Macho headers + unpackExtent(&xi, &xo, f_decompress, 0); // never filtered? + + entry = do_xmap(mhdr, &xi0, -1, mhdrpp, f_decompress, f_unf); + + { // Map dyld dynamic loader + Mach_load_command const *lc = (Mach_load_command const *)(1+ mhdr); + int j; + + for (j=0; j < mhdr->ncmds; ++j, + (lc = (Mach_load_command const *)(lc->cmdsize + (char const *)lc)) + ) if (LC_LOAD_DYLINKER==lc->cmd) { + char const *const dyld_name = ((Mach_lc_str const *)(1+ lc))->offset + + (char const *)lc; + int const fdi = open(dyld_name, O_RDONLY, 0); + if (0 > fdi) { + err_exit(18); + } + if (sz_mhdr!=read(fdi, (void *)mhdr, sz_mhdr)) { +ERR_LAB + err_exit(19); + } + entry = do_xmap(mhdr, 0, fdi, 0, 0, 0); + close(fdi); + } + } + + return entry; +} + + +/* +vi:ts=4:et:nowrap +*/ +