/src/upx/src/packer_f.cpp
Line | Count | Source |
1 | | /* packer_f.cpp -- Packer filter handling |
2 | | |
3 | | This file is part of the UPX executable compressor. |
4 | | |
5 | | Copyright (C) Markus Franz Xaver Johannes Oberhumer |
6 | | Copyright (C) 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 | | #include "conf.h" |
29 | | #include "packer.h" |
30 | | #include "filter.h" |
31 | | #include "linker.h" |
32 | | |
33 | | /************************************************************************* |
34 | | // filter util; see class FilterImpl |
35 | | **************************************************************************/ |
36 | | |
37 | 0 | bool Packer::isValidFilter(int filter_id) const { |
38 | 0 | return Filter::isValidFilter(filter_id, getFilters()); |
39 | 0 | } |
40 | | |
41 | | /************************************************************************* |
42 | | // addFilter32 |
43 | | **************************************************************************/ |
44 | | |
45 | 0 | #define NOFILT 0 // no filter |
46 | 0 | #define FNOMRU 1 // filter, but not using mru |
47 | 0 | #define MRUFLT 2 // mru filter |
48 | | |
49 | 0 | static inline unsigned f80_call(int filter_id) { return (1 + (0x0f & filter_id)) % 3; } |
50 | | |
51 | 0 | static inline unsigned f80_jmp1(int filter_id) { return ((1 + (0x0f & filter_id)) / 3) % 3; } |
52 | | |
53 | 0 | static inline unsigned f80_jcc2(int filter_id) { return f80_jmp1(filter_id); } |
54 | | |
55 | 0 | void Packer::addFilter32(int filter_id) { |
56 | 0 | assert(filter_id > 0); |
57 | 0 | assert(isValidFilter(filter_id)); |
58 | | |
59 | 0 | if (filter_id < 0x80) { |
60 | 0 | if (0x50 == (0xF0 & filter_id)) { |
61 | 0 | addLoader("ctok32.00", |
62 | 0 | ((0x50 == filter_id) ? "ctok32.50" |
63 | 0 | : (0x51 == filter_id) ? "ctok32.51" |
64 | 0 | : ""), |
65 | 0 | "ctok32.10"); |
66 | 0 | } else if ((filter_id & 0xf) % 3 == 0) { |
67 | 0 | if (filter_id < 0x40) { |
68 | 0 | addLoader("CALLTR00", (filter_id > 0x20) ? "CTCLEVE1" : "", "CALLTR01", |
69 | 0 | (filter_id & 0xf) > 3 |
70 | 0 | ? (filter_id > 0x20 ? "CTBSHR01,CTBSWA01" : "CTBROR01,CTBSWA01") |
71 | 0 | : "", |
72 | 0 | "CALLTR02"); |
73 | 0 | } else if (0x40 == (0xF0 & filter_id)) { |
74 | 0 | addLoader("ctok32.00"); |
75 | 0 | if (9 <= (0xf & filter_id)) { |
76 | 0 | addLoader("ctok32.10"); |
77 | 0 | } |
78 | 0 | addLoader("ctok32.20"); |
79 | 0 | if (9 <= (0xf & filter_id)) { |
80 | 0 | addLoader("ctok32.30"); |
81 | 0 | } |
82 | 0 | addLoader("ctok32.40"); |
83 | 0 | } |
84 | 0 | } else |
85 | 0 | addLoader("CALLTR10", (filter_id & 0xf) % 3 == 1 ? "CALLTRE8" : "CALLTRE9", "CALLTR11", |
86 | 0 | (filter_id > 0x20) ? "CTCLEVE2" : "", "CALLTR12", |
87 | 0 | (filter_id & 0xf) > 3 |
88 | 0 | ? (filter_id > 0x20 ? "CTBSHR11,CTBSWA11" : "CTBROR11,CTBSWA11") |
89 | 0 | : "", |
90 | 0 | "CALLTR13"); |
91 | 0 | } |
92 | 0 | if (0x80 == (filter_id & 0xF0)) { |
93 | 0 | const bool x386 = (opt->cpu_x86 <= opt->CPU_386); |
94 | 0 | const unsigned n_mru = ph.n_mru ? 1 + ph.n_mru : 0; |
95 | 0 | const bool mrupwr2 = (0 != n_mru) && 0 == ((n_mru - 1) & n_mru); |
96 | 0 | const unsigned f_call = f80_call(filter_id); |
97 | 0 | const unsigned f_jmp1 = f80_jmp1(filter_id); |
98 | 0 | const unsigned f_jcc2 = f80_jcc2(filter_id); |
99 | |
|
100 | 0 | if (NOFILT != f_jcc2) { |
101 | 0 | addLoader("LXJCC010"); |
102 | 0 | if (n_mru) { |
103 | 0 | addLoader("LXMRU045"); |
104 | 0 | } else { |
105 | 0 | addLoader("LXMRU046"); |
106 | 0 | } |
107 | 0 | if (0 == n_mru || MRUFLT != f_jcc2) { |
108 | 0 | addLoader("LXJCC020"); |
109 | 0 | } else { // 0 != n_mru |
110 | 0 | addLoader("LXJCC021"); |
111 | 0 | } |
112 | 0 | if (NOFILT != f_jcc2) { |
113 | 0 | addLoader("LXJCC023"); |
114 | 0 | } |
115 | 0 | } |
116 | 0 | addLoader("LXUNF037"); |
117 | 0 | if (x386) { |
118 | 0 | if (n_mru) { |
119 | 0 | addLoader("LXUNF386"); |
120 | 0 | } |
121 | 0 | addLoader("LXUNF387"); |
122 | 0 | if (n_mru) { |
123 | 0 | addLoader("LXUNF388"); |
124 | 0 | } |
125 | 0 | } else { |
126 | 0 | addLoader("LXUNF486"); |
127 | 0 | if (n_mru) { |
128 | 0 | addLoader("LXUNF487"); |
129 | 0 | } |
130 | 0 | } |
131 | 0 | if (n_mru) { |
132 | 0 | addLoader("LXMRU065"); |
133 | 0 | if (256 == n_mru) { |
134 | 0 | addLoader("MRUBYTE3"); |
135 | 0 | } else { |
136 | 0 | addLoader("MRUARB30"); |
137 | 0 | if (mrupwr2) { |
138 | 0 | addLoader("MRUBITS3"); |
139 | 0 | } else { |
140 | 0 | addLoader("MRUARB40"); |
141 | 0 | } |
142 | 0 | } |
143 | 0 | addLoader("LXMRU070"); |
144 | 0 | if (256 == n_mru) { |
145 | 0 | addLoader("MRUBYTE4"); |
146 | 0 | } else if (mrupwr2) { |
147 | 0 | addLoader("MRUBITS4"); |
148 | 0 | } else { |
149 | 0 | addLoader("MRUARB50"); |
150 | 0 | } |
151 | 0 | addLoader("LXMRU080"); |
152 | 0 | if (256 == n_mru) { |
153 | 0 | addLoader("MRUBYTE5"); |
154 | 0 | } else { |
155 | 0 | addLoader("MRUARB60"); |
156 | 0 | if (mrupwr2) { |
157 | 0 | addLoader("MRUBITS5"); |
158 | 0 | } else { |
159 | 0 | addLoader("MRUARB70"); |
160 | 0 | } |
161 | 0 | } |
162 | 0 | addLoader("LXMRU090"); |
163 | 0 | if (256 == n_mru) { |
164 | 0 | addLoader("MRUBYTE6"); |
165 | 0 | } else { |
166 | 0 | addLoader("MRUARB80"); |
167 | 0 | if (mrupwr2) { |
168 | 0 | addLoader("MRUBITS6"); |
169 | 0 | } else { |
170 | 0 | addLoader("MRUARB90"); |
171 | 0 | } |
172 | 0 | } |
173 | 0 | addLoader("LXMRU100"); |
174 | 0 | } |
175 | 0 | addLoader("LXUNF040"); |
176 | 0 | if (n_mru) { |
177 | 0 | addLoader("LXMRU110"); |
178 | 0 | } else { |
179 | 0 | addLoader("LXMRU111"); |
180 | 0 | } |
181 | 0 | addLoader("LXUNF041"); |
182 | 0 | addLoader("LXUNF042"); |
183 | 0 | if (n_mru) { |
184 | 0 | addLoader("LXMRU010"); |
185 | 0 | if (NOFILT != f_jmp1 && NOFILT == f_call) { |
186 | 0 | addLoader("LXJMPA00"); |
187 | 0 | } else { |
188 | 0 | addLoader("LXCALLB0"); |
189 | 0 | } |
190 | 0 | addLoader("LXUNF021"); |
191 | 0 | } else { |
192 | 0 | addLoader("LXMRU022"); |
193 | 0 | if (NOFILT != f_jmp1 && NOFILT == f_call) { |
194 | 0 | addLoader("LXJMPA01"); |
195 | 0 | } else { |
196 | 0 | addLoader("LXCALLB1"); |
197 | 0 | } |
198 | 0 | } |
199 | 0 | if (n_mru) { |
200 | 0 | if (256 != n_mru && mrupwr2) { |
201 | 0 | addLoader("MRUBITS1"); |
202 | 0 | } |
203 | 0 | addLoader("LXMRU030"); |
204 | 0 | if (256 == n_mru) { |
205 | 0 | addLoader("MRUBYTE1"); |
206 | 0 | } else { |
207 | 0 | addLoader("MRUARB10"); |
208 | 0 | } |
209 | 0 | addLoader("LXMRU040"); |
210 | 0 | } |
211 | |
|
212 | 0 | addLoader("LXUNF030"); |
213 | 0 | if (NOFILT != f_jcc2) { |
214 | 0 | addLoader("LXJCC000"); |
215 | 0 | } |
216 | 0 | if (NOFILT != f_call || NOFILT != f_jmp1) { // at least one is filtered |
217 | | // shift opcode origin to zero |
218 | 0 | if (0 == n_mru) { |
219 | 0 | addLoader("LXCJ0MRU"); |
220 | 0 | } else { |
221 | 0 | addLoader("LXCJ1MRU"); |
222 | 0 | } |
223 | | |
224 | | // determine if in range |
225 | 0 | if ((NOFILT != f_call) && (NOFILT != f_jmp1)) { // unfilter both |
226 | 0 | addLoader("LXCALJMP"); |
227 | 0 | } |
228 | 0 | if ((NOFILT == f_call) ^ (NOFILT == f_jmp1)) { // unfilter just one |
229 | 0 | if (0 == n_mru) { |
230 | 0 | addLoader("LXCALL00"); |
231 | 0 | } else { |
232 | 0 | addLoader("LXCALL01"); |
233 | 0 | } |
234 | 0 | } |
235 | | |
236 | | // determine if mru applies |
237 | 0 | if (0 == n_mru || !((FNOMRU == f_call) || (FNOMRU == f_jmp1))) { |
238 | | // no mru, or no exceptions |
239 | 0 | addLoader("LXCJ2MRU"); |
240 | 0 | } else { |
241 | | // mru on one, but not the other |
242 | 0 | addLoader("LXCJ4MRU"); |
243 | 0 | if (MRUFLT == f_jmp1) { // JMP only |
244 | 0 | addLoader("LXCJ6MRU"); |
245 | 0 | } else if (MRUFLT == f_call) { // CALL only |
246 | 0 | addLoader("LXCJ7MRU"); |
247 | 0 | } |
248 | 0 | addLoader("LXCJ8MRU"); |
249 | 0 | } |
250 | 0 | } |
251 | 0 | addLoader("LXUNF034"); |
252 | 0 | if (n_mru) { |
253 | 0 | addLoader("LXMRU055"); |
254 | 0 | if (256 == n_mru) { |
255 | 0 | addLoader("MRUBYTE2"); |
256 | 0 | } else if (mrupwr2) { |
257 | 0 | addLoader("MRUBITS2"); |
258 | 0 | } else { |
259 | 0 | addLoader("MRUARB20"); |
260 | 0 | } |
261 | 0 | addLoader("LXMRU057"); |
262 | 0 | } |
263 | 0 | } |
264 | 0 | } |
265 | | |
266 | | #undef NOFILT |
267 | | #undef FNOMRU |
268 | | #undef MRUFLT |
269 | | |
270 | | /************************************************************************* |
271 | | // |
272 | | **************************************************************************/ |
273 | | |
274 | 0 | void Packer::defineFilterSymbols(const Filter *ft) { |
275 | 0 | if (ft->id == 0) { |
276 | 0 | linker->defineSymbol("filter_length", 0); |
277 | 0 | linker->defineSymbol("filter_cto", 0); |
278 | 0 | return; |
279 | 0 | } |
280 | 0 | assert(ft->calls > 0); |
281 | 0 | assert(ft->buf_len > 0); |
282 | | |
283 | 0 | if (ft->id >= 0x40 && ft->id <= 0x4f) { |
284 | 0 | linker->defineSymbol("filter_length", ft->buf_len); |
285 | 0 | linker->defineSymbol("filter_cto", ft->cto); |
286 | 0 | } else if (ft->id >= 0x50 && ft->id <= 0x5f) { |
287 | 0 | linker->defineSymbol("filter_id", ft->id); |
288 | 0 | linker->defineSymbol("filter_cto", ft->cto); |
289 | 0 | } else if ((ft->id & 0xf) % 3 == 0) { |
290 | 0 | linker->defineSymbol("filter_length", ft->calls); |
291 | 0 | linker->defineSymbol("filter_cto", ft->cto); |
292 | 0 | } else { |
293 | 0 | linker->defineSymbol("filter_length", ft->lastcall - ft->calls * 4); |
294 | 0 | linker->defineSymbol("filter_cto", ft->cto); |
295 | 0 | } |
296 | |
|
297 | | #if 0 |
298 | | if (0x80 == (ft->id & 0xF0)) { |
299 | | const int mru = ph.n_mru ? 1 + ph.n_mru : 0; |
300 | | if (mru && mru != 256) { |
301 | | const unsigned is_pwr2 = (0 == ((mru - 1) & mru)); |
302 | | // patch_le32(0x80 + (char *) loader, lsize - 0x80, "NMRU", mru - is_pwr2); |
303 | | } |
304 | | } |
305 | | #endif |
306 | 0 | } |
307 | | |
308 | | /* vim:set ts=4 sw=4 et: */ |