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