mirror of
https://github.com/upx/upx
synced 2025-10-05 19:20:23 +08:00
mmap() needs in-range fd; b_method as arg5 to decompress
l_lx_elfppc32.S l_lx_elfppc32.h ppc_d_nrv2e.S ppc_d_nrv2b.S committer: jreiser <jreiser> 1109217478 +0000
This commit is contained in:
parent
615615b1df
commit
f86d57bfe3
|
@ -39,6 +39,7 @@ _start: .globl _start
|
|||
sz_b_info= 12
|
||||
sz_unc= 0
|
||||
sz_cpr= 4
|
||||
b_method= 8
|
||||
|
||||
PROT_READ= 1
|
||||
PROT_WRITE= 2
|
||||
|
@ -57,36 +58,34 @@ PAGE_SIZE = -(~0<<PAGE_SHIFT)
|
|||
unfold:
|
||||
mflr r30 # &{ b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...}
|
||||
|
||||
/* linux ignores fd and off_t when MAP_ANONYMOUS
|
||||
li a5,0 # off_t
|
||||
li a4,-1 # BSD fd
|
||||
*/
|
||||
li a3,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS
|
||||
li a4,0 # fd; ignored, but must be in range?
|
||||
lwz a0,sz_cpr(r30)
|
||||
li a3,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS
|
||||
li a2,PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
add a0,a0,r30
|
||||
li a1,PAGE_SIZE
|
||||
addi a0,a0,sz_b_info+PAGE_SIZE-1
|
||||
add a0,a0,r30
|
||||
li 0,SYS_mmap
|
||||
addi a0,a0,sz_b_info+PAGE_SIZE-1
|
||||
rlwinm a0,a0,0,0,31-PAGE_SHIFT # next page boundary after fold
|
||||
sc
|
||||
bso- fail # Branch if SummaryOverflow (syscall failure), unlikely
|
||||
|
||||
mtlr a0 # &continuation
|
||||
bns+ 0f; trap # Branch if NoSummary[Overflow] (no failure)
|
||||
0:
|
||||
mtctr r31
|
||||
lbz meth,b_method(r30)
|
||||
la ldst,31*4(sp) # &do_not_care
|
||||
mr dst,a0
|
||||
mtctr r31
|
||||
mtlr a0 # &continuation
|
||||
lwz lsrc,sz_cpr(r30)
|
||||
addi src,r30,sz_b_info
|
||||
bctr # goto decomrpess; return to link register (mmap'ed page)
|
||||
fail:
|
||||
trap
|
||||
|
||||
main:
|
||||
stwu r1,-32*4(sp) # allocate space (keeping 0 mod 16), save r1
|
||||
stmw r2,4(sp) # save registers r2 thru r31
|
||||
mflr r31 # &decompress
|
||||
mflr r31 # &decompress
|
||||
call unfold
|
||||
/* { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...} */
|
||||
/* { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...} */
|
||||
|
||||
eof:
|
||||
/*__XTHEENDX__*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* l_lx_elfppc32.h -- created from l_lx_elfppc32.bin, 448 (0x1c0) bytes
|
||||
/* l_lx_elfppc32.h -- created from l_lx_elfppc32.bin, 460 (0x1cc) bytes
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
|
@ -26,11 +26,11 @@
|
|||
*/
|
||||
|
||||
|
||||
#define LINUX_ELFPPC32_LOADER_ADLER32 0x337c930d
|
||||
#define LINUX_ELFPPC32_LOADER_CRC32 0xac495fea
|
||||
#define LINUX_ELFPPC32_LOADER_ADLER32 0xd58495f3
|
||||
#define LINUX_ELFPPC32_LOADER_CRC32 0x5b115466
|
||||
|
||||
unsigned char linux_elfppc32_loader[448] = {
|
||||
72, 0, 1,177,124, 0, 41,236,144,166, 0, 0,124,132, 26, 20, /* 0x 0 */
|
||||
unsigned char linux_elfppc32_loader[460] = {
|
||||
72, 0, 1,189,124, 0, 41,236,144,166, 0, 0,124,132, 26, 20, /* 0x 0 */
|
||||
60, 0,128, 0, 61, 32,128, 0, 56, 99,255,255, 56,165,255,255, /* 0x 10 */
|
||||
57, 64,255,255,125,168, 2,166, 72, 0, 1, 12, 57, 32, 0, 1, /* 0x 20 */
|
||||
125, 41, 28, 44, 56, 99, 0, 4,124, 9, 0, 64,125, 41, 72, 20, /* 0x 30 */
|
||||
|
@ -52,10 +52,11 @@ unsigned char linux_elfppc32_loader[448] = {
|
|||
66, 0,255,248, 56,224, 1, 0,124, 7, 41,236,124, 7, 26, 44, /* 0x 130 */
|
||||
75,255,255, 16,128, 6, 0, 0,125,168, 3,166, 56,165, 0, 1, /* 0x 140 */
|
||||
56, 99, 0, 1,124,160, 40, 80,124,100, 24, 80,144,166, 0, 0, /* 0x 150 */
|
||||
78,128, 0, 32,127,200, 2,166, 56,192, 0, 50,128,126, 0, 4, /* 0x 160 */
|
||||
56,160, 0, 7,124, 99,242, 20, 56,128, 16, 0, 56, 99, 16, 11, /* 0x 170 */
|
||||
56, 0, 0, 90, 84, 99, 0, 38, 68, 0, 0, 2, 65,131, 0, 32, /* 0x 180 */
|
||||
124,104, 3,166, 56,193, 0,124,124,101, 27,120,127,233, 3,166, /* 0x 190 */
|
||||
128,158, 0, 4, 56,126, 0, 12, 78,128, 4, 32,127,224, 0, 8, /* 0x 1a0 */
|
||||
148, 33,255,128,188, 65, 0, 4,127,232, 2,166, 75,255,255,169 /* 0x 1b0 */
|
||||
78,128, 0, 32,127,200, 2,166, 57, 0, 0, 0, 56,224, 0, 0, /* 0x 160 */
|
||||
128,126, 0, 4, 56,192, 0, 50, 56,160, 0, 7, 56,128, 16, 0, /* 0x 170 */
|
||||
124, 99,242, 20, 56, 0, 0, 90, 56, 99, 16, 11, 84, 99, 0, 38, /* 0x 180 */
|
||||
68, 0, 0, 2, 64,163, 0, 8,127,224, 0, 8,127,233, 3,166, /* 0x 190 */
|
||||
136,254, 0, 8, 56,193, 0,124,124,101, 27,120,124,104, 3,166, /* 0x 1a0 */
|
||||
128,158, 0, 4, 56,126, 0, 12, 78,128, 4, 32,148, 33,255,128, /* 0x 1b0 */
|
||||
188, 65, 0, 4,127,232, 2,166, 75,255,255,157 /* 0x 1c0 */
|
||||
};
|
||||
|
|
171
src/stub/ppc_d_nrv2b.S
Normal file
171
src/stub/ppc_d_nrv2b.S
Normal file
|
@ -0,0 +1,171 @@
|
|||
/* ppc_d_nrv2b.S -- PowerPC decompressor for NRV2B
|
||||
|
||||
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) 2000-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
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#include "ppc_regs.h"
|
||||
|
||||
SZ_DLINE=128 # size of data cache line in Apple G5
|
||||
|
||||
/* Returns 0 on success; non-zero on failure. */
|
||||
decompress: # (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst, uint method)
|
||||
|
||||
/* PowerPC has no 'cmplis': compare logical [unsigned] immediate shifted [by 16] */
|
||||
#define hibit r0 /* holds 0x80000000 during decompress */
|
||||
|
||||
#define src a0
|
||||
#define lsrc a1
|
||||
#define dst a2
|
||||
#define ldst a3 /* Out: actually a reference: &len_dst */
|
||||
#define meth a4
|
||||
|
||||
#define off a4
|
||||
#define len a5
|
||||
#define bits a6
|
||||
#define disp a7
|
||||
|
||||
dcbtst 0,dst # prime dcache for store
|
||||
|
||||
stw dst,0(ldst) # original dst
|
||||
add lsrc,lsrc,src # input eof
|
||||
|
||||
lis hibit,0x8000 # 0x80000000 for detecting next bit
|
||||
lis bits,0x8000 # prepare for first load
|
||||
addi src,src,-1 # prepare for 'lbzu'
|
||||
addi dst,dst,-1 # prepare for 'stbu'
|
||||
li disp,-1 # initial displacement
|
||||
|
||||
mflr t3 # return address
|
||||
b bot_n2b
|
||||
|
||||
/* jump on next bit, with branch prediction: y==>likely; n==>unlikely
|
||||
cr0 is set by the cmpl ["compare logical"==>unsigned]:
|
||||
lt next bit is 0
|
||||
gt next bit is 1
|
||||
eq must load next 32 bits from memory
|
||||
*/
|
||||
#define jnextb0y call get1; blt+ cr0,
|
||||
#define jnextb0n call get1; blt- cr0,
|
||||
#define jnextb1y call get1; bgt+ cr0,
|
||||
#define jnextb1n call get1; bgt- cr0,
|
||||
|
||||
/* rotate next bit into bottom bit of reg; set cr0 based on entire result reg */
|
||||
#define getnextb(reg) call get1; adde. reg,reg,reg
|
||||
|
||||
get1:
|
||||
cmpl cr0,bits,hibit # cr0 for jnextb
|
||||
addc bits,bits,bits # CArry for getnextb
|
||||
bnelr+ cr0 # return if reload not needed; likely 31/32
|
||||
|
||||
/* CArry has been set from adding 0x80000000 to itself; preserve for 'adde' */
|
||||
# fetch 4 bytes unaligned and LITTLE ENDIAN
|
||||
#if 0 /*{ clean; but 4 instr larger, and 3 cycles longer */
|
||||
lbz bits,1(src) # lo8
|
||||
lbz t0,2(src); rlwimi bits,t0, 8,16,23
|
||||
lbz t0,3(src); rlwimi bits,t0,16, 8,15
|
||||
lbzu t0,4(src); rlwimi bits,t0,24, 0, 7
|
||||
#else /*}{ pray for no unalignment trap or slowdown */
|
||||
li bits,1 # compensate for 'lbzu'
|
||||
lwbrx bits,bits,src # bits= fetch_le32(bits+src)
|
||||
addi src,src,4
|
||||
#endif /*}*/
|
||||
|
||||
cmpl cr0,bits,hibit # cr0 for jnextb
|
||||
adde bits,bits,bits # CArry for getnextb; set lo bit from CarryIn
|
||||
ret
|
||||
|
||||
lit_n2b:
|
||||
#define tmp len
|
||||
lbzu tmp,1(src) # tmp= *++src;
|
||||
stbu tmp,1(dst) # *++dst= tmp;
|
||||
#undef tmp
|
||||
top_n2b:
|
||||
jnextb1y lit_n2b
|
||||
li off,1 # "the msb"
|
||||
offmore_n2b:
|
||||
getnextb(off)
|
||||
jnextb0n offmore_n2b
|
||||
|
||||
addic. off,off,-3 # CArry set [and ignored], but no 'addi.'
|
||||
li len,0
|
||||
blt- offprev_n2b
|
||||
lbzu t0,1(src)
|
||||
rlwinm off,off,8,0,31-8 # off<<=8;
|
||||
nor. disp,off,t0 # disp = -(1+ (off|t0));
|
||||
beq- eof_n2b
|
||||
|
||||
offprev_n2b: # In: 0==len
|
||||
getnextb(len); getnextb(len) # two bits; cr0 set on result
|
||||
li off,1; bne- gotlen_n2b # raw 1,2,3 ==> 2,3,4
|
||||
li off,3 # raw 2.. ==> 5..
|
||||
li len,1 # "the msb"
|
||||
lenmore_n2b:
|
||||
getnextb(len)
|
||||
jnextb0n lenmore_n2b
|
||||
gotlen_n2b:
|
||||
subfic t0,disp,(~0)+(-0xd00) # want CArry only
|
||||
adde len,len,off # len += off + (disp < -0xd00);
|
||||
|
||||
copy:
|
||||
#define back off
|
||||
add back,disp,dst # point back to match in dst
|
||||
mtctr len
|
||||
short_n2b:
|
||||
#define tmp len
|
||||
lbzu tmp,1(back)
|
||||
stbu tmp,1(dst)
|
||||
#undef tmp
|
||||
bdnz+ short_n2b
|
||||
|
||||
/* This "prefetch for store" is simple, small, and effective. Matches
|
||||
usually occur more frequently than once per 128 bytes, but G4 line size
|
||||
is only 32 bytes anyway. Assume that an 'unnecessary' dcbtst costs only
|
||||
about as much as a hit. The counter register is free at top_n2b, so we could
|
||||
pace the dcbtst optimally; but that takes 7 or 8 instructions of space.
|
||||
*/
|
||||
bot_n2b:
|
||||
li back,2*SZ_DLINE
|
||||
dcbtst back,dst # 2 lines ahead [-1 for stbu]
|
||||
dcbt back,src # jump start auto prefetch at page boundary
|
||||
/* Auto prefetch for Read quits at page boundary; needs 2 misses to restart. */
|
||||
#undef back
|
||||
b top_n2b
|
||||
|
||||
eof_n2b:
|
||||
#define tmp r0 /* hibit is dead */
|
||||
lwz tmp,0(ldst) # original dst
|
||||
mtlr t3 # return address
|
||||
addi dst,dst,1 # uncorrect for 'stbu'
|
||||
addi src,src,1 # uncorrect for 'lbzu'
|
||||
subf dst,tmp,dst # dst -= tmp; // dst length
|
||||
#undef tmp
|
||||
subf a0,lsrc,src # src -= eof; // return 0: good; else: bad
|
||||
stw dst,0(ldst)
|
||||
ret
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
SZ_DLINE=128 # size of data cache line in Apple G5
|
||||
|
||||
/* Returns 0 on success; non-zero on failure. */
|
||||
decompress: # (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst)
|
||||
decompress: # (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst, uint method)
|
||||
|
||||
/* PowerPC has no 'cmplis': compare logical [unsigned] immediate shifted [by 16] */
|
||||
#define hibit r0 /* holds 0x80000000 during decompress */
|
||||
|
@ -43,6 +43,7 @@ decompress: # (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst)
|
|||
#define lsrc a1
|
||||
#define dst a2
|
||||
#define ldst a3 /* Out: actually a reference: &len_dst */
|
||||
#define meth a4
|
||||
|
||||
#define off a4
|
||||
#define len a5
|
||||
|
|
Loading…
Reference in New Issue
Block a user