1/* i386-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 32NBPW= 8 33#include "arch/amd64/macros.S" 34 35sz_b_info= 12 36 sz_unc= 0 37 sz_cpr= 4 38 39sz_l_info= 12 40sz_p_info= 12 41 42sz_Mach_header64= 8*4 43sz_Mach_segment_command= 2*4 + 16 + 4*8 + 4*4 44 45_start: .globl _start # ignored, but silence "cannot find entry symbol _start" from ld 46 47 48fold_begin: // In: %rbp= &f_exp; %r14= ADRX; %r15= LENX 49// rsp/ fd,ADRU,LENU,%entry,&Mach_header64, argc,argv,0,envp,0,apple,0,strings 50// int3 51 call L90 # push &L90 52#include "arch/amd64/bxx.S" 53L90: 54 pop %arg6 # &amdbxx: f_unfilter 55 movq %r14,%arg1 // ADRX 56 movq %r15,%arg2 // LENX 57 movq %rsp,%r12 // remember for un-alloca 58 movl sz_unc+sz_p_info+sz_l_info(%arg1),%arg4l // sz_mhdr 59 movl $2048,%eax // >= 2KiB for /usr/lib/dyld 60 cmpl %eax,%arg4l 61 cmovb %eax,%arg4l // sz_mhdr 62 lea 4*NBPW(%r12),%rax // &&Mach_header64 for arg7 63 movq %rbp,%arg5 // f_decompress 64 subq %arg4,%rsp // alloca(sz_mhdr) 65 movq %rsp,%arg3 // temp char mhdr[sz_mhdr] 66 push %rax // (arg7) mhdrpp= &mhdrp 67// upx_main(&l_info,len_cpr,temp[sz_mhdr],sz_mhdr,f_exp,f_unf,mhdr **) 68 call upx_main # Out: rax= &Mach_AMD64_thread_state of dyld 69 70AMD64_ts_rip= 16*NBPW 71 movq (%rax),%rbp // &hatch 72 movq AMD64_ts_rip(%rax),%rcx // from temp char mhdr[] before unalloca 73 movq %r12,%rsp // unalloca 74 movq %rcx,3*NBPW(%rsp) // entry 75 pop %arg1 // fd 76 call close 77 pop %arg1 // ADRU 78 pop %arg2 // LENU 79 mov $SYS_munmap+SYSBASE,%eax 80 jmp *%rbp // goto hatch: syscall.munmap(ADRU,LENU); ret 81 82bswap: .globl bswap 830: 84 mov (%arg1),%eax 85 .byte 0x0f,0xc8 // bswap eax 86 mov %eax,(%arg1) 87 sub $4,%arg2l 88 lea 4(%arg1),%arg1 89 ja 0b 90 ret 91 92SYSBASE= 0x02000000 93 94SYS_exit =1 95SYS_read =3 96SYS_write =4 97SYS_open =5 98SYS_close =6 99 100SYS_pread =0x99 101SYS_mmap =0xc5 102SYS_munmap =0x49 103SYS_mprotect =0x4a 104 105// lazy jmps enable compression of this code 106write: .globl write 107 mov $SYS_write,%al; jmp 2+ 0f; 0: 108exit: .globl exit 109 mov $SYS_exit,%al; jmp 2+ 0f; 0: 110mprotect: .globl mprotect 111 mov $SYS_mprotect,%al; jmp 2+ 0f; 0: 112munmap: .globl munmap 113 mov $SYS_munmap,%al; jmp 2+ 0f; 0: 114pread: .globl pread 115 mov $SYS_pread,%al; jmp 2+ 0f; 0: 116close: .globl close 117 mov $SYS_close,%al; jmp 2+ 0f; 0: 118open: .globl open 119 mov $SYS_open,%al; jmp 2+ 0f; 0: 120mmap: .globl mmap 121 mov $SYS_mmap,%al; jmp 2+ 0f; 0: 122read: .globl read 123 mov $SYS_read,%al 124 125 push %r9; push %r8; push %rcx; push %rdx; push %rsi; push %rdi 126 movzbl %al,%eax; push %rax // save SYS_nnn for error diagnosis 127 or $SYSBASE,%eax 128 mov %rcx,%r10 129 syscall // .byte 0x0f,0x05 130 131#define DEBUG 0 132#if !DEBUG //{ 133 jc sysfail 134 add $7*8,%rsp // SYS_nnn, 6 args 135 ret 136#endif //} 137 138DFRAME=0x100 139sysfail: 140 pushf 141 push %rax // retval 142 push %rdi; push %rsi // registers used 143 push %rbp; mov %rsp,%rbp 144 cmpl $SYS_write,5*8+0*8(%rbp); je ignore_WRITE 145 sub $DFRAME,%rsp // alloca 146 147 mov %rsp,%rdi // output ptr 148 movb $'\n',%al; stosb 149 movb $'*',%al; stosb 150 mov 3*8(%rbp),%rax; call pr_hex; movb $'=',%al; stosb // retval 151 mov 5*8+0*8(%rbp),%rax; call pr_hex; movb $'(',%al; stosb // SYS_nnn 152 mov 5*8+1*8(%rbp),%rax; call pr_hex; movb $',',%al; stosb // arg1 153 mov 5*8+2*8(%rbp),%rax; call pr_hex; movb $',',%al; stosb // arg2 154 mov 5*8+3*8(%rbp),%rax; call pr_hex; movb $',',%al; stosb // arg3 155 mov 5*8+4*8(%rbp),%rax; call pr_hex; movb $',',%al; stosb // arg4 156 mov 5*8+5*8(%rbp),%rax; call pr_hex; movb $',',%al; stosb // arg5 157 mov 5*8+6*8(%rbp),%rax; call pr_hex; movb $')',%al; stosb // arg6 158 movb $'\n',%al; stosb 159 160 mov %rdi,%rdx 161 sub %rsp,%rdx // len 162 mov %rsp,%rsi // ptr 163 mov $2,%edi // FD_STDERR 164 mov $SYS_write+SYSBASE,%eax 165 syscall 166 167 add $DFRAME,%rsp 168ignore_WRITE: 169 pop %rbp; pop %rsi; pop %rdi 170 pop %rax // retval 171 popf 172 lea 7*8(%rsp),%rsp // SYS_nnn, args 173 174 jnc sysOK 175 or $~0,%rax //mov errno,eax 176sysOK: 177 ret 178 179pr_hex: 180 lea hextab(%rip),%rsi 181 mov %rax,%rdx 182 mov $16,%ecx // char count 1831: 184 rol $4,%rdx; mov %edx,%eax; and $0xf,%eax 185 movzbl (%rsi,%rax),%eax 186 stosb; sub $1,%ecx; jnz 1b 187 ret 188 189hextab: 190 .ascii "0123456789abcdef" 191 192/* vim:set ts=8 sw=8 et: */ 193