Coverage Report

Created: 2026-06-13 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */