1 /* ct.h -- calltrick filter
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
30 /*************************************************************************
31 // 16-bit calltrick ("naive")
32 **************************************************************************/
33
34 #define CT16(f, cond, addvalue, get, set) \
35 upx_byte *b = f->buf; \
36 upx_byte *b_end = b + f->buf_len - 3; \
37 do { \
38 if (cond) \
39 { \
40 b += 1; \
41 unsigned a = (unsigned) (b - f->buf); \
42 f->lastcall = a; \
43 set(b, get(b) + (addvalue)); \
44 f->calls++; \
45 b += 2 - 1; \
46 } \
47 } while (++b < b_end); \
48 if (f->lastcall) f->lastcall += 2; \
49 return 0;
50
51
52
53 // filter: e8, e9, e8e9
f_ct16_e8(Filter * f)54 static int f_ct16_e8(Filter *f)
55 {
56 CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_le16)
57 }
58
f_ct16_e9(Filter * f)59 static int f_ct16_e9(Filter *f)
60 {
61 CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_le16)
62 }
63
f_ct16_e8e9(Filter * f)64 static int f_ct16_e8e9(Filter *f)
65 {
66 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_le16)
67 }
68
69
70 // unfilter: e8, e9, e8e9
u_ct16_e8(Filter * f)71 static int u_ct16_e8(Filter *f)
72 {
73 CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_le16)
74 }
75
u_ct16_e9(Filter * f)76 static int u_ct16_e9(Filter *f)
77 {
78 CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
79 }
80
u_ct16_e8e9(Filter * f)81 static int u_ct16_e8e9(Filter *f)
82 {
83 CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
84 }
85
86
87 // scan: e8, e9, e8e9
s_ct16_e8(Filter * f)88 static int s_ct16_e8(Filter *f)
89 {
90 CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
91 }
92
s_ct16_e9(Filter * f)93 static int s_ct16_e9(Filter *f)
94 {
95 CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
96 }
97
s_ct16_e8e9(Filter * f)98 static int s_ct16_e8e9(Filter *f)
99 {
100 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
101 }
102
103
104 // filter: e8, e9, e8e9 with bswap le->be
f_ct16_e8_bswap_le(Filter * f)105 static int f_ct16_e8_bswap_le(Filter *f)
106 {
107 CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
108 }
109
f_ct16_e9_bswap_le(Filter * f)110 static int f_ct16_e9_bswap_le(Filter *f)
111 {
112 CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
113 }
114
f_ct16_e8e9_bswap_le(Filter * f)115 static int f_ct16_e8e9_bswap_le(Filter *f)
116 {
117 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_be16)
118 }
119
120
121 // unfilter: e8, e9, e8e9 with bswap le->be
u_ct16_e8_bswap_le(Filter * f)122 static int u_ct16_e8_bswap_le(Filter *f)
123 {
124 CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
125 }
126
u_ct16_e9_bswap_le(Filter * f)127 static int u_ct16_e9_bswap_le(Filter *f)
128 {
129 CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
130 }
131
u_ct16_e8e9_bswap_le(Filter * f)132 static int u_ct16_e8e9_bswap_le(Filter *f)
133 {
134 CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
135 }
136
137
138 // scan: e8, e9, e8e9 with bswap le->be
s_ct16_e8_bswap_le(Filter * f)139 static int s_ct16_e8_bswap_le(Filter *f)
140 {
141 CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_dummy)
142 }
143
s_ct16_e9_bswap_le(Filter * f)144 static int s_ct16_e9_bswap_le(Filter *f)
145 {
146 CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_dummy)
147 }
148
s_ct16_e8e9_bswap_le(Filter * f)149 static int s_ct16_e8e9_bswap_le(Filter *f)
150 {
151 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_dummy)
152 }
153
154
155 // filter: e8, e9, e8e9 with bswap be->le
f_ct16_e8_bswap_be(Filter * f)156 static int f_ct16_e8_bswap_be(Filter *f)
157 {
158 CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_le16)
159 }
160
f_ct16_e9_bswap_be(Filter * f)161 static int f_ct16_e9_bswap_be(Filter *f)
162 {
163 CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_le16)
164 }
165
f_ct16_e8e9_bswap_be(Filter * f)166 static int f_ct16_e8e9_bswap_be(Filter *f)
167 {
168 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_le16)
169 }
170
171
172 // unfilter: e8, e9, e8e9 with bswap be->le
u_ct16_e8_bswap_be(Filter * f)173 static int u_ct16_e8_bswap_be(Filter *f)
174 {
175 CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_be16)
176 }
177
u_ct16_e9_bswap_be(Filter * f)178 static int u_ct16_e9_bswap_be(Filter *f)
179 {
180 CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
181 }
182
u_ct16_e8e9_bswap_be(Filter * f)183 static int u_ct16_e8e9_bswap_be(Filter *f)
184 {
185 CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
186 }
187
188
189 // scan: e8, e9, e8e9 with bswap be->le
s_ct16_e8_bswap_be(Filter * f)190 static int s_ct16_e8_bswap_be(Filter *f)
191 {
192 CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
193 }
194
s_ct16_e9_bswap_be(Filter * f)195 static int s_ct16_e9_bswap_be(Filter *f)
196 {
197 CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
198 }
199
s_ct16_e8e9_bswap_be(Filter * f)200 static int s_ct16_e8e9_bswap_be(Filter *f)
201 {
202 CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
203 }
204
205
206 #undef CT16
207
208
209 /*************************************************************************
210 // 32-bit calltrick ("naive")
211 **************************************************************************/
212
213 #define CT32(f, cond, addvalue, get, set) \
214 upx_byte *b = f->buf; \
215 upx_byte *b_end = b + f->buf_len - 5; \
216 do { \
217 if (cond) \
218 { \
219 b += 1; \
220 unsigned a = (unsigned) (b - f->buf); \
221 f->lastcall = a; \
222 set(b, get(b) + (addvalue)); \
223 f->calls++; \
224 b += 4 - 1; \
225 } \
226 } while (++b < b_end); \
227 if (f->lastcall) f->lastcall += 4; \
228 return 0;
229
230
231 // filter: e8, e9, e8e9
f_ct32_e8(Filter * f)232 static int f_ct32_e8(Filter *f)
233 {
234 CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_le32)
235 }
236
f_ct32_e9(Filter * f)237 static int f_ct32_e9(Filter *f)
238 {
239 CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_le32)
240 }
241
f_ct32_e8e9(Filter * f)242 static int f_ct32_e8e9(Filter *f)
243 {
244 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_le32)
245 }
246
247
248 // unfilter: e8, e9, e8e9
u_ct32_e8(Filter * f)249 static int u_ct32_e8(Filter *f)
250 {
251 CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_le32)
252 }
253
u_ct32_e9(Filter * f)254 static int u_ct32_e9(Filter *f)
255 {
256 CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
257 }
258
u_ct32_e8e9(Filter * f)259 static int u_ct32_e8e9(Filter *f)
260 {
261 CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
262 }
263
264
265 // scan: e8, e9, e8e9
s_ct32_e8(Filter * f)266 static int s_ct32_e8(Filter *f)
267 {
268 CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
269 }
270
s_ct32_e9(Filter * f)271 static int s_ct32_e9(Filter *f)
272 {
273 CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
274 }
275
s_ct32_e8e9(Filter * f)276 static int s_ct32_e8e9(Filter *f)
277 {
278 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
279 }
280
281
282 // filter: e8, e9, e8e9 with bswap le->be
f_ct32_e8_bswap_le(Filter * f)283 static int f_ct32_e8_bswap_le(Filter *f)
284 {
285 CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
286 }
287
f_ct32_e9_bswap_le(Filter * f)288 static int f_ct32_e9_bswap_le(Filter *f)
289 {
290 CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
291 }
292
f_ct32_e8e9_bswap_le(Filter * f)293 static int f_ct32_e8e9_bswap_le(Filter *f)
294 {
295 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_be32)
296 }
297
298
299 // unfilter: e8, e9, e8e9 with bswap le->be
u_ct32_e8_bswap_le(Filter * f)300 static int u_ct32_e8_bswap_le(Filter *f)
301 {
302 CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
303 }
304
u_ct32_e9_bswap_le(Filter * f)305 static int u_ct32_e9_bswap_le(Filter *f)
306 {
307 CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
308 }
309
u_ct32_e8e9_bswap_le(Filter * f)310 static int u_ct32_e8e9_bswap_le(Filter *f)
311 {
312 CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
313 }
314
315
316 // scan: e8, e9, e8e9 with bswap le->be
s_ct32_e8_bswap_le(Filter * f)317 static int s_ct32_e8_bswap_le(Filter *f)
318 {
319 CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_dummy)
320 }
321
s_ct32_e9_bswap_le(Filter * f)322 static int s_ct32_e9_bswap_le(Filter *f)
323 {
324 CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_dummy)
325 }
326
s_ct32_e8e9_bswap_le(Filter * f)327 static int s_ct32_e8e9_bswap_le(Filter *f)
328 {
329 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_dummy)
330 }
331
332
333 // filter: e8, e9, e8e9 with bswap be->le
f_ct32_e8_bswap_be(Filter * f)334 static int f_ct32_e8_bswap_be(Filter *f)
335 {
336 CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_le32)
337 }
338
f_ct32_e9_bswap_be(Filter * f)339 static int f_ct32_e9_bswap_be(Filter *f)
340 {
341 CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_le32)
342 }
343
f_ct32_e8e9_bswap_be(Filter * f)344 static int f_ct32_e8e9_bswap_be(Filter *f)
345 {
346 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_le32)
347 }
348
349
350 // unfilter: e8, e9, e8e9 with bswap be->le
u_ct32_e8_bswap_be(Filter * f)351 static int u_ct32_e8_bswap_be(Filter *f)
352 {
353 CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_be32)
354 }
355
u_ct32_e9_bswap_be(Filter * f)356 static int u_ct32_e9_bswap_be(Filter *f)
357 {
358 CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
359 }
360
u_ct32_e8e9_bswap_be(Filter * f)361 static int u_ct32_e8e9_bswap_be(Filter *f)
362 {
363 CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
364 }
365
366
367 // scan: e8, e9, e8e9 with bswap be->le
s_ct32_e8_bswap_be(Filter * f)368 static int s_ct32_e8_bswap_be(Filter *f)
369 {
370 CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
371 }
372
s_ct32_e9_bswap_be(Filter * f)373 static int s_ct32_e9_bswap_be(Filter *f)
374 {
375 CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
376 }
377
s_ct32_e8e9_bswap_be(Filter * f)378 static int s_ct32_e8e9_bswap_be(Filter *f)
379 {
380 CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
381 }
382
383
384 #undef CT32
385
386 /*************************************************************************
387 // 24-bit ARM calltrick ("naive")
388 **************************************************************************/
389
390 #define CT24ARM_LE(f, cond, addvalue, get, set) \
391 upx_byte *b = f->buf; \
392 upx_byte *b_end = b + f->buf_len - 4; \
393 do { \
394 if (cond) \
395 { \
396 unsigned a = (unsigned) (b - f->buf); \
397 f->lastcall = a; \
398 set(b, get(b) + (addvalue)); \
399 f->calls++; \
400 } \
401 b += 4; \
402 } while (b < b_end); \
403 if (f->lastcall) f->lastcall += 4; \
404 return 0;
405
406
407 #define ARMCT_COND_le (((b[3] & 0x0f) == 0x0b))
408
f_ct24arm_le(Filter * f)409 static int f_ct24arm_le(Filter *f)
410 {
411 CT24ARM_LE(f, ARMCT_COND_le, a / 4 + f->addvalue, get_le24, set_le24)
412 }
413
u_ct24arm_le(Filter * f)414 static int u_ct24arm_le(Filter *f)
415 {
416 CT24ARM_LE(f, ARMCT_COND_le, 0 - a / 4 - f->addvalue, get_le24, set_le24)
417 }
418
s_ct24arm_le(Filter * f)419 static int s_ct24arm_le(Filter *f)
420 {
421 CT24ARM_LE(f, ARMCT_COND_le, a + f->addvalue, get_le24, set_dummy)
422 }
423
424 #undef CT24ARM_LE
425
426 #define CT24ARM_BE(f, cond, addvalue, get, set) \
427 upx_byte *b = f->buf; \
428 upx_byte *b_end = b + f->buf_len - 4; \
429 do { \
430 if (cond) \
431 { \
432 unsigned a = (unsigned) (b - f->buf); \
433 f->lastcall = a; \
434 set(1+b, get(1+b) + (addvalue)); \
435 f->calls++; \
436 } \
437 b += 4; \
438 } while (b < b_end); \
439 if (f->lastcall) f->lastcall += 4; \
440 return 0;
441
442 #define ARMCT_COND_be (((b[0] & 0x0f) == 0x0b))
443
f_ct24arm_be(Filter * f)444 static int f_ct24arm_be(Filter *f)
445 {
446 CT24ARM_BE(f, ARMCT_COND_be, a / 4 + f->addvalue, get_be24, set_be24)
447 }
448
u_ct24arm_be(Filter * f)449 static int u_ct24arm_be(Filter *f)
450 {
451 CT24ARM_BE(f, ARMCT_COND_be, 0 - a / 4 - f->addvalue, get_be24, set_be24)
452 }
453
s_ct24arm_be(Filter * f)454 static int s_ct24arm_be(Filter *f)
455 {
456 CT24ARM_BE(f, ARMCT_COND_be, a + f->addvalue, get_be24, set_dummy)
457 }
458
459 #undef CT24ARM_BE
460 #undef ARMCT_COND
461
462 /*************************************************************************
463 // 26-bit ARM calltrick ("naive")
464 **************************************************************************/
465
466 #define CT26ARM_LE(f, cond, addvalue, get, set) \
467 upx_byte *b = f->buf; \
468 upx_byte *b_end = b + f->buf_len - 4; \
469 do { \
470 if (cond) \
471 { \
472 unsigned a = (unsigned) (b - f->buf); \
473 f->lastcall = a; \
474 set(b, get(b) + (addvalue)); \
475 f->calls++; \
476 } \
477 b += 4; \
478 } while (b < b_end); \
479 if (f->lastcall) f->lastcall += 4; \
480 return 0;
481
482
483 #define ARMCT_COND (((b[3] & 0x7C) == 0x14))
484
f_ct26arm_le(Filter * f)485 static int f_ct26arm_le(Filter *f)
486 {
487 CT26ARM_LE(f, ARMCT_COND, a / 4 + f->addvalue, get_le26, set_le26)
488 }
489
u_ct26arm_le(Filter * f)490 static int u_ct26arm_le(Filter *f)
491 {
492 CT26ARM_LE(f, ARMCT_COND, 0 - a / 4 - f->addvalue, get_le26, set_le26)
493 }
494
s_ct26arm_le(Filter * f)495 static int s_ct26arm_le(Filter *f)
496 {
497 CT26ARM_LE(f, ARMCT_COND, a + f->addvalue, get_le26, set_dummy)
498 }
499
500 #undef CT26ARM_LE
501 #undef ARMCT_COND
502
503 /* vim:set ts=4 sw=4 et: */
504