9b86e68268
Powerpc: ppc64le processor - Fix nrv2x-d.S compression routines xstrip - disallow assert at line 178 Signed-off-by: Thierry Fauck <tfauck@free.fr> modified: powerpc-darwin.dylib-entry.h modified: powerpc-darwin.macho-entry.h modified: powerpc-darwin.macho-fold.h modified: powerpc-linux.elf-entry.h modified: powerpc-linux.elf-fold.h modified: powerpc-linux.kernel.vmlinux.h modified: powerpc64le-darwin.dylib-entry.h modified: powerpc64le-darwin.macho-entry.h modified: powerpc64le-darwin.macho-fold.h modified: powerpc64le-linux.elf-entry.h modified: powerpc64le-linux.elf-fold.h modified: powerpc64le-linux.kernel.vmlinux.h modified: scripts/xstrip.py modified: src/arch/powerpc/64le/nrv2b_d.S modified: src/arch/powerpc/64le/nrv2d_d.S modified: src/arch/powerpc/64le/nrv2e_d.S modified: src/powerpc-linux.elf-entry.S modified: src/powerpc-linux.elf-fold.S modified: src/powerpc-linux.elf-main.c modified: tmp/powerpc-linux.elf-entry.bin.dump modified: tmp/powerpc64le-darwin.dylib-entry.bin.dump modified: tmp/powerpc64le-darwin.macho-entry.bin.dump modified: tmp/powerpc64le-linux.elf-entry.bin.dump modified: tmp/powerpc64le-linux.kernel.vmlinux.bin.dump
251 lines
7.9 KiB
ArmAsm
251 lines
7.9 KiB
ArmAsm
/* powerpc-linux.elf-entry.S -- Linux program entry point & decompressor (Elf binary)
|
|
*
|
|
* This file is part of the UPX executable compressor.
|
|
*
|
|
* Copyright (C) 1996-2016 Markus Franz Xaver Johannes Oberhumer
|
|
* Copyright (C) 1996-2016 Laszlo Molnar
|
|
* Copyright (C) 2000-2016 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
|
|
* <markus@oberhumer.com> <ezerotven+github@gmail.com>
|
|
*
|
|
* John F. Reiser
|
|
* <jreiser@users.sourceforge.net>
|
|
*/
|
|
|
|
#include "arch/powerpc/32/macros.S"
|
|
#include "arch/powerpc/32/ppc_regs.h"
|
|
|
|
sz_b_info= 12
|
|
sz_unc= 0
|
|
sz_cpr= 4
|
|
b_method= 8
|
|
|
|
PROT_READ= 1
|
|
PROT_WRITE= 2
|
|
PROT_EXEC= 4
|
|
|
|
MAP_PRIVATE= 2
|
|
MAP_FIXED= 0x10
|
|
MAP_ANONYMOUS= 0x20
|
|
|
|
PAGE_SHIFT= 12
|
|
PAGE_SIZE = -(~0<<PAGE_SHIFT)
|
|
PAGE_SHIFT64= 16
|
|
PAGE_SIZE64 = -(~0<<PAGE_SHIFT64)
|
|
|
|
|
|
/* /usr/include/asm-ppc/unistd.h */
|
|
__NR_write = 4
|
|
__NR_exit = 1
|
|
__NR_mmap = 90
|
|
__NR_munmap = 91
|
|
|
|
section ELFMAINX
|
|
_start: .globl _start
|
|
call main // must be exactly 1 instruction; link_register= &decompress
|
|
|
|
/* Returns 0 on success; non-zero on failure. */
|
|
decompress: // (uchar const *src, size_t lsrc, uchar *dst, size_t &ldst, uint method)
|
|
|
|
section NRV_HEAD
|
|
SZ_DLINE=128 # size of data cache line in Apple G5
|
|
|
|
/* 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
|
|
|
|
section NRV2E
|
|
#include "arch/powerpc/32/nrv2e_d.S"
|
|
|
|
section NRV2D
|
|
#include "arch/powerpc/32/nrv2d_d.S"
|
|
|
|
section NRV2B
|
|
#include "arch/powerpc/32/nrv2b_d.S"
|
|
|
|
#include "arch/powerpc/32/lzma_d.S"
|
|
|
|
section NRV_TAIL
|
|
eof_nrv:
|
|
#define dst0 a4
|
|
#define tmp a1
|
|
lwz dst0,0(ldst) // original dst
|
|
mtlr t3 // return address
|
|
subf a0,lsrc,src
|
|
subf tmp,dst0,dst // -1+ dst length
|
|
addi a0,a0,1 // return 0: good; else: bad [+1: correct for lbzu]
|
|
addi tmp,tmp,1 // dst length
|
|
stw tmp,0(ldst)
|
|
#undef tmp
|
|
|
|
// CACHELINE=32 is the observed minimum line size of any cache.
|
|
// Some caches may have larger lines, but it is cumbersome to lookup
|
|
// {AT_DCACHEBSIZE, AT_ICACHEBSIZE, AT_UCACHEBSIZE: /usr/include/elf.h},
|
|
// then save the correct size in a variable {where to put it?}, or to modify
|
|
// the two instructions here. If a cache has larger lines, then we expect
|
|
// that the second dcbst (or icbi) on a the same line will be fast.
|
|
// If not, then too bad.
|
|
|
|
section CFLUSH // In: a2=dst= &highest stored byte; a4=dst0= &lowest stored byte
|
|
CACHELINE=32
|
|
ori dst0,dst0,-1+ CACHELINE // highest addr on cache line
|
|
cfl_nrv:
|
|
dcbst 0,dst0 // initiate store (modified) cacheline to memory
|
|
cmpl cr0,dst0,dst // did we cover the highest-addressed byte?
|
|
icbi 0,dst0 // discard instructions from cacheline
|
|
addi dst0,dst0,CACHELINE // highest addr on next line
|
|
blt cr0,cfl_nrv // not done yet
|
|
#undef dst0
|
|
sync // wait for all memory operations to finish
|
|
isync // discard prefetched instructions (if any)
|
|
cfl_ret:
|
|
ret
|
|
|
|
section ELFMAINY
|
|
msg_SELinux:
|
|
call L72
|
|
L70:
|
|
.asciz "PROT_EXEC|PROT_WRITE failed.\n"
|
|
L71:
|
|
// IDENTSTR goes here
|
|
|
|
section ELFMAINZ
|
|
L72:
|
|
li a2,L71 - L70 // length
|
|
mflr a1 // message text
|
|
li a0,2 // fd stderr
|
|
li 0,__NR_write; sc
|
|
die:
|
|
li a0,127
|
|
li 0,__NR_exit; sc
|
|
|
|
/* Decompress the rest of this loader, and jump to it. */
|
|
unfold:
|
|
mflr r30 // &{ b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...}
|
|
|
|
li a5,0 // off_t
|
|
li a4,-1 // fd; cater to *BSD for MAP_ANON
|
|
li a3,MAP_PRIVATE | MAP_ANONYMOUS
|
|
li a2,PROT_READ | PROT_WRITE
|
|
li a1,PAGE_SIZE
|
|
add a1,a1,a1 // allocate twice 4K
|
|
lwz a0,sz_cpr(r30)
|
|
add a0,a0,r30
|
|
addi a0,a0,sz_b_info+PAGE_SIZE-1
|
|
rlwinm a0,a0,0,0,31-PAGE_SHIFT // next page boundary after fold
|
|
mr 23,a1 // save PAGE_SIZE value
|
|
mr 14,a0 // save address being allocated
|
|
li 0,__NR_mmap
|
|
sc
|
|
cmp 0,0,a0,14
|
|
beq alloc4
|
|
b alloc64
|
|
/* try to allocate a 4k page - if failure then allocate 64k page */
|
|
alloc4:
|
|
/* deallocate stub allocation */
|
|
mr a1,23
|
|
li 0,__NR_munmap
|
|
sc
|
|
/* allocate 4k page */
|
|
li a5,0 // off_t
|
|
li a4,-1 // fd; cater to *BSD for MAP_ANON
|
|
li a3,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS
|
|
li a2,PROT_READ | PROT_WRITE | PROT_EXEC
|
|
li a1,PAGE_SIZE
|
|
lwz a0,sz_cpr(r30)
|
|
add a0,a0,r30
|
|
addi a0,a0,sz_b_info+PAGE_SIZE-1
|
|
rlwinm a0,a0,0,0,31-PAGE_SHIFT // next page boundary after fold
|
|
li 0,__NR_mmap
|
|
mr 23,a1 // save PAGE_SIZE value
|
|
mr 14,a0 // save address being allocated
|
|
sc
|
|
cmpi 0,0,a0,14 //
|
|
bne decomp
|
|
b msg_SELinux // Branch if SummaryOverflow (failure)
|
|
/* 64k page */
|
|
alloc64:
|
|
/* deallocate stub allocation */
|
|
mr a1,23
|
|
li 0,__NR_munmap
|
|
sc
|
|
/* allocate 64k page */
|
|
li a5,0 // off_t
|
|
li a4,-1 // fd; cater to *BSD for MAP_ANON
|
|
li a3,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS
|
|
li a2,PROT_READ | PROT_WRITE | PROT_EXEC
|
|
lis a1,1 // 64K
|
|
lwz a0,sz_cpr(r30)
|
|
add a0,a0,r30
|
|
addi a0,a0,sz_b_info-1
|
|
add a0,a0,a1
|
|
rlwinm a0,a0,0,0,31-PAGE_SHIFT64 // next page boundary after fold
|
|
li 0,__NR_mmap
|
|
mr 23,a1 // save PAGE_SIZE value
|
|
sc
|
|
cmpi 0,0,a0,22 // return code
|
|
beq msg_SELinux
|
|
decomp:
|
|
0:
|
|
mtctr r31
|
|
lwz r0,sz_unc(r30)
|
|
lbz meth,b_method(r30)
|
|
la ldst,31*4(sp) // &slot on stack
|
|
stw r0,31*4(sp) // lzma uses for EOF
|
|
stw 23,23*4(sp) // save pag shift value
|
|
mr dst,a0
|
|
mtlr a0 // &continuation
|
|
lwz lsrc,sz_cpr(r30)
|
|
addi src,r30,sz_b_info
|
|
la sp,-6*4(sp) // (sp,pc,cr, xx,yy,zz) save area per calling convention
|
|
bctr // goto decomrpess; return to link register (mmap'ed page)
|
|
|
|
// Example code at entrypoint of C-language subroutine:
|
|
// mflr r0 # r0= return address
|
|
// stwu sp,-96(sp) # allocate local frame; chain to previous frame
|
|
// stmw r14,24(sp) # save 18 regs r14,r15,...,r31; 4*18 == (96 - 24)
|
|
// stw r0,100(sp) # save return address into caller's frame (100 >= 96)
|
|
// Example code at exit:
|
|
// lwz r0,100(sp) # r0= return address
|
|
// lmw r14,24(sp) # restore 18 regs r14,r15,...,r31
|
|
// mtlr r0 # prepare for indirect jump
|
|
// addi sp,sp,96 # de-allocate local frame
|
|
// blr # goto return address
|
|
|
|
main:
|
|
//// teq r0,r0 // debugging
|
|
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
|
|
call unfold
|
|
/* { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...} */
|
|
|
|
/* vim:set ts=8 sw=8 et: */
|