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