1 /* ppcbxx.h -- PowerPC Branch trick
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    Copyright (C) 2004-2020 John F. Reiser
8    All Rights Reserved.
9 
10    UPX and the UCL library are free software; you can redistribute them
11    and/or modify them under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; see the file COPYING.
22    If not, write to the Free Software Foundation, Inc.,
23    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25    Markus F.X.J. Oberhumer              Laszlo Molnar
26    <markus@oberhumer.com>               <ezerotven+github@gmail.com>
27 
28    John F. Reiser
29    <jreiser@users.sourceforge.net>
30  */
31 
32 
33 
34 /*************************************************************************
35 // filter / scan
36 **************************************************************************/
37 
38 #define W_CTO 4  /* width of cto; must match stub/ppc_bxx.S */
39 
F(Filter * f)40 static int F(Filter *f)
41 {
42 #ifdef U
43     // filter
44     upx_byte *b = f->buf;
45     const unsigned addvalue = f->addvalue;
46 #else
47     // scan
48     const upx_byte *b = f->buf;
49 #endif
50     const unsigned size  = umin(f->buf_len, 0u - (~0u<<(32 - (6+ W_CTO))));
51     const unsigned size4 = size -4;
52 
53     unsigned ic;
54     unsigned calls = 0, noncalls = 0;
55     unsigned lastnoncall = size, lastcall = 0;
56 
57     // find 26-2-W_CTO bits of displacements that contain no targets
58     {
59         unsigned char buf[256];
60         unsigned short wbuf[256];
61         const size_t WW = (size_t)0 - ((~(size_t)0) << W_CTO); // ???
62         memset(wbuf, 0, sizeof(wbuf));
63         memset(buf     , 0,       WW);
64         memset(buf + WW, 1, 256 - WW);
65 
66         for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
67             unsigned const off = (int)(get_be32(b+ic)<<6) >>6;
68             if (size <= (off & (~0u<<2))+ic) {
69                 buf[(~(~0u<<W_CTO)) & (off>>(26 - W_CTO))] |= 1;
70                 ++wbuf[0xff&(off>>18)];
71             }
72         }
73 
74         if (getcto(f, buf) < 0) {
75 #if (W_CTO != 0)
76             return -1;
77 #else
78             f->cto = 0;
79 #endif
80         }
81     }
82     const unsigned char cto8 = f->cto;
83 #ifdef U
84     const unsigned cto = (unsigned)f->cto << (24+2 - W_CTO);
85 #endif
86 
87     for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
88         unsigned const word = get_be32(b+ic);
89         unsigned const off = (int)(word<<6) >>6;
90         unsigned const jc = (off & (~0u<<2))+ic;
91         // try to detect 'real' calls only
92         if (jc < size) {
93 #ifdef U
94             set_be32(b+ic,(0xfc000003&word) | (jc+addvalue+cto));
95 #endif
96             calls++;
97             lastcall = ic;
98         }
99         else {
100 #if (W_CTO != 0)
101             assert((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) != (unsigned) cto8);  // this should not happen
102 #endif
103             lastnoncall = ic;
104             noncalls++;
105         }
106     }
107 
108     f->calls = calls;
109     f->noncalls = noncalls;
110     f->lastcall = lastcall;
111     ACC_UNUSED(lastnoncall);
112 
113 #if 0 || defined(TESTING)
114     printf("\ncalls=%d noncalls=%d text_size=%x calltrickoffset=%x\n",
115         calls,noncalls,size,cto8);
116 #endif
117     return 0;
118 }
119 
120 
121 /*************************************************************************
122 // unfilter
123 **************************************************************************/
124 
125 #ifdef U
U(Filter * f)126 static int U(Filter *f)
127 {
128     upx_byte *b = f->buf;
129     const unsigned size4 = umin(f->buf_len - 4, 0u - (~0u<<(32 - (6+ W_CTO))));
130     const unsigned addvalue = f->addvalue;
131 
132     unsigned ic;
133 
134    for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
135         unsigned const word = get_be32(b+ic);
136         if ((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) == (unsigned) f->cto) {
137             unsigned const jc = word & (~(~0u<<(26 - W_CTO)) & (~0u<<2));
138             set_be32(b+ic, (0xfc000003&word)|(0x03fffffc&(jc-ic-addvalue)));
139             f->calls++;
140             f->lastcall = ic;
141         }
142         else {
143             f->noncalls++;
144         }
145     }
146     return 0;
147 }
148 #endif
149 
150 
151 #undef F
152 #undef U
153 
154 #undef W_CTO
155 
156 /* vim:set ts=4 sw=4 et: */
157