/*
;  i386-linux.elf.execve-entry.S -- Linux program entry point & decompressor (kernel exec)
;
;  This file is part of the UPX executable compressor.
;
;  Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
;  Copyright (C) 1996-2025 Laszlo Molnar
;  Copyright (C) 2000-2025 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/i386/macros.S"


/*************************************************************************
// program entry point
// see glibc/sysdeps/i386/elf/start.S
**************************************************************************/

section LEXEC000
_start: .globl _start
////    int3
/*
;; How to debug this code:  Uncomment the 'int3' breakpoint instruction above.
;; Build the stubs and upx.  Compress a testcase, such as a copy of /bin/date.
;; Invoke gdb, and give a 'run' command.  Define a single-step macro such as
;;      define g
;;      stepi
;;      x/i $pc
;;      end
;; and a step-over macro such as
;;      define h
;;      x/2i $pc
;;      tbreak *$_
;;      continue
;;      x/i $pc
;;      end
;; Step through the code; remember that <Enter> repeats the previous command.
;;
*/

#if 0
                // personality(PER_LINUX)
                mov     eax, 136            // syscall_personality
                xor     ebx, ebx            // PER_LINUX
                int     0x80
#endif

        call main  // push address of decompress subroutine
decompress:

// /*************************************************************************
// // C callable decompressor
// **************************************************************************/

// /* Offsets to parameters, allowing for {push + pusha + call} */
#define         O_INP   (4+ 8*4 +1*4)
#define         O_INS   (4+ 8*4 +2*4)
#define         O_OUTP  (4+ 8*4 +3*4)
#define         O_OUTS  (4+ 8*4 +4*4)
#define         O_PARAM (4+ 8*4 +5*4)

#define         INP     dword ptr [esp+O_INP]
#define         INS     dword ptr [esp+O_INS]
#define         OUTP    dword ptr [esp+O_OUTP]
#define         OUTS    dword ptr [esp+O_OUTS]
#define         PARM    dword ptr [esp+O_PARAM]

section LEXEC009
                mov     eax, offset NMRU  // free slot in following 'pusha'
section LEXEC010
                pusha
                .byte   0x6a, filter_cto  // push byte
                // cld

                mov     esi, INP
                mov     edi, OUTP

                or      ebp, -1
//              align   8

#include      "arch/i386/nrv2b_d32.S"
#include      "arch/i386/nrv2d_d32.S"
#include      "arch/i386/nrv2e_d32.S"
#include      "arch/i386/lzma-multi_d.S"

section LEXEC015
                // eax is 0 from decompressor code
                //xor     eax, eax               ; return code

// check compressed size
                mov     edx, INP
                add     edx, INS
                cmp     edx, esi
                jz      .ok
                dec     eax
.ok:
                xchg [8*4 + esp], eax  // store success/failure, fetch NMRU

// write back the uncompressed size, and prepare for unfilter
                mov edx, OUTS
                mov ecx, edi
                mov edi, OUTP
                sub ecx, edi  // ecx= uncompressed size
                mov [edx], ecx

                pop edx  // cto8

section LEXEC110  // Jcc and/or possible n_mru
                push edi  // addvalue
                push 0x0f
                pop ebx
                mov bh, dl  // ebx= 0,,cto8,0x0F

section LEXEC100  // 0!=n_mru
                xchg eax, ebx  // eax= ct08_0f; ebx= n_mru {or n_mru1}

section LEXEC016  // bug in APP: jmp and target must be in same .asx
//;              jmpn lxunf0  ; logically belongs here

                ctojr32
                ctok32  edi, dl
                cit32   edi
section LEXEC017
                popa
                ret

section LEXEC020

main:
        pop ebp  // &decompress
        mov ebx, 0x401000  // &Elf32_Ehdr of this program
//; fall into fold_begin

eof:

/* vim:set ts=8 sw=8 et: */
