dos/djgpp2 using nrv2e converted to ElfLinker

This commit is contained in:
László Molnár 2006-07-01 17:29:41 +02:00
parent 5964a06386
commit f022c9d510
7 changed files with 1815 additions and 634 deletions

View File

@ -31,6 +31,7 @@
#include "filter.h"
#include "packer.h"
#include "p_djgpp2.h"
#include "linker.h"
static const
#include "stub/i386-dos32.djgpp2.h"
@ -82,6 +83,12 @@ unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf,
}
Linker* PackDjgpp2::newLinker() const
{
return new ElfLinkerX86;
}
int PackDjgpp2::buildLoader(const Filter *ft)
{
// prepare loader
@ -101,7 +108,7 @@ int PackDjgpp2::buildLoader(const Filter *ft)
addLoader("DJCALLT2", NULL);
addFilter32(ft->id);
}
addLoader("DJRETURN,+40DXXXX,UPX1HEAD", NULL);
addLoader("DJRETURN,+40C,UPX1HEAD", NULL);
freezeLoader();
return getLoaderSize();
}
@ -228,6 +235,29 @@ void PackDjgpp2::stripDebug()
}
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
{
if (ft->id == 0)
return false;
assert(ft->calls > 0);
linker->defineSymbol("filter_cto", ft->cto);
linker->defineSymbol("filter_length",
(ft->id & 0xf) % 3 == 0 ? ft->calls :
ft->lastcall - ft->calls * 4);
#if 0
if (0x80==(ft->id & 0xF0)) {
int const mru = ph.n_mru ? 1+ ph.n_mru : 0;
if (mru && mru!=256) {
unsigned const is_pwr2 = (0==((mru -1) & mru));
patch_le32(0x80 + (char *)loader, lsize - 0x80, "NMRU", mru - is_pwr2);
}
}
#endif
return true;
}
/*************************************************************************
//
**************************************************************************/
@ -300,6 +330,7 @@ void PackDjgpp2::pack(OutputFile *fo)
// patch coff header #2
const unsigned lsize = getLoaderSize();
assert(lsize % 4 == 0);
text->size = lsize; // new size of .text
data->size = ph.c_len; // new size of .data
@ -313,21 +344,14 @@ void PackDjgpp2::pack(OutputFile *fo)
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + ph.overlap_overhead - 0x200;
coff_hdr.f_nscns = 3;
// prepare loader
MemBuffer loader(lsize);
memcpy(loader, getLoader(), lsize);
// patch loader
patchPackHeader(loader, lsize);
patch_le32(loader, lsize, "ENTR", coff_hdr.a_entry);
patchFilter32(loader, lsize, &ft);
patch_le32(loader, lsize, "BSSL", ph.overlap_overhead / 4);
patchDecompressor(loader, lsize);
linker->defineSymbol("original_entry", coff_hdr.a_entry);
linker->defineSymbol("length_of_bss", ph.overlap_overhead / 4);
//patchDecompressor(loader, lsize); // FIXME
assert(bss->vaddr == ((size + 0x1ff) &~ 0x1ff) + (text->vaddr &~ 0x1ff));
if (ph.method == M_LZMA)
patch_le32(loader, lsize, "ESP0", bss->vaddr + bss->size);
patch_le32(loader, lsize, "OUTP", text->vaddr - hdrsize);
patch_le32(loader, lsize, "INPP", data->vaddr);
linker->defineSymbol("stack_for_lzma", bss->vaddr + bss->size);
linker->defineSymbol("start_of_uncompressed", text->vaddr - hdrsize);
linker->defineSymbol("start_of_compressed", data->vaddr);
defineFilterSymbols(linker, &ft);
// we should not overwrite our decompressor during unpacking
// the original coff header (which is put just before the
@ -344,6 +368,14 @@ void PackDjgpp2::pack(OutputFile *fo)
memcpy(obuf+data->size, "UPX", 3);
data->size = ALIGN_UP(data->size, 4);
linker->defineSymbol("DJ2MAIN1", coff_hdr.a_entry);
linker->relocate();
// prepare loader
MemBuffer loader(lsize);
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader, lsize);
// write coff header, loader and compressed file
fo->write(&coff_hdr, sizeof(coff_hdr));
fo->write(loader, lsize);

View File

@ -60,6 +60,7 @@ protected:
unsigned range = 0,
unsigned upper_limit = ~0u) const;
virtual int buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
long coff_offset;

View File

@ -313,9 +313,11 @@ i086-dos16.sys.h : $(srcdir)/src/$$T.asm
i386-dos32.djgpp2% : tc_list = arch-i386 default
i386-dos32.djgpp2.h : $(srcdir)/src/$$T.asm
$(call tc,pp-nasm) --MMD=$@ $< -o tmp/$T.tmp1
$(call tc,app-nasm) tmp/$T.tmp1 tmp/$T.tmp2
$(call tc,nasm) -f bin -l tmp/$T.bin.lst tmp/$T.tmp2 -o tmp/$T.bin
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin
$(call tc,m-objcopy) --strip-unneeded tmp/$T.bin
$(call tc,m-objcopy) -R .text -R .data -R .bss tmp/$T.bin
$(call tc,m-objcopy) -R .note -R .comment tmp/$T.bin
$(call tc,m-objdump) -trwh tmp/$T.bin >> tmp/$T.bin
$(call tc,bin2h) --ident=nrv_loader tmp/$T.bin $@
i386-dos32.djgpp2-stubify.h : $(srcdir)/src/$$T.asm

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,617 @@
/*
; macros.ash --
;
; This file is part of the UPX executable compressor.
;
; Copyright (C) 1996-2006 Markus Franz Xaver Johannes Oberhumer
; Copyright (C) 1996-2006 Laszlo Molnar
; 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>
;
*/
.intel_syntax noprefix
.macro section name
.section \name
.code32
.endm
.macro CPU id
.ifc \id, 386
//.arch i386, nojumps
.endif
.ifc \id, 486
.arch i486, nojumps
.endif
.endm
.macro jmps target
.byte 0xeb, \target - . - 1
.endm
.macro jos target
.byte 0x70, \target - . - 1
.endm
.macro jnos target
.byte 0x71, \target - . - 1
.endm
.macro jcs target
.byte 0x72, \target - . - 1
.endm
.macro jncs target
.byte 0x73, \target - . - 1
.endm
.macro jzs target
.byte 0x74, \target - . - 1
.endm
.macro jnzs target
.byte 0x75, \target - . - 1
.endm
.macro jnas target
.byte 0x76, \target - . - 1
.endm
.macro jas target
.byte 0x77, \target - . - 1
.endm
.macro jss target
.byte 0x78, \target - . - 1
.endm
.macro jnss target
.byte 0x79, \target - . - 1
.endm
.macro jps target
.byte 0x7a, \target - . - 1
.endm
.macro jnps target
.byte 0x7b, \target - . - 1
.endm
.macro jls target
.byte 0x7c, \target - . - 1
.endm
.macro jnls target
.byte 0x7d, \target - . - 1
.endm
.macro jngs target
.byte 0x7e, \target - . - 1
.endm
.macro jgs target
.byte 0x7f, \target - . - 1
.endm
#define jes jzs
#define jnes jnzs
#define jbes jnas
/*
;; =============
;; ============= 32-BIT CALLTRICK & JUMPTRICK
;; =============
;; call & jump trick : 2 in 1
*/
.macro cjt32 addvalue
section CALLTR00
mov ecx, offset filter_length
calltrickloop:
mov al, [edi]
inc edi
sub al, 0xE8
ct1:
cmp al, 1
ja calltrickloop
section CTCLEVE1
cmpb [edi], offset filter_cto
jnzs calltrickloop
section CALLTR01
mov eax, [edi]
mov bl, [edi + 4]
section CTBSHR01
shr ax, 8
section CTBROR01
xchg ah, al
section CTBSWA01
rol eax, 16
xchg ah, al
section CALLTR02
sub eax, edi
sub bl, 0xE8
.if \addvalue
add eax, \addvalue
.endif
mov [edi], eax
add edi, 5
mov al, bl
loop ct1
section CALLTR10
//;; 32-bit call XOR jump trick
mov ecx, offset filter_length
ctloop1:
section CALLTRE8
mov al,0xE8
section CALLTRE9
mov al,0xE9
section CALLTR11
ctloop2:
repnz
scasb
jnzs ctend
section CTCLEVE2
cmpb [edi], offset filter_cto
jnzs ctloop2
section CALLTR12
mov eax, [edi]
section CTBSHR11
shr ax, 8
section CTBROR11
xchg ah, al
section CTBSWA11
rol eax, 16
xchg ah, al
section CALLTR13
sub eax, edi
.if \addvalue
add eax, \addvalue
.endif
stosd
jmps ctloop1
ctend:
section CTTHEEND
.endm
#if 0
;; call/jump/jcc trick; also used more than once (and/or optionally), so
;; ecx has byte count (not count of applied instances), and
;; edi points to buffer.
%macro ckt32 2
; 1st param: effective addvalue (typically 0 or edi; any rvalue)
; 2nd param: where is cto8 (dl, bl, or literal)
section CKLLTR00
%ifnidn %1,0
mov esi, %1
%endif
jmps ckstart
ckloop3:
mov al, [edi]
add edi, byte 1
section CKLLTR10 Jcc only
cmp al, 0x80 ; lo of 6-byte Jcc
jb ckloop2
cmp al, 0x8f ; hi of 6-byte Jcc
ja ckloop2
cmp byte [edi -2], 0x0F ; prefix of 6-byte Jcc
je ckmark
ckloop2:
section CKLLTR20
sub al, 0xE8
cmp al, 0xE9 - 0xE8
ja ckcount
ckmark:
cmp byte [edi], %2 ; cto8
jnz ckcount
mov eax, [edi]
shr ax, 8
rol eax, 16
xchg ah, al
; above 3 instr are equivalent to the following 2 instr:
; mov al, 0 ; clear cto8 [setup partial-write stall]
; bswap eax ; not on 386: need 486 and up
sub eax, edi
%ifnidn %1,0
add eax, esi
%endif
mov [edi], eax
add edi, byte 4
ckstart:
sub ecx, byte 4
section CKLLTR30 Jcc only
mov al, [edi]
add edi, byte 1
loop ckloop2 ; prefix cannot overlap previous displacement
section CKLLTR40
ckcount:
sub ecx, byte 1
jg ckloop3
ckend:
%endmacro
;; =============
;; ============= 32-BIT RELOCATIONS
;; =============
%macro reloc32 3
section RELOC320
reloc_main:
xor eax, eax
mov al, [%1]
inc %1
or eax, eax
jz reloc_endx
cmp al, 0xEF
ja reloc_fx
reloc_add:
add %2, eax
%if 1
mov eax, [%2]
xchg ah, al
rol eax, 16
xchg ah, al
add eax, %3
mov [%2], eax
%else
add [%2], %3
%endif
jmps reloc_main
reloc_fx:
and al, 0x0F
shl eax, 16
mov ax, [%1]
add %1, byte 2
section REL32BIG
or eax, eax
jnz reloc_add
mov eax, [%1]
add %1, byte 4
section RELOC32J
jmps reloc_add
reloc_endx:
section REL32END
%endmacro
;; =============
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
;; =============
;;;; names of pseudo-sections for addLoader:
;; LXUNFnnn Linux unfilter
;; LXMRUnnn MostRecentlyUsed recoding of destinations
;; MRUARBnn arbitrary number of entries in wheel
;; MRUBITSn power of 2 entries in wheel (smaller code)
;; MRUBYTEn 256 entries in wheel (smallest code)
%macro ctojr32 0
%push ctojr32
;; I got confused by the syntactic sugar of the fake %ifdefs.
;; I can read the section name more easily when it is at the left margin.
;; Also, some of the logic to select the sections is not that simple,
;; and any mismatch between the logic and the %ifdefs is very confusing.
;; Instead, I use comments after the section name, and blank lines for grouping.
section LXUNF000 enter at +0 for decompression; +2 for unfiltering
jmps decompr0
section LXUNF002
;; 2+ address of decompress subroutine
;; unfilter(upx_byte *, length, cto8)
lxunfilter:
pop edx ; return address
pop eax ; upx_byte *, same as addvalue
pop ecx ; length
xchg eax, edi ; edi= pointer; eax= saved_edi
pusha ; save C-convention ebx, ebp, esi, edi; also eax, edx
; at most one of the next 2
section MRUBYTE0 256==n_mru
xor ebx, ebx ; zero
section LXMRU005 0!=n_mru
mov ebx, 'NMRU' ; modified N_MRU or N_MRU -1
section LXMRU006 0!=n_mru
push byte 0x0f ; prefix of 6-byte Jcc <d32>
pop eax
mov ah, [esp + 8*4] ; cto8
section LXMRU007 0==n_mru
push byte 0x0f ; prefix of 6-byte Jcc <d32>
pop ebx
mov bh, [esp + 8*4] ; cto8
section LXUNF008
mov dl, [esp + 8*4] ; cto8
section LXUNF010
jmpn lxunf0
decompr0:
;; These %define are only if 0!=n_mru;
;; else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
%define %$n_mru [esi]
%define %$n_mru1 [esi]
%define %$tail [esi + 4*1]
%define %$cto8_e8e9 [esi + 4*2]
%define %$cto8_0f [esi + 4*3]
%define %$addvalue [esi + 4*4]
%define %$tmp ebp
%define %$hand ebx
%define %$hand_l bl
%define %$kh edx
%define %$kh_l dl
section LXJCC010
lxunf2: ; have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
movzx ebp, word [edi] ; 2 bytes, zero-extended
section LXMRU045 0!=n_mru
sub ebp, %$cto8_0f
section LXMRU046 0==n_mru
sub ebp, ebx
section LXJCC020 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
jne unfcount
section LXJCC021 0!=n_mru and Jcc participates; must set Carry
sub ebp, byte 1 ; set Carry iff in range
jnb unfcount
section LXJCC023 found Jcc; re-swap 0x8Y opcode and 0x0f prefix
mov byte [edi -1], bl ; 0x0f prefix
dec ecx ; preserve Carry
mov byte [edi], al ; Jcc opcode
inc edi ; preserve Carry
section LXUNF037
%define %$jc eax
lxunf: ; in: Carry set iff we should apply mru and 0!=n_mru
mov eax, [edi] ; BE32 displacement with cto8 in low 8 bits
section LXUNF386 0!=n_mru && 386
pushf
section LXUNF387 ==386
shr ax, 8
rol eax, 16
xchg ah, al
section LXUNF388 0!=n_mru && 386
popf
jnc unf_store ; do not apply mru
section LXUNF486 >=486
mov al, byte 0
CPU 486
bswap eax ; preserve Carry (2-byte instruction)
CPU 386
section LXUNF487 0!=n_mru && >=486
jnc unf_store ; do not apply mru
section LXMRU065 0!=n_mru
shr %$jc, 1 ; eax= jc, or mru index
jnc mru4 ; not 1st time for this jc
section MRUBYTE3
dec %$hand_l
section MRUARB30
dec %$hand
section MRUBITS3
and %$hand, %$n_mru1
section MRUARB40
jge mru3
add %$hand, %$n_mru
mru3:
section LXMRU070
mov [esp + 4*%$hand], %$jc ; 1st time: mru[hand] = jc
jmps unf_store
mru4: ; not 1st time for this jc
lea %$kh, [%$jc + %$hand] ; kh = jc + hand
section MRUBYTE4
movzx %$kh, %$kh_l
section MRUBITS4
and %$kh, %$n_mru1
section MRUARB50
cmp %$kh, %$n_mru
jb mru5
sub %$kh, %$n_mru
mru5:
section LXMRU080
mov %$jc, [esp + 4*%$kh] ; jc = mru[kh]
section MRUBYTE5
dec %$hand_l
section MRUARB60
dec %$hand
section MRUBITS5
and %$hand, %$n_mru1
section MRUARB70
jge mru6
add %$hand, %$n_mru
mru6:
section LXMRU090
mov %$tmp, [esp + 4*%$hand] ; tmp = mru[hand]
test %$tmp,%$tmp
jnz mru8
push %$jc ; ran out of registers
mov eax, %$tail
section MRUBYTE6
dec al
section MRUARB80
dec eax
section MRUBITS6
and eax, %$n_mru1
section MRUARB90
jge mru7
add eax, %$n_mru
mru7:
section LXMRU100
xor %$tmp,%$tmp
mov %$tail, eax
xchg [4+ esp + 4*eax], %$tmp ; tmp = mru[tail]; mru[tail] = 0
pop %$jc
mru8:
mov [esp + 4*%$kh ], %$tmp ; mru[kh] = tmp
mov [esp + 4*%$hand], %$jc ; mru[hand] = jc
section LXUNF040
unf_store:
sub eax, edi
sub ecx, byte 4
; one of the next2
section LXMRU110 0!=n_mru
add eax, %$addvalue
section LXMRU111 0==n_mru
add eax, esi ; addvalue (same as initial pointer)
section LXUNF041
mov [edi], eax
add edi, byte 4
jmps unfcount
section LXUNF042
lxunf0: ;; continuation of entry prolog for unfilter
section LEXEC016 bug in APP: jmp and label must be in same .asx/.asy
jmp lxunf0 ; this instr does not really go here!
section LXMRU010 0!=n_mru
push eax ; cto8_0f
section LXJMPA00 only JMP, and not CALL, is filtered
mov al, 0xE9
section LXCALLB0 only CALL, or both CALL and JMP are filtered
mov al, 0xE8
section LXUNF021 common tail
push eax ; cto8_e8e9
push byte 0 ; tail
push ebx ; n_mru or n_mru1
mov esi, esp ; flat model "[esi]" saves a byte over "[ebp]"
section LXMRU022 0==n_mru
pop esi ; addvalue
mov edx, ebx ; dh= cto8
section LXJMPA01 only JMP, and not CALL, is filtered
mov dl, 0xE9
section LXCALLB1 only CALL, or both CALL and JMP are filtered
mov dl, 0xE8
section MRUBITS1
inc %$hand ; n_mru1 ==> n_mru
section LXMRU030
lxunf1: ; allocate and clear mru[]
push byte 0
; one of the next 2, if n_mru
section MRUBYTE1
dec %$hand_l
section MRUARB10
dec %$hand
section LXMRU040 0!=n_mru
jnz lxunf1 ; leaves 0=='hand'
section LXUNF030
lxctloop:
movzx eax, word [edi] ; 2 bytes, zero extended
add edi, byte 1
section LXJCC000
cmp al, 0x80 ; lo of Jcc <d32>
jb lxct1
cmp al, 0x8f ; hi of Jcc <d32>
jbe lxunf2
lxct1:
section LXCJ0MRU 0==n_mru
sub eax, edx
section LXCJ1MRU 0!=n_mru
sub eax, %$cto8_e8e9
; both CALL and JMP are filtered
section LXCALJMP
sub eax, byte 1+ (0xE9 - 0xE8) ; set Carry iff in range (result: -2, -1)
; only CALL, or only JMP, is filtered
section LXCALL00 0==n_mru
je lxunf
section LXCALL01 0!=n_rmu
sub eax, byte 1 ; set Carry iff in range
section LXCJ2MRU 0==n_mru, or apply mru to all that are filtered here
jb lxunf ; only Carry (Borrow) matters
section LXCJ4MRU 0!=n_mru, but apply mru only to subset of filtered here
jnb unfcount ; was not filtered anyway: do not unfilter
;we will unfilter, and 0!=n_mru, but should we apply mru?
section LXCJ6MRU apply mru to JMP only (0xFF==al)
jpe lxct3 ; jump if even number of 1 bits in al
section LXCJ7MRU apply mru to CALL only (0xFE==al)
jpo lxct3 ; jump if odd number of 1 bits in al
section LXCJ8MRU do not apply mru to one or both
clc
lxct3:
jmps lxunf
section LXUNF034
unfcount:
sub ecx, byte 1
jg lxctloop
section LXMRU055
mov edi, esp ; clear mru[] portion of stack
section MRUBYTE2
mov ecx, 4+ 256 ; unused, tail, cto8_e8e9, cto8_0f
section MRUBITS2
mov ecx, %$n_mru1
add ecx, byte 1+ 4 ; n_mru1, tail, cto8_e8e9, cto8_0f
section MRUARB20
mov ecx, %$n_mru
add ecx, byte 4 ; n_mru, tail, cto8_e8e9, cto8_0f
section LXMRU057
xor eax, eax
rep
stosd
mov esp, edi
section LXMRU058 0==n_mru
push esi
section LXUNF035
popa
xchg eax, edi
push ecx
push eax
push edx
ret
%pop
%endmacro
#endif
// vi:ts=8:et:nowrap

View File

@ -0,0 +1,200 @@
/*
; n2e_d32.ash -- ucl_nrv2e_decompress_le32 in 32-bit assembly
;
; This file is part of the UCL data compression library.
;
; Copyright (C) 1996-2006 Markus Franz Xaver Johannes Oberhumer
; All Rights Reserved.
;
; The UCL library is free software; you can redistribute it and/or
; modify it 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.
;
; The UCL library 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 the UCL library; 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
; <markus@oberhumer.com>
; http://www.oberhumer.com/opensource/ucl/
;
; ------------- DECOMPRESSION -------------
; Input:
; esi - source
; edi - dest
; ebp - -1
; cld
; Output:
; eax - 0
; ecx - 0
*/
// CPU 386
.macro getbit_n2e one
.ifc \one, 1
add ebx, ebx
jnz 1f
.endif
mov ebx, [esi]
sub esi, -4
adc ebx, ebx
1:
.endm
#undef getbit
#define getbit getbit_n2e
section N2ESMA10
jmps dcl1_n2e
decompr_literals_n2e:
movsb
section N2EFAS10
jmps dcl1_n2e
section N2EFAS11
decompr_literalb_n2e:
mov al, [esi]
inc esi
mov [edi], al
inc edi
section N2EDEC10
decompr_loop_n2e:
add ebx, ebx
jnz dcl2_n2e
dcl1_n2e:
getbit 32
dcl2_n2e:
section N2ESMA20
jcs decompr_literals_n2e
xor eax, eax
inc eax
section N2EFAS20
#ifndef UPX102
mov al, [edi] // force data cache allocate (PentiumPlain or MMX)
#endif
jcs decompr_literalb_n2e
mov eax, 1
section N2EDEC20
loop1_n2e:
getbit 1
adc eax, eax
section N2ESMA30
getbit 1
jcs loopend1_n2e
section N2EFAS30
add ebx, ebx
jnc loopcontinue1_n2e
jnzs loopend1_n2e
getbit 32
jcs loopend1_n2e
loopcontinue1_n2e:
section N2EDEC30
dec eax
getbit 1
adc eax, eax
jmps loop1_n2e
decompr_mlen1_n2e:
getbit 1
adc ecx, ecx
jmps decompr_got_mlen_n2e
loopend1_n2e:
xor ecx, ecx
sub eax, 3
jb decompr_prev_dist_n2e
shl eax, 8
mov al, [esi]
inc esi
xor eax, -1
jzs decompr_end_n2e
sar eax, 1 // shift low-bit into carry
mov ebp, eax
jmps decompr_ebpeax_n2e
decompr_prev_dist_n2e:
getbit 1
decompr_ebpeax_n2e:
jcs decompr_mlen1_n2e
inc ecx
getbit 1
jcs decompr_mlen1_n2e
loop2_n2e:
getbit 1
adc ecx, ecx
section N2ESMA40
getbit 1
jncs loop2_n2e
section N2EFAS40
add ebx, ebx
jncs loop2_n2e
jnz loopend2_n2e
getbit 32
jncs loop2_n2e
loopend2_n2e:
section N2ESMA50
inc ecx
inc ecx
section N2EFAS50
add ecx, 2
section N2EDEC50
decompr_got_mlen_n2e:
cmp ebp, -0x500
adc ecx, 2
section N2ESMA60
#ifndef UPX102
push esi
#else
mov edx, esi
#endif
lea esi, [edi+ebp]
rep
movsb
#ifndef UPX102
pop esi
#else
mov esi, edx
#endif
jmp decompr_loop_n2e
section N2EFAS60
lea edx, [edi+ebp]
cmp ebp, -4
#ifndef UPX102
mov al, [edi+ecx] // force data cache allocate (PentiumPlain or MMX)
#endif
jbes decompr_copy4_n2e
loop3_n2e:
mov al, [edx]
inc edx
mov [edi], al
inc edi
dec ecx
jnz loop3_n2e
jmp decompr_loop_n2e
section N2EFAS61
decompr_copy4_n2e:
mov eax, [edx]
add edx, 4
mov [edi], eax
add edi, 4
sub ecx, 4
ja decompr_copy4_n2e
add edi, ecx
jmp decompr_loop_n2e
section N2EDEC60
decompr_end_n2e:
// vi:ts=8:et

View File

@ -1,3 +1,4 @@
/*
; l_djgpp2.asm -- loader & decompressor for the djgpp2/coff format
;
; This file is part of the UPX executable compressor.
@ -24,93 +25,72 @@
; Markus F.X.J. Oberhumer Laszlo Molnar
; <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
;
*/
#include "arch/i386/macros2.ash"
%define jmps jmp short
%define jmpn jmp near
%include "arch/i386/macros.ash"
BITS 32
SECTION .text
ORG 0
CPU 386
; =============
; ============= ENTRY POINT
; =============
; __DJ2MAIN1__
start:
section DJ2MAIN1
push ds
pop es
mov esi, 'INPP' ; input pointer
mov edi, 'OUTP' ; output pointer
%ifdef __DJCALLT1__
mov esi, offset start_of_compressed
mov edi, offset start_of_uncompressed
section DJCALLT1
push edi
%endif; __DJ2MAIN2__
; cld ; the stub sets this
or ebp, byte -1
section DJ2MAIN2
or ebp, -1
; __LZMA_INIT_STACK__
section LZMA_INIT_STACK
/*
; as this stub gets loaded from 0x000000a8, we have some scratch
; memory starting from 0x00000000 to store ss:esp
; note: NULL page protection is only activated by the
; uncompressed application later
*/
xor eax, eax
mov [eax], ss
mov [eax + 4], esp
mov eax, ds
mov ss, eax
mov esp, 'ESP0'
mov esp, offset stack_for_lzma
/*
; =============
; ============= DECOMPRESSION
; =============
*/
%include "arch/i386/nrv2b_d32.ash"
%include "arch/i386/nrv2d_d32.ash"
%include "arch/i386/nrv2e_d32.ash"
%include "arch/i386/lzma_d.ash"
//include "arch/i386/nrv2b_d32.ash"
//#include "arch/i386/nrv2d_d32.ash"
#include "arch/i386/nrv2e_d32_2.ash"
//#include "arch/i386/lzma_d.ash"
; __LZMA_DONE_STACK__
mov ss, [eax] ; eax is always 0 here
section LZMA_DONE_STACK
mov ss, [eax] // eax is always 0 here
mov esp, [eax + 4]
; =============
; __DJ2BSS00__
mov ecx, 'BSSL'
section DJ2BSS00
mov ecx, offset length_of_bss
rep
stosd
%ifdef __DJCALLT2__
; =============
; ============= CALLTRICK
; =============
section DJCALLT2
pop edi
cjt32 0
%endif; __DJRETURN__
; =============
push dword 'ENTR' ; entry point
ret
section DJRETURN
jmp original_entry
/*
; because of a feature of the djgpp loader, the size of this stub must be
; a multiple of 4 and as the upx decompressor depends on the fact that
; the compressed data stream begins just after the header, i must
; use an alignment here - ML
align 4
%include "include/header.ash"
eof:
; __DJTHEEND__
section .data
dd -1
dw eof
; the compressed data stream begins just after the header,
; so the header section should be 4 byte aligned
*/
#include "include/header2.ash"
; vi:ts=8:et:nowrap
// vi:ts=8:et:nowrap