From c9339741748dfc16825bc2e7bffb4d184d9e1512 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sun, 20 Feb 2005 01:31:03 +0000 Subject: [PATCH] branch trick for PowerPC32 committer: jreiser 1108863063 +0000 --- src/filter/ppcbxx.h | 153 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/filter/ppcbxx.h diff --git a/src/filter/ppcbxx.h b/src/filter/ppcbxx.h new file mode 100644 index 00000000..430c2669 --- /dev/null +++ b/src/filter/ppcbxx.h @@ -0,0 +1,153 @@ +/* ppcbxx.h -- PowerPC Branch trick + + This file is part of the UPX executable compressor. + + Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2004 Laszlo Molnar + Copyright (C) 2004-2005 John F. Reiser + All Rights Reserved. + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer Laszlo Molnar + + + John F. Reiser + + */ + + + +/************************************************************************* +// filter / scan +**************************************************************************/ + +#define W_CTO 4 /* width of cto; must match stub/ppc_bxx.S */ + +static int F(Filter *f) +{ +#ifdef U + // filter + upx_byte *b = f->buf; + const unsigned addvalue = f->addvalue; +#else + // scan + const upx_byte *b = f->buf; +#endif + const unsigned size = f->buf_len; + + unsigned ic; + unsigned calls = 0, noncalls = 0; + unsigned lastnoncall = size, lastcall = 0; + + // find 26-2-W_CTO bits of displacements that contain no targets + { + unsigned char buf[256]; + unsigned short wbuf[256]; + memset(wbuf, 0, sizeof(wbuf)); + memset(buf , 0, -(~0<>6; + if (size <= (off & (~0<<2))+ic) { + buf[(~(~0<>(26 - W_CTO))] |= 1; + ++wbuf[0xff&(off>>18)]; + } + } + + if (getcto(f, buf) < 0) { + if (0!=W_CTO) + return -1; + f->cto = 0; + } + } + const unsigned char cto8 = f->cto; +#ifdef U + const unsigned cto = (unsigned)f->cto << (24+2 - W_CTO); +#endif + + for (ic = 0; ic < size - 4; ic+=4) if (COND(b,ic)) { + unsigned const word = get_be32(b+ic); + unsigned const off = (int)(word<<6) >>6; + unsigned const jc = (off & (~0<<2))+ic; + // try to detect 'real' calls only + if (jc < size) { +#ifdef U + set_be32(b+ic,(0xfc000003&word) | (jc+addvalue+cto)); +#endif + calls++; + lastcall = ic; + } + else { + assert(0==W_CTO + || (~(~0<>(24+2 - W_CTO))) != cto8); // this should not happen + lastnoncall = ic; + noncalls++; + } + } + + f->calls = calls; + f->noncalls = noncalls; + f->lastcall = lastcall; + +#if 1 + printf("\ncalls=%d noncalls=%d text_size=%x calltrickoffset=%x\n", + calls,noncalls,size,cto8); +#endif + return 0; +} + + +/************************************************************************* +// unfilter +**************************************************************************/ + +#ifdef U +static int U(Filter *f) +{ + upx_byte *b = f->buf; + const unsigned size4 = f->buf_len - 4; + const unsigned addvalue = f->addvalue; + + unsigned ic; + + for (ic = 0; ic < size4; ic+=4) if (COND(b,ic)) { + unsigned const word = get_be32(b+ic); + if ((~(~0<>(24+2 - W_CTO))) == f->cto) { + unsigned const jc = word & (~(~0<<(26 - W_CTO)) & (~0<<2)); + set_be32(b+ic, (0xfc000003&word)|(0x03fffffc&(jc-ic-addvalue))); + f->calls++; + f->lastcall = ic; + } + else { + f->noncalls++; + } + } + return 0; +} +#endif + + +#undef F +#undef U + +#undef W_CTO + +/* +vi:ts=4:et:nowrap +*/ +