1 /* filteri.cpp -- filter implementation (low-level)
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 "filter.h"
31 
32 static unsigned
umin(unsigned const a,unsigned const b)33 umin(unsigned const a, unsigned const b)
34 {
35     return (a<=b) ? a : b;
36 }
37 
38 
39 #define set_dummy(p, v)     ((void)0)
40 #define get_8(p)            (*(p))
41 #define set_8(p, v)         (*(p) = (v))
42 
43 
44 /*************************************************************************
45 // util
46 **************************************************************************/
47 
48 #include "filter/getcto.h"
49 
50 
51 /*************************************************************************
52 // simple filters: calltrick / swaptrick / delta / ...
53 **************************************************************************/
54 
55 #include "filter/ct.h"
56 #include "filter/sw.h"
57 #include "filter/ctsw.h"
58 
59 #include "filter/sub8.h"
60 #include "filter/sub16.h"
61 #include "filter/sub32.h"
62 
63 
64 /*************************************************************************
65 // cto calltrick
66 **************************************************************************/
67 
68 #define COND(b,x)               (b[x] == 0xe8)
69 #define F                       f_cto32_e8_bswap_le
70 #define U                       u_cto32_e8_bswap_le
71 #include "filter/cto.h"
72 #define F                       s_cto32_e8_bswap_le
73 #include "filter/cto.h"
74 #undef COND
75 
76 #define COND(b,x)               (b[x] == 0xe9)
77 #define F                       f_cto32_e9_bswap_le
78 #define U                       u_cto32_e9_bswap_le
79 #include "filter/cto.h"
80 #define F                       s_cto32_e9_bswap_le
81 #include "filter/cto.h"
82 #undef COND
83 
84 #define COND(b,x)               (b[x] == 0xe8 || b[x] == 0xe9)
85 #define F                       f_cto32_e8e9_bswap_le
86 #define U                       u_cto32_e8e9_bswap_le
87 #include "filter/cto.h"
88 #define F                       s_cto32_e8e9_bswap_le
89 #include "filter/cto.h"
90 #undef COND
91 
92 
93 /*************************************************************************
94 // cto calltrick with jmp
95 **************************************************************************/
96 
97 #define COND(b,x,lastcall) (b[x] == 0xe8 || b[x] == 0xe9)
98 #define F                       f_ctoj32_e8e9_bswap_le
99 #define U                       u_ctoj32_e8e9_bswap_le
100 #include "filter/ctoj.h"
101 #define F                       s_ctoj32_e8e9_bswap_le
102 #include "filter/ctoj.h"
103 #undef COND
104 
105 
106 /*************************************************************************
107 // cto calltrick with jmp, optional jcc
108 **************************************************************************/
109 
110 #define COND1(b,x)     (b[x] == 0xe8 || b[x] == 0xe9)
111 #define COND2(b,x,lc)  (lc!=(x) && 0xf==b[(x)-1] && 0x80<=b[x] && b[x]<=0x8f)
112 #define COND(b,x,lc,id) (COND1(b,x) || ((9<=(0xf&(id))) && COND2(b,x,lc)))
113 #define F                       f_ctok32_e8e9_bswap_le
114 #define U                       u_ctok32_e8e9_bswap_le
115 #include "filter/ctok.h"
116 #define F                       s_ctok32_e8e9_bswap_le
117 #include "filter/ctok.h"
118 #undef COND
119 #undef COND2
120 #undef COND1
121 
122 
123 /*************************************************************************
124 // cto calltrick with jmp and jcc and relative renumbering
125 **************************************************************************/
126 
127 #define COND_CALL(which,b,x) ((which = 0), b[x] == 0xe8)
128 #define COND_JMP( which,b,x) ((which = 1), b[x] == 0xe9)
129 #define COND_JCC( which,b,lastcall,x,y,z) ((which = 2), \
130          (lastcall!=(x) && 0xf==b[y] && 0x80<=b[z] && b[z]<=0x8f))
131 #define COND1(which,b,x) (COND_CALL(which,b,x) || COND_JMP(which,b,x))
132 #define COND2(which,b,lastcall,x,y,z) COND_JCC(which,b,lastcall,x,y,z)
133 
134 #define CONDF(which,b,x,lastcall) \
135     (COND1(which,b,x) || COND2(which,b,lastcall,x,(x)-1, x   ))
136 #define CONDU(which,b,x,lastcall) \
137     (COND1(which,b,x) || COND2(which,b,lastcall,x, x   ,(x)-1))
138 
139 #define F                       f_ctojr32_e8e9_bswap_le
140 #define U                       u_ctojr32_e8e9_bswap_le
141 #include "filter/ctojr.h"
142 #define F                       s_ctojr32_e8e9_bswap_le
143 #include "filter/ctojr.h"
144 
145 #undef CONDU
146 #undef CONDF
147 #undef COND2
148 #undef COND1
149 #undef COND_JCC
150 #undef COND_JMP
151 #undef COND_CALL
152 
153 
154 /*************************************************************************
155 // PowerPC branch [incl. call] trick
156 **************************************************************************/
157 
158 #define COND(b,x) (18==(get_be32(b+x)>>26))
159 #define F                       f_ppcbxx
160 #define U                       u_ppcbxx
161 #include "filter/ppcbxx.h"
162 #define F                       s_ppcbxx
163 #include "filter/ppcbxx.h"
164 #undef COND
165 
166 
167 /*************************************************************************
168 // database for use in class Filter
169 **************************************************************************/
170 
171 const FilterImp::FilterEntry FilterImp::filters[] = {
172     // no filter
173     { 0x00, 0,          0, NULL, NULL, NULL },
174 
175     // 16-bit calltrick
176     { 0x01, 4,          0, f_ct16_e8, u_ct16_e8, s_ct16_e8 },
177     { 0x02, 4,          0, f_ct16_e9, u_ct16_e9, s_ct16_e9 },
178     { 0x03, 4,          0, f_ct16_e8e9, u_ct16_e8e9, s_ct16_e8e9 },
179     { 0x04, 4,          0, f_ct16_e8_bswap_le, u_ct16_e8_bswap_le, s_ct16_e8_bswap_le },
180     { 0x05, 4,          0, f_ct16_e9_bswap_le, u_ct16_e9_bswap_le, s_ct16_e9_bswap_le },
181     { 0x06, 4,          0, f_ct16_e8e9_bswap_le, u_ct16_e8e9_bswap_le, s_ct16_e8e9_bswap_le },
182     { 0x07, 4,          0, f_ct16_e8_bswap_be, u_ct16_e8_bswap_be, s_ct16_e8_bswap_be },
183     { 0x08, 4,          0, f_ct16_e9_bswap_be, u_ct16_e9_bswap_be, s_ct16_e9_bswap_be },
184     { 0x09, 4,          0, f_ct16_e8e9_bswap_be, u_ct16_e8e9_bswap_be, s_ct16_e8e9_bswap_be },
185 
186     // 16-bit swaptrick
187     { 0x0a, 4,          0, f_sw16_e8, u_sw16_e8, s_sw16_e8 },
188     { 0x0b, 4,          0, f_sw16_e9, u_sw16_e9, s_sw16_e9 },
189     { 0x0c, 4,          0, f_sw16_e8e9, u_sw16_e8e9, s_sw16_e8e9 },
190 
191     // 16-bit call-/swaptrick
192     { 0x0d, 4,          0, f_ctsw16_e8_e9, u_ctsw16_e8_e9, s_ctsw16_e8_e9 },
193     { 0x0e, 4,          0, f_ctsw16_e9_e8, u_ctsw16_e9_e8, s_ctsw16_e9_e8 },
194 
195     // 32-bit calltrick
196     { 0x11, 6,          0, f_ct32_e8, u_ct32_e8, s_ct32_e8 },
197     { 0x12, 6,          0, f_ct32_e9, u_ct32_e9, s_ct32_e9 },
198     { 0x13, 6,          0, f_ct32_e8e9, u_ct32_e8e9, s_ct32_e8e9 },
199     { 0x14, 6,          0, f_ct32_e8_bswap_le, u_ct32_e8_bswap_le, s_ct32_e8_bswap_le },
200     { 0x15, 6,          0, f_ct32_e9_bswap_le, u_ct32_e9_bswap_le, s_ct32_e9_bswap_le },
201     { 0x16, 6,          0, f_ct32_e8e9_bswap_le, u_ct32_e8e9_bswap_le, s_ct32_e8e9_bswap_le },
202     { 0x17, 6,          0, f_ct32_e8_bswap_be, u_ct32_e8_bswap_be, s_ct32_e8_bswap_be },
203     { 0x18, 6,          0, f_ct32_e9_bswap_be, u_ct32_e9_bswap_be, s_ct32_e9_bswap_be },
204     { 0x19, 6,          0, f_ct32_e8e9_bswap_be, u_ct32_e8e9_bswap_be, s_ct32_e8e9_bswap_be },
205 
206     // 32-bit swaptrick
207     { 0x1a, 6,          0, f_sw32_e8, u_sw32_e8, s_sw32_e8 },
208     { 0x1b, 6,          0, f_sw32_e9, u_sw32_e9, s_sw32_e9 },
209     { 0x1c, 6,          0, f_sw32_e8e9, u_sw32_e8e9, s_sw32_e8e9 },
210 
211     // 32-bit call-/swaptrick
212     { 0x1d, 6,          0, f_ctsw32_e8_e9, u_ctsw32_e8_e9, s_ctsw32_e8_e9 },
213     { 0x1e, 6,          0, f_ctsw32_e9_e8, u_ctsw32_e9_e8, s_ctsw32_e9_e8 },
214 
215     // 32-bit cto calltrick
216     { 0x24, 6, 0x00ffffff, f_cto32_e8_bswap_le, u_cto32_e8_bswap_le, s_cto32_e8_bswap_le },
217     { 0x25, 6, 0x00ffffff, f_cto32_e9_bswap_le, u_cto32_e9_bswap_le, s_cto32_e9_bswap_le },
218     { 0x26, 6, 0x00ffffff, f_cto32_e8e9_bswap_le, u_cto32_e8e9_bswap_le, s_cto32_e8e9_bswap_le },
219 
220     // 32-bit cto calltrick with jmp
221     { 0x36, 6, 0x00ffffff, f_ctoj32_e8e9_bswap_le, u_ctoj32_e8e9_bswap_le, s_ctoj32_e8e9_bswap_le },
222 
223     // 32-bit calltrick with jmp, optional jcc; runtime can unfilter more than one block
224     { 0x46, 6, 0x00ffffff, f_ctok32_e8e9_bswap_le, u_ctok32_e8e9_bswap_le, s_ctok32_e8e9_bswap_le },
225     { 0x49, 6, 0x00ffffff, f_ctok32_e8e9_bswap_le, u_ctok32_e8e9_bswap_le, s_ctok32_e8e9_bswap_le },
226 
227     // 24-bit calltrick for arm
228     { 0x50, 8, 0x01ffffff, f_ct24arm_le, u_ct24arm_le, s_ct24arm_le },
229     { 0x51, 8, 0x01ffffff, f_ct24arm_be, u_ct24arm_be, s_ct24arm_be },
230 
231     // 26-bit calltrick for arm64
232     { 0x52, 8, 0x03ffffff, f_ct26arm_le, u_ct26arm_le, s_ct26arm_le },
233 
234     // 32-bit cto calltrick with jmp and jcc(swap 0x0f/0x8Y) and relative renumbering
235     { 0x80, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
236     { 0x81, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
237     { 0x82, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
238     { 0x83, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
239     { 0x84, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
240     { 0x85, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
241     { 0x86, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
242     { 0x87, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
243 
244     // simple delta filter
245     { 0x90, 2,          0, f_sub8_1, u_sub8_1, s_sub8_1 },
246     { 0x91, 3,          0, f_sub8_2, u_sub8_2, s_sub8_2 },
247     { 0x92, 4,          0, f_sub8_3, u_sub8_3, s_sub8_3 },
248     { 0x93, 5,          0, f_sub8_4, u_sub8_4, s_sub8_4 },
249 
250     { 0xa0,99,          0, f_sub16_1, u_sub16_1, s_sub16_1 },
251     { 0xa1,99,          0, f_sub16_2, u_sub16_2, s_sub16_2 },
252     { 0xa2,99,          0, f_sub16_3, u_sub16_3, s_sub16_3 },
253     { 0xa3,99,          0, f_sub16_4, u_sub16_4, s_sub16_4 },
254 
255     { 0xb0,99,          0, f_sub32_1, u_sub32_1, s_sub32_1 },
256     { 0xb1,99,          0, f_sub32_2, u_sub32_2, s_sub32_2 },
257     { 0xb2,99,          0, f_sub32_3, u_sub32_3, s_sub32_3 },
258     { 0xb3,99,          0, f_sub32_4, u_sub32_4, s_sub32_4 },
259 
260     // PowerPC branch+call trick
261     { 0xd0, 8,          0, f_ppcbxx, u_ppcbxx, s_ppcbxx },
262 };
263 
264 const int FilterImp::n_filters = TABLESIZE(filters);
265 
266 /* vim:set ts=4 sw=4 et: */
267