1 /* ctsw.h -- call-/swaptrick 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 call-/swaptrick ("naive")
32 **************************************************************************/
33 
34 #define CTSW16(f, cond1, cond2, addvalue, get, set) \
35     upx_byte *b = f->buf; \
36     upx_byte *b_end = b + f->buf_len - 3; \
37     do { \
38         if (cond1) \
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         else if (cond2) \
48         { \
49             b += 1; \
50             unsigned a = (unsigned) (b - f->buf); \
51             f->lastcall = a; \
52             set(b, get(b)); \
53             f->calls++; \
54             b += 2 - 1; \
55         } \
56     } while (++b < b_end); \
57     if (f->lastcall) f->lastcall += 2; \
58     return 0;
59 
60 
61 // filter
f_ctsw16_e8_e9(Filter * f)62 static int f_ctsw16_e8_e9(Filter *f)
63 {
64     CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
65 }
66 
f_ctsw16_e9_e8(Filter * f)67 static int f_ctsw16_e9_e8(Filter *f)
68 {
69     CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
70 }
71 
72 
73 // unfilter
u_ctsw16_e8_e9(Filter * f)74 static int u_ctsw16_e8_e9(Filter *f)
75 {
76     CTSW16(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
77 }
78 
u_ctsw16_e9_e8(Filter * f)79 static int u_ctsw16_e9_e8(Filter *f)
80 {
81     CTSW16(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
82 }
83 
84 
85 // scan
s_ctsw16_e8_e9(Filter * f)86 static int s_ctsw16_e8_e9(Filter *f)
87 {
88     CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
89 }
90 
s_ctsw16_e9_e8(Filter * f)91 static int s_ctsw16_e9_e8(Filter *f)
92 {
93     CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
94 }
95 
96 
97 #undef CTSW16
98 
99 
100 /*************************************************************************
101 // 32-bit call-/swaptrick ("naive")
102 **************************************************************************/
103 
104 #define CTSW32(f, cond1, cond2, addvalue, get, set) \
105     upx_byte *b = f->buf; \
106     upx_byte *b_end = b + f->buf_len - 5; \
107     do { \
108         if (cond1) \
109         { \
110             b += 1; \
111             unsigned a = (unsigned) (b - f->buf); \
112             f->lastcall = a; \
113             set(b, get(b) + (addvalue)); \
114             f->calls++; \
115             b += 4 - 1; \
116         } \
117         else if (cond2) \
118         { \
119             b += 1; \
120             unsigned a = (unsigned) (b - f->buf); \
121             f->lastcall = a; \
122             set(b, get(b)); \
123             f->calls++; \
124             b += 4 - 1; \
125         } \
126     } while (++b < b_end); \
127     if (f->lastcall) f->lastcall += 4; \
128     return 0;
129 
130 
131 // filter
f_ctsw32_e8_e9(Filter * f)132 static int f_ctsw32_e8_e9(Filter *f)
133 {
134     CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
135 }
136 
f_ctsw32_e9_e8(Filter * f)137 static int f_ctsw32_e9_e8(Filter *f)
138 {
139     CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
140 }
141 
142 
143 // unfilter
u_ctsw32_e8_e9(Filter * f)144 static int u_ctsw32_e8_e9(Filter *f)
145 {
146     CTSW32(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
147 }
148 
u_ctsw32_e9_e8(Filter * f)149 static int u_ctsw32_e9_e8(Filter *f)
150 {
151     CTSW32(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
152 }
153 
154 
155 // scan
s_ctsw32_e8_e9(Filter * f)156 static int s_ctsw32_e8_e9(Filter *f)
157 {
158     CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
159 }
160 
s_ctsw32_e9_e8(Filter * f)161 static int s_ctsw32_e9_e8(Filter *f)
162 {
163     CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
164 }
165 
166 
167 #undef CTSW32
168 
169 /* vim:set ts=4 sw=4 et: */
170