1/* powerpc-darwin.macho-fold.S -- linkage to C code to process Mach-o binary 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) 2000-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#include "arch/powerpc/64le/macros.S" 33#include "arch/powerpc/64le/ppc_regs.h" 34retaddr = 2*8 35 36sz_b_info= 12 37 sz_unc= 0 38 sz_cpr= 4 39 40sz_l_info= 12 41sz_p_info= 12 42 43/* Mach_ppc_thread_state */ 44srr0 = 0*4 45srr1 = 1*4 46reg0 = 2*4 47 48reg_cr = 34*4 49reg_xer = 35*4 50reg_lr = 36*4 51reg_ctr = 37*4 52reg_mq = 38*4 53reg_vrsave = 39*4 54 55 56_start: .globl _start # ignored, but silence "cannot find entry symbol _start" from ld 57/* In: 58 r31= &decompress; also 8+ (char *)&(offset to {l_info; p_info; b_info}) 59*/ 60fold_begin: 61 teq r0,r0 // this code has not been converted to 64-bit!! 62 call L90 63#include "arch/powerpc/32/bxx.S" 64 65L90: 66 la sp,SZ_FRAME(sp) // trim save area used by decompressor 67 li a6,0 68 stwu a6,-4(sp) # _push_ default value for dyld 69 movr a6,sp # &mhdrp 70 mflr a5 # &ppcbxx: f_unfilter 71 72 lwz a1,-8(r31) # offset to {l_info; p_info; b_info} 73 subf a0,a1,r31 # &l_info 74 lwz a3,sz_unc+sz_p_info+sz_l_info(a0) # sz_mach_headers 75 cmplwi cr0,a3,2048; bgt L100; li a3,2048 # at least 2 KiB for /usr/lib/dyld 76L100: 77 movr r29,sp # remember for restoring later 78 subf sp,a3,sp # alloca 79 movr a2,sp # &temp char[sz_mach_headers] 80 stdu sp,-SZ_FRAME(sp) # ABI convention 81 movr a4,r31 # f_decompress 82 call upx_main # Out: a0= &Mach_ppc_thread_state of dyld 83 84 movr sp,r29 # restore stack pointer 85 lwz r0, srr0(a0); mtctr r0 # entry address 86 /* Next 3 lines probably are not needed, but ... */ 87 lwz r0, reg_cr(a0); mtcr r0 # condition code 88 lwz r0,reg_xer(a0); mtxer r0 # extended error reg (CArry, etc.) 89 lwz r0, reg_lr(a0); mtlr r0 # link register 90 91 lmw 4,4*4+reg0(3) # reg 4 thru 31 92 lwz 0,0*4+reg0(3) 93 lwz 2,2*4+reg0(3) 94 lwz 3,3*4+reg0(3) 95 bctr # goto dyld 96 97SYS_exit =1 98SYS_fork =2 99SYS_read =3 100SYS_write =4 101SYS_open =5 102SYS_close =6 103 104SYS_pread =153 105SYS_mmap =197 106SYS_mprotect= 74 107 108/* SYS_mmap takes a 64-bit off_t, but gcc-3.4.1-20040827 passes long long 109 in wrong registers. So change C interface to use size_t (32-bits) instead 110 of off_t (64 bits), and convert here. 111*/ 112pread: .globl pread 113 movr a4,a3; li a3,0 # zero extend 4th arg size_t to off_t 114 li 0,SYS_pread; b sysgo 115mmap: .globl mmap 116 movr a6,a5; li a5,0 # zero extend 6th arg size_t to off_t 117 li 0,SYS_mmap 118sysgo: 119 sc 120 li a0,-1 # failure return 121 ret 122 123exit: .globl exit 124 li 0,SYS_exit; b sysgo 125read: .globl read 126 li 0,SYS_read; b sysgo 127open: .globl open 128 li 0,SYS_open; b sysgo 129close: .globl close 130 li 0,SYS_close; b sysgo 131mprotect: .globl mprotect 132 li 0,SYS_mprotect; b sysgo 133 134#include "powerpc64-savegpr0.S" 135 136/* vim:set ts=8 sw=8 et: */ 137