Files
upx/src/stub/src/i386-expand.S
T
John Reiser cc87a2c867 ELF2 for mips 32-bit main programs
modified:   ../misc/testsuite/upx_testsuite_1-expected_sha256sums.sh
	modified:   stub/src/include/linux.h
	modified:   p_lx_elf.cpp
	modified:   stub/Makefile
	modified:   stub/src/arch/mips/r3000/lzma_d.S
	modified:   stub/src/arch/mips/r3000/macros.ash
	modified:   stub/src/arm.v4a-linux.elf-fold.S
	modified:   stub/src/arm.v4a-linux.elf-main2.c
	modified:   stub/src/arm.v4a-linux.elf-so_fold.lds
	modified:   stub/src/arm.v5a-linux.elf-so_fold.lds
	modified:   stub/src/arm64-linux.elf-so_fold.lds
	modified:   stub/src/i386-expand.S
	modified:   stub/src/i386-linux.elf-entry.lds
	modified:   stub/src/i386-linux.elf-main2.c
	modified:   stub/src/i386-linux.elf-so_fold.lds
	new file:   stub/src/mips.r3000-expand.S
	new file:   stub/src/mips.r3000-linux.elf-entry.lds
	modified:   stub/src/mips.r3000-linux.elf-fold.S
	modified:   stub/src/mips.r3000-linux.elf-fold.lds
	new file:   stub/src/mips.r3000-linux.elf-main2.c
	new file:   stub/src/mipsel.r3000-expand.S
	modified:   stub/src/mipsel.r3000-linux.elf-entry.S
	new file:   stub/src/mipsel.r3000-linux.elf-entry.lds
	modified:   stub/src/mipsel.r3000-linux.elf-fold.S
	modified:   stub/src/mipsel.r3000-linux.elf-fold.lds
	new file:   stub/src/mipsel.r3000-linux.elf-main2.c
	modified:   stub/src/mipsel.r3000-linux.shlib-init.S
	modified:   stub/src/powerpc-linux.elf-fold.lds
	modified:   stub/src/upxfd_android.c
           plus generated *.h *.map *.dump
2024-08-25 15:16:29 -07:00

209 lines
6.5 KiB
ArmAsm

/*
; i386-expand.S -- decompressors for i386
;
; This file is part of the UPX executable compressor.
;
; Copyright (C) 1996-2021 Markus Franz Xaver Johannes Oberhumer
; Copyright (C) 1996-2021 Laszlo Molnar
; Copyright (C) 2000-2021 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>
;
*/
#define section .section
NBPW= 4
/* AMD64 branch prediction is much worse if there are more than 3 branches
per 16-byte block. The jnextb would suffer unless inlined. getnextb is OK
using closed subroutine to save space, and should be OK on cycles because
CALL+RET should be predicted. getnextb could partially expand, using closed
subroutine only for refill.
*/
/* jump on next bit {0,1} with prediction {y==>likely, n==>unlikely} */
/* Prediction omitted for now. */
/* On refill: prefetch next byte, for latency reduction on literals and offsets. */
#define jnextb0np jnextb0yp
#define jnextb0yp GETBITp; jnc
#define jnextb1np jnextb1yp
#define jnextb1yp GETBITp; jc
#define GETBITp \
addl bits,bits; jnz 0f; \
movl (%esi),bits; sub $-4,%esi; \
adcl bits,bits; movb (%esi),%dl; \
0:
/* Same, but without prefetch (not useful for length of match.) */
#define jnextb0n jnextb0y
#define jnextb0y GETBIT; jnc
#define jnextb1n jnextb1y
#define jnextb1y GETBIT; jc
#define GETBIT \
addl bits,bits; jnz 0f; \
movl (%esi),bits; sub $-4,%esi; \
adcl bits,bits; \
0:
/* rotate next bit into bottom bit of reg */
#define getnextbp(reg) GETBITp; adcl reg,reg
#define getnextb(reg) getnextbp(reg)
sz_unc= 0*4 // offsets in struct b_info
sz_cpr= 1*4
method= 2*4
sz_binfo= 3*4
section EXP_HEAD
f_unfilter: // (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);
#include "arch/i386/bxx.S"
// int f_expand(nrv_byte const *src, nrv_byte *dst, size_t *dstlen) // C-callable
// Includes unfilter and cache flush.
// Returns 0 on success.
// *dstlen returns actual length
// *src includes 3-word b_info (sz_unc, sz_cpr, {method, filter, cto8, extra})
// src might not be 4-byte aligned.
// C-callable, so must save+restore %ebx,%esi,%edi,%ebp
/* Working registers for NRV2B/NRV2D/NRV2E (i386) */
#define off %eax /* XXX: 2GB */
#define len %ecx /* XXX: 2GB */
#define lenq %ecx
#define bits %ebx
#define src %esi
#define dst %edi
#define disp %ebp
#define displ %ebp
#define dispq %ebp
f_expand: .globl f_expand // start of code for actual de-compressor
push %ebp; mov %esp,%ebp
push %edi; push %esi; push %ebx // MATCH_29
#define fx_src 2*NBPW(%ebp)
#define fx_dst 3*NBPW(%ebp)
#define fx_dstlen 4*NBPW(%ebp)
call decompress
push %eax // MATCH_30 result of decompression: 0=>success
mov fx_src,src
movzbl 1+ method(src),%eax; test %eax,%eax; je no_unf; push %eax // ftid
movzbl 2+ method(src),%eax; push %eax // cto8
push /*sz_unc*/(src)
push fx_dst
call f_unfilter; add $4*NBPW,%esp
no_unf:
pop %eax // MATCH_30
pop %ebx; pop %esi; pop %edi; pop %ebp // MATCH_29
ret
__clear_cache: .globl __clear_cache
int3 // __clear_cache
ret
// common subroutines for NRV2B,NRV2D,NRV2E
refill:
movl (%esi),bits; sub $-4,%esi // next 32 bits; set Carry
adcl bits,bits // LSB= 1 (CarryIn); CarryOut= next bit
movb (%esi),%dl // pre-fetch: literal, or bottom 8 bits of offset
rep; ret
getbit:
addl bits,bits; jz refill // Carry= next bit
rep; ret
copy: // In: len, %edi, dispq; Out: 0==len, %edi, dispq; trashes %eax, %edx
lea (%edi,dispq),%eax; cmpl $5,len // <=3 is forced
movb (%eax),%dl; jbe copy1 // <=5 for better branch predict
cmpl $-4,displ; ja copy1 // 4-byte chunks would overlap
subl $4,len // adjust for termination cases
copy4:
movl (%eax),%edx; add $4, %eax; subl $4,len
movl %edx,(%edi); lea 4(%edi),%edi; jnc copy4
addl $4,len; movb (%eax),%dl; jz copy0
copy1:
inc %eax; movb %dl,(%edi); dec len
movb (%eax),%dl
lea 1(%edi),%edi; jnz copy1
copy0:
rep; ret
decompress: // sections NRV2B, etc, are inserted here
mov fx_src,src
mov fx_dst,dst
lodsl // %eax= sz_unc; [lodsl ==> %eax= *src++;]
mov fx_dstlen,%edx; mov %eax,(%edx); push %edx // MATCH_51 *eof_dst = dstlen
lodsl; xchg %eax,%ecx // %ecx= sz_cpr(src)
lodsl; movzbl %al,%edx // method
add src,%ecx; push %ecx // MATCH_52 eof_src
push dst // MATCH_53 dst_orig
push %ebp // MATCH_54 sanity
// initialize NRV2 working registers
xor bits,bits // empty; force refill
xor len,len // create loop invariant
or $(~0),disp // -1: initial displacement
cld
movzbl -NBPW(src),%edx // method
#define methb %dl
section EXP_TAIL
eof: // decompressors jump here when done
pop %ebp // MATCH_54
pop %eax // MATCH_53 dst_orig
sub %eax,%edi // dst -= original dst
pop %eax // MATCH_52 src_EOF
pop %ecx // MATCH_51 &dstlen
movl %edi,(%ecx) // actual length used at dst XXX: 4GB
sub %esi,%eax // src -= eof; // return 0: good; else: bad
ret // back into f_expand, with sane %ebp
#define M_NRV2B_LE32 2
#define M_NRV2D_LE32 5
#define M_NRV2E_LE32 8
#define M_CL1B_LE32 11
#define M_LZMA 14
section NRV2E
#include "arch/i386/nrv2e_d32-easy.S"
section NRV2D
#include "arch/i386/nrv2d_d32-easy.S"
section NRV2B
#include "arch/i386/nrv2b_d32-easy.S"
#undef off
#undef len
#undef bits
#undef displ
#undef dispq
#undef src
#undef dst
#undef meth
// lzma code is written in intel syntax!
///* lzma has its own 'section's */
.intel_syntax noprefix
#include "arch/i386/lzma_d.S"