2
; i386-darwin.dylib-entry.S -- program entry point & decompressor (i386 Mach-o)
4
; This file is part of the UPX executable compressor.
6
; Copyright (C) 1996-2009 Markus Franz Xaver Johannes Oberhumer
7
; Copyright (C) 1996-2009 Laszlo Molnar
8
; Copyright (C) 2000-2009 John F. Reiser
11
; UPX and the UCL library are free software; you can redistribute them
12
; and/or modify them under the terms of the GNU General Public License as
13
; published by the Free Software Foundation; either version 2 of
14
; the License, or (at your option) any later version.
16
; This program is distributed in the hope that it will be useful,
17
; but WITHOUT ANY WARRANTY; without even the implied warranty of
18
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
; GNU General Public License for more details.
21
; You should have received a copy of the GNU General Public License
22
; along with this program; see the file COPYING.
23
; If not, write to the Free Software Foundation, Inc.,
24
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
; Markus F.X.J. Oberhumer Laszlo Molnar
27
; <markus@oberhumer.com> <ml1050@users.sourceforge.net>
30
; <jreiser@users.sourceforge.net>
34
#include "arch/i386/macros.S"
37
/*************************************************************************
38
// We have been CALLed as a subroutine from dyld; C-language rules apply.
39
// -4*4+_start: .long offset(user_init_function)
40
// -3*4+_start: .long offset(&b_info of compressed Mach_headers)
41
// -2*4+_start: .long length(compressed __TEXT)
42
// -1*4+_start: .long total_length # of preceding bytes in file
43
**************************************************************************/
47
//// int3 # for debug only
48
push eax # space for &user_init_function
50
call main // push address of decompress subroutine
53
// /*************************************************************************
54
// // C callable decompressor
55
// **************************************************************************/
57
// /* Offsets to parameters, allowing for {pusha + call} */
58
#define O_INP (8*4 +1*4)
59
#define O_INS (8*4 +2*4)
60
#define O_OUTP (8*4 +3*4)
61
#define O_OUTS (8*4 +4*4)
62
#define O_PARAM (8*4 +5*4)
64
#define INP dword ptr [esp+O_INP]
65
#define INS dword ptr [esp+O_INS]
66
#define OUTP dword ptr [esp+O_OUTP]
67
#define OUTS dword ptr [esp+O_OUTS]
68
#define PARM dword ptr [esp+O_PARAM]
71
//; empty section for commonality with l_lx_exec86.asm
82
#include "arch/i386/nrv2b_d32.S"
83
#include "arch/i386/nrv2d_d32.S"
84
#include "arch/i386/nrv2e_d32.S"
85
#include "arch/i386/lzma_d.S"
88
// eax is 0 from decompressor code
89
//xor eax, eax ; return code
91
// check compressed size
99
// write back the uncompressed size
117
#define PAGE_SIZE ( 1<<12)
123
seg_vmsize=4+seg_vmaddr
124
seg_filesize=2*4+seg_vmsize
133
#define MAP_FIXED 0x10
134
#define MAP_PRIVATE 0x02
135
#define MAP_ANON 0x1000
142
pop ebp # &decompress
143
lea ebx,[-4+ _start - decompress + ebp] # &total_length
144
mov eax,[-1*4 + ebx] # length(compressed __TEXT)
145
add eax,offset(dy_top)
146
sub eax,offset(decompress)
148
push eax # length for eventual munmap
150
push 0 # hi32(offset)
151
push 0 # lo32(offset)
153
push MAP_ANON|MAP_PRIVATE
154
push PROT_READ|PROT_WRITE
160
push eax # addr for eventual munmap
162
// Copy interval [decompress, dy_top).
163
mov esi,ebp # decompressor
164
mov ebp,eax # new location
165
mov edi,eax # dst for decompressor
166
mov ecx,offset(dy_top)
167
sub ecx,offset(decompress)
170
// Goto the copied dy_reloc.
171
lea eax,[-offset(dy_top - dy_reloc) + edi]
175
// Copy compressed __TEXT.
176
push edi # remember start of compressed __TEXT
177
mov edx,ebx # &total_length
178
mov eax,[-3*4+ebx] # offset(user_init_function)
179
sub edx,[ebx] # runtime base address
180
add eax,edx; mov [(1+2+8)*4 + esp],eax # relocate &user_init_function
181
mov esi,[-2*4 + ebx]; add esi,edx
184
pop esi # &b_info for Mach_header
185
mov edi,edx # runtime base address
187
// Decompress __TEXT, but do not overwrite Mach_headers
188
// in order to maintain consistency with dyld partial caching of them.
189
// So, skip the first compressed block.
190
lodsd; add edi,eax # sz_unc
191
lodsd; add esi,eax # sz_cpr
194
push esi; push edi # save in case unfilter
196
lodsd; test eax,eax; jz dy_done
197
push eax // sz_uncompressed (maximum dstlen for lzma)
198
mov ecx,esp // save &dstlen
199
push eax // space for 5th param b_info.misc
202
add edi,eax // next dst
203
lodsd; push eax // sz_compressed (srclen)
205
lodsd; mov [3*4 + esp],eax // last 4 bytes of b_info
206
push esi // &compressed __TEXT
207
add esi,ecx // next src
208
call ebp // decompress(src, srclen, dst, &dstlen, b_info.misc)
209
add esp, (5+1)*4 // (5+1) args to decompress
211
pop edx; pop eax # edx= old dst; eax= old &b_info
212
movzbl ecx,[1+ b_method + eax]; jecxz dy_uncpr; push ecx # ftid
213
movzbl ecx,[2+ b_method + eax]; push ecx # cto8
216
lea eax,[2+ ebp]; call eax # f_unfilter(dst, dstlen, cto8, ftid)
223
call sysgo; jncs 0f; or eax,~0
229
pop eax # discard, leaving 1 junk word below the regs for POPA
230
lea edx,[-5+ edi] # steal some space at high end of __TEXT
231
mov byte ptr [ edx], 0x58 # pop eax
232
mov dword ptr [1+ edx],0xc3615858 # pop eax; pop eax; popa; ret
236
pop edx # return address for sysenter
237
mov ecx,esp # &{user_ret, arg1, arg2, ...}
238
.byte 0x0f, 0x34 # sysenter