1 /* packer_c.cpp -- Packer compression handling
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 All Rights Reserved.
8
9 UPX and the UCL library are free software; you can redistribute them
10 and/or modify them under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of
12 the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING.
21 If not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 Markus F.X.J. Oberhumer Laszlo Molnar
25 <markus@oberhumer.com> <ezerotven+github@gmail.com>
26 */
27
28
29 #include "conf.h"
30 #include "packer.h"
31 #include "linker.h"
32 //#include "filter.h"
33
34
35 /*************************************************************************
36 // compression method util
37 **************************************************************************/
38
isValidCompressionMethod(int method)39 bool Packer::isValidCompressionMethod(int method)
40 {
41 if (M_IS_LZMA(method)) {
42 #if !(WITH_LZMA)
43 assert(0 && "Internal error - LZMA not compiled in");
44 #else
45 return true;
46 #endif
47 }
48 return (method >= M_NRV2B_LE32 && method <= M_LZMA);
49 }
50
51
getDefaultCompressionMethods_8(int method,int level,int small) const52 const int *Packer::getDefaultCompressionMethods_8(int method, int level, int small) const
53 {
54 #define M_LZMA_003 (M_LZMA | 0x00300)
55 #define M_LZMA_407 (M_LZMA | 0x40700)
56 static const int m_all[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
57 //static const int m_cl1b[] = { M_CL1B_8, M_END };
58 static const int m_lzma[] = { M_LZMA, M_END };
59 static const int m_nrv2b[] = { M_NRV2B_8, M_END };
60 static const int m_nrv2d[] = { M_NRV2D_8, M_END };
61 static const int m_nrv2e[] = { M_NRV2E_8, M_END };
62
63 if (method == M_ALL) return m_all;
64 //if (M_IS_CL1B(method)) return m_cl1b;
65 if (M_IS_LZMA(method)) return m_lzma;
66 if (M_IS_NRV2B(method)) return m_nrv2b;
67 if (M_IS_NRV2D(method)) return m_nrv2d;
68 if (M_IS_NRV2E(method)) return m_nrv2e;
69 if (small < 0)
70 small = file_size <= 512*1024;
71 if (level == 1 || small)
72 return m_nrv2b;
73 return m_nrv2e;
74 }
75
76
getDefaultCompressionMethods_le32(int method,int level,int small) const77 const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int small) const
78 {
79 static const int m_all[] = { M_NRV2B_LE32, M_NRV2D_LE32, M_NRV2E_LE32, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
80 //static const int m_cl1b[] = { M_CL1B_LE32, M_END };
81 static const int m_lzma[] = { M_LZMA, M_END };
82 static const int m_nrv2b[] = { M_NRV2B_LE32, M_END };
83 static const int m_nrv2d[] = { M_NRV2D_LE32, M_END };
84 static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
85
86 if (method == M_ALL) return m_all;
87 //if (M_IS_CL1B(method)) return m_cl1b;
88 if (M_IS_LZMA(method)) return m_lzma;
89 if (M_IS_NRV2B(method)) return m_nrv2b;
90 if (M_IS_NRV2D(method)) return m_nrv2d;
91 if (M_IS_NRV2E(method)) return m_nrv2e;
92 if (small < 0)
93 small = file_size <= 512*1024;
94 if (level == 1 || small)
95 return m_nrv2b;
96 return m_nrv2e;
97 }
98
99
100 /*************************************************************************
101 // loader util
102 **************************************************************************/
103
getDecompressorSections() const104 const char *Packer::getDecompressorSections() const
105 {
106 static const char nrv2b_le32_small[] =
107 "N2BSMA10,N2BDEC10,N2BSMA20,N2BDEC20,N2BSMA30,"
108 "N2BDEC30,N2BSMA40,N2BSMA50,N2BDEC50,N2BSMA60,"
109 "N2BDEC60";
110 static const char nrv2b_le32_fast[] =
111 "N2BFAS10,+80CXXXX,N2BFAS11,N2BDEC10,N2BFAS20,"
112 "N2BDEC20,N2BFAS30,N2BDEC30,N2BFAS40,N2BFAS50,"
113 "N2BDEC50,N2BFAS60,+40CXXXX,N2BFAS61,N2BDEC60";
114 static const char nrv2d_le32_small[] =
115 "N2DSMA10,N2DDEC10,N2DSMA20,N2DDEC20,N2DSMA30,"
116 "N2DDEC30,N2DSMA40,N2DSMA50,N2DDEC50,N2DSMA60,"
117 "N2DDEC60";
118 static const char nrv2d_le32_fast[] =
119 "N2DFAS10,+80CXXXX,N2DFAS11,N2DDEC10,N2DFAS20,"
120 "N2DDEC20,N2DFAS30,N2DDEC30,N2DFAS40,N2DFAS50,"
121 "N2DDEC50,N2DFAS60,+40CXXXX,N2DFAS61,N2DDEC60";
122 static const char nrv2e_le32_small[] =
123 "N2ESMA10,N2EDEC10,N2ESMA20,N2EDEC20,N2ESMA30,"
124 "N2EDEC30,N2ESMA40,N2ESMA50,N2EDEC50,N2ESMA60,"
125 "N2EDEC60";
126 static const char nrv2e_le32_fast[] =
127 "N2EFAS10,+80CXXXX,N2EFAS11,N2EDEC10,N2EFAS20,"
128 "N2EDEC20,N2EFAS30,N2EDEC30,N2EFAS40,N2EFAS50,"
129 "N2EDEC50,N2EFAS60,+40CXXXX,N2EFAS61,N2EDEC60";
130 #if 0
131 static const char cl1b_le32_small[] =
132 "CL1ENTER,CL1SMA10,CL1RLOAD,"
133 "CL1WID01,CL1SMA1B,"
134 "CL1WID02,CL1SMA1B,"
135 "CL1WID03,CL1SMA1B,"
136 "CL1WID04,CL1SMA1B,"
137 "CL1WID05,CL1SMA1B,"
138 "CL1WID06,CL1SMA1B,"
139 "CL1WID07,CL1SMA1B,"
140 "CL1WID08,CL1SMA1B,"
141 "CL1WID09,CL1SMA1B,"
142 "CL1WID10,"
143 "CL1START,"
144 "CL1TOP00,CL1SMA1B,"
145 "CL1TOP01,CL1SMA1B,"
146 "CL1TOP02,CL1SMA1B,"
147 "CL1TOP03,CL1SMA1B,"
148 "CL1TOP04,CL1SMA1B,"
149 "CL1TOP05,CL1SMA1B,"
150 "CL1TOP06,CL1SMA1B,"
151 "CL1TOP07,CL1SMA1B,"
152 "CL1OFF01,CL1SMA1B,"
153 "CL1OFF02,CL1SMA1B,"
154 "CL1OFF03,CL1SMA1B,"
155 "CL1OFF04,"
156 "CL1LEN00,CL1SMA1B,"
157 "CL1LEN01,CL1SMA1B,"
158 "CL1LEN02,"
159 "CL1COPY0";
160 static const char cl1b_le32_fast[] =
161 "CL1ENTER," "CL1RLOAD,"
162 "CL1WID01,CL1FAS1B,"
163 "CL1WID02,CL1FAS1B,"
164 "CL1WID03,CL1FAS1B,"
165 "CL1WID04,CL1FAS1B,"
166 "CL1WID05,CL1FAS1B,"
167 "CL1WID06,CL1FAS1B,"
168 "CL1WID07,CL1FAS1B,"
169 "CL1WID08,CL1FAS1B,"
170 "CL1WID09,CL1FAS1B,"
171 "CL1WID10,"
172 "CL1START,"
173 "CL1TOP00,CL1FAS1B,"
174 "CL1TOP01,CL1FAS1B,"
175 "CL1TOP02,CL1FAS1B,"
176 "CL1TOP03,CL1FAS1B,"
177 "CL1TOP04,CL1FAS1B,"
178 "CL1TOP05,CL1FAS1B,"
179 "CL1TOP06,CL1FAS1B,"
180 "CL1TOP07,CL1FAS1B,"
181 "CL1OFF01,CL1FAS1B,"
182 "CL1OFF02,CL1FAS1B,"
183 "CL1OFF03,CL1FAS1B,"
184 "CL1OFF04,"
185 "CL1LEN00,CL1FAS1B,"
186 "CL1LEN01,CL1FAS1B,"
187 "CL1LEN02,"
188 "CL1COPY0";
189 #endif
190 static const char lzma_small[] =
191 "LZMA_DEC00,LZMA_DEC10,LZMA_DEC30";
192 static const char lzma_fast[] =
193 "LZMA_DEC00,LZMA_DEC20,LZMA_DEC30";
194 static const char lzma_elf_small[] =
195 "LZMA_ELF00,LZMA_DEC10,LZMA_DEC30";
196 static const char lzma_elf_fast[] =
197 "LZMA_ELF00,LZMA_DEC20,LZMA_DEC30";
198
199 if (ph.method == M_NRV2B_LE32)
200 return opt->small ? nrv2b_le32_small : nrv2b_le32_fast;
201 if (ph.method == M_NRV2D_LE32)
202 return opt->small ? nrv2d_le32_small : nrv2d_le32_fast;
203 if (ph.method == M_NRV2E_LE32)
204 return opt->small ? nrv2e_le32_small : nrv2e_le32_fast;
205 // if (ph.method == M_CL1B_LE32)
206 // return opt->small ? cl1b_le32_small : cl1b_le32_fast;
207 if (M_IS_LZMA(ph.method)) {
208 if (UPX_F_LINUX_ELF_i386 ==ph.format
209 || UPX_F_LINUX_ELFI_i386 ==ph.format
210 || UPX_F_LINUX_ELF64_AMD ==ph.format
211 || UPX_F_LINUX_ELF32_ARMEL==ph.format
212 || UPX_F_LINUX_ELFPPC32 ==ph.format
213 || UPX_F_LINUX_ELFPPC64LE ==ph.format
214 || UPX_F_LINUX_ELF32_ARMEB==ph.format
215 || UPX_F_BSD_ELF_i386 ==ph.format
216 || UPX_F_VMLINUZ_ARMEL ==ph.format
217 || UPX_F_VMLINUX_ARMEL ==ph.format
218 || UPX_F_VMLINUX_ARMEB ==ph.format
219 || UPX_F_VMLINUX_PPC32 ==ph.format
220 || UPX_F_VMLINUX_PPC64LE ==ph.format
221 || UPX_F_MACH_PPC32 ==ph.format
222 || UPX_F_MACH_PPC64LE ==ph.format
223 || UPX_F_MACH_i386 ==ph.format
224 || UPX_F_DYLIB_i386 ==ph.format
225 ) {
226 return opt->small ? lzma_elf_small : lzma_elf_fast;
227 }
228 return opt->small ? lzma_small : lzma_fast;
229 }
230 throwInternalError("bad decompressor");
231 return NULL;
232 }
233
234
getDecompressorWrkmemSize() const235 unsigned Packer::getDecompressorWrkmemSize() const
236 {
237 unsigned size = 0;
238 if (M_IS_LZMA(ph.method))
239 {
240 const lzma_compress_result_t *res = &ph.compress_result.result_lzma;
241 // FIXME - this is for i386 only
242 size = 8 + 4 + ALIGN_UP(2 * res->num_probs, 4u);
243 size = ALIGN_UP(size, 16u);
244 }
245 assert((int)size >= 0);
246 return size;
247 }
248
defineDecompressorSymbols()249 void Packer::defineDecompressorSymbols()
250 {
251 if (UPX_F_LINUX_ELF_i386 ==ph.format
252 || UPX_F_LINUX_ELFI_i386 ==ph.format
253 || UPX_F_LINUX_ELF64_AMD ==ph.format
254 || UPX_F_LINUX_ELF32_ARMEL==ph.format
255 || UPX_F_LINUX_ELFPPC32 ==ph.format
256 || UPX_F_LINUX_ELFPPC64LE ==ph.format
257 || UPX_F_LINUX_ELF32_ARMEB==ph.format
258 || UPX_F_BSD_ELF_i386 ==ph.format
259 || UPX_F_VMLINUZ_ARMEL ==ph.format
260 || UPX_F_VMLINUX_ARMEL ==ph.format
261 || UPX_F_VMLINUX_ARMEB ==ph.format
262 || UPX_F_VMLINUX_PPC32 ==ph.format
263 || UPX_F_VMLINUX_PPC64LE ==ph.format
264 || UPX_F_MACH_PPC32 ==ph.format
265 || UPX_F_MACH_PPC64LE ==ph.format
266 || UPX_F_MACH_i386 ==ph.format
267 || UPX_F_DYLIB_i386 ==ph.format
268 ) {
269 // ELF calls the decompressor many times; the parameters change!
270 return;
271 }
272 if (M_IS_LZMA(ph.method))
273 {
274 const lzma_compress_result_t *res = &ph.compress_result.result_lzma;
275 upx_uint32_t properties = // lc, lp, pb, dummy
276 (res->lit_context_bits << 0) |
277 (res->lit_pos_bits << 8) |
278 (res->pos_bits << 16);
279 if (linker->bele->isBE()) // big endian - bswap32
280 acc_swab32s(&properties);
281
282 linker->defineSymbol("lzma_properties", properties);
283 // len - 2 because of properties
284 linker->defineSymbol("lzma_c_len", ph.c_len - 2);
285 linker->defineSymbol("lzma_u_len", ph.u_len);
286 unsigned stack = getDecompressorWrkmemSize();
287 linker->defineSymbol("lzma_stack_adjust", 0u - stack);
288
289 if (ph.format == UPX_F_DOS_EXE)
290 {
291 linker->defineSymbol("lzma_properties_hi", properties >> 16); // pb
292 linker->defineSymbol("lzma_c_len_hi", (ph.c_len - 2) >> 16);
293 linker->defineSymbol("lzma_u_len_hi", ph.u_len >> 16);
294 linker->defineSymbol("lzma_u_len_segment", (ph.u_len & 0xf0000) >> 4);
295 }
296 }
297 }
298
299 /* vim:set ts=4 sw=4 et: */
300