new file format vmlinux/i386

Modified Files:
	Makefile conf.h help.cpp linker.cpp p_elf.h packer.cpp
	packerf.cpp packmast.cpp stub/Makefile stub/l_vmlinz.asm
Added Files:
	p_vmlinx.h p_vmlinx.cpp stub/l_vmlinx.asm

committer: jreiser <jreiser> 1089652867 +0000
This commit is contained in:
John Reiser 2004-07-12 17:21:07 +00:00
parent cbf1dbe2cb
commit 5d331fdf69
12 changed files with 732 additions and 6 deletions

View File

@ -52,7 +52,7 @@ OBJECTS1 = \
p_com$o p_djgpp2$o p_elks$o p_exe$o \
p_lx_elf$o p_lx_exc$o p_lx_sep$o p_lx_sh$o \
p_ps1$o p_sys$o p_tmt$o p_tos$o \
p_unix$o p_vmlinz$o p_w16ne$o p_w32pe$o p_wcle$o
p_unix$o p_vmlinz$o p_vmlinx$o p_w16ne$o p_w32pe$o p_wcle$o
# no exceptions or RTTI
OBJECTS2 = \

View File

@ -437,6 +437,7 @@ inline void operator delete[](void *p)
#define UPX_F_BVMLINUZ_i386 16
#define UPX_F_ELKS_8086 17
#define UPX_F_PS1_EXE 18
#define UPX_F_VMLINUX_i386 19
#define UPX_F_ATARI_TOS 129
#define UPX_F_SOLARIS_SPARC 130

View File

@ -260,6 +260,7 @@ void show_help(int x)
" rtm32/pe,"
" tmt/adam,"
"\n "
" vmlinux/386,"
" vmlinuz/386,"
" watcom/le,"
//" win16/ne,"

View File

@ -57,7 +57,8 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
info = pinfo;
njumps = nsections = frozen = 0;
jumps = new jump[200];
sections = new section[200];
#define NSECTIONS 350
sections = new section[NSECTIONS];
char *p = iloader + info;
while (get32(p) != (unsigned)(-1))
@ -68,7 +69,7 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
sections[nsections].istart = get32(p+8);
sections[nsections++].ostart = -1;
p += 12;
assert(nsections < 200);
assert(nsections < NSECTIONS);
}
else
{
@ -154,7 +155,7 @@ void Linker::addSection(const char *sname, const void *sdata, unsigned len)
sections[nsections].istart = ilen;
sections[nsections].len = len;
sections[nsections++].ostart = olen;
assert(nsections < 200);
assert(nsections < NSECTIONS);
memcpy(iloader+ilen,sdata,len);
ilen += len;
}

View File

@ -51,6 +51,15 @@ struct Elf_LE32_Ehdr
LE16 e_shentsize; /* Section header table entry size */
LE16 e_shnum; /* Section header table entry count */
LE16 e_shstrndx; /* Section header string table index */
// Values for e_type
enum {
ET_NONE =0, /* No file type */
ET_REL =1, /* Relocatable file */
ET_EXEC =2, /* Executable file */
ET_DYN =3, /* Shared object file */
ET_CORE =4 /* Core file */
};
}
__attribute_packed;

486
src/p_vmlinx.cpp Normal file
View File

@ -0,0 +1,486 @@
/* p_vmlinx.cpp -- pack vmlinux ET_EXEC file (before bootsect or setup)
This file is part of the UPX executable compressor.
Copyright (C) 2004 John Reiser
Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2004 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
markus@oberhumer.com ml1050@cdata.tvnet.hu
John Reiser
jreiser@users.sourceforge.net
*/
#include "conf.h"
#include "file.h"
#include "filter.h"
#include "packer.h"
#include "p_vmlinx.h"
static const
#include "stub/l_vmlinx.h"
/*************************************************************************
//
**************************************************************************/
PackVmlinuxI386::PackVmlinuxI386(InputFile *f) :
super(f), shdri(NULL)
{
}
PackVmlinuxI386::~PackVmlinuxI386()
{
delete [] shdri;
}
const int *PackVmlinuxI386::getCompressionMethods(int method, int level) const
{
return Packer::getDefaultCompressionMethods_le32(method, level);
}
const int *PackVmlinuxI386::getFilters() const
{
static const int filters[] = {
0x49,
-1 };
return filters;
}
bool PackVmlinuxI386::canPack()
{
fi->seek(0, SEEK_SET);
fi->readx(&ehdri, sizeof(ehdri));
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46\x01\x01\x01", 7) // ELF 32-bit LSB
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|| ehdri.e_machine != 3 // Intel 80386
|| ehdri.e_version != 1 // version
)
return false;
// additional requirements for vmlinux
if (ehdri.e_ehsize != sizeof(ehdri) // different <elf.h> ?
|| ehdri.e_phoff != sizeof(ehdri) // Phdrs not contiguous with Ehdr
|| ehdri.e_phnum!=2 || ehdri.e_phentsize!=sizeof(Elf_LE32_Phdr)
|| ehdri.e_type!=Elf_LE32_Ehdr::ET_EXEC
|| 0x00100000!=(0x001fffff & ehdri.e_entry) // entry not an odd 1MB
) {
return false;
}
fi->seek(ehdri.e_phoff, SEEK_SET);
fi->readx(phdri, sizeof(phdri));
if (Elf_LE32_Phdr::PT_LOAD!=phdri[0].p_type || 0!=(0xfff & phdri[0].p_offset)
|| Elf_LE32_Phdr::PT_LOAD!=phdri[1].p_type || 0!=(0xfff & phdri[1].p_offset)
|| 0!=(0xfff & phdri[0].p_paddr) || 0!=(0xfff & phdri[0].p_vaddr)
|| 0!=(0xfff & phdri[1].p_paddr) || 0!=(0xfff & phdri[1].p_vaddr)
|| 0x1000!=phdri[0].p_offset
|| phdri[1].p_offset!=(phdri[0].p_offset + (~0xfff & (0xfff + phdri[0].p_filesz)))
) {
return false;
}
return true;
}
int PackVmlinuxI386::buildLoader(const Filter *ft)
{
// prepare loader
initLoader(nrv_loader, sizeof(nrv_loader));
addLoader("LINUX000",
(0x40==(0xf0 & ft->id)) ? "LXCKLLT1" : (ft->id ? "LXCALLT1" : ""),
"LXMOVEUP",
getDecompressor(),
NULL
);
if (ft->id)
{
assert(ft->calls > 0);
if (0x40==(0xf0 & ft->id)) {
addLoader("LXCKLLT9", NULL);
}
else {
addLoader("LXCALLT9", NULL);
}
addFilter32(ft->id);
}
addLoader("LINUX990""IDENTSTR""UPX1HEAD", NULL);
return getLoaderSize();
}
void PackVmlinuxI386::pack(OutputFile *fo)
{
unsigned fo_off = 0;
Elf_LE32_Ehdr ehdro;
// NULL
// .text(PT_LOADs) .note(1st page) .note(rest)
// .shstrtab /* .symtab .strtab */
Elf_LE32_Shdr shdro[1+3+1/*+2*/];
memset(shdro, 0, sizeof(shdro));
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
char const *p = shstrtab;
ibuf.alloc(file_size);
obuf.allocForCompression(file_size);
// .e_ident, .e_machine, .e_version, .e_flags
memcpy(&ehdro, &ehdri, sizeof(ehdro));
ehdro.e_type = Elf_LE32_Ehdr::ET_REL;
ehdro.e_entry = 0;
ehdro.e_phoff = 0;
ehdro.e_shoff = 0; // later
ehdro.e_phentsize = 0;
ehdro.e_phnum = 0;
ehdro.e_shnum = 1+3+1/*+2*/;
ehdro.e_shstrndx = 4;
fo->write(&ehdro, sizeof(ehdro)); fo_off+= sizeof(ehdro);
// .data length + (.text length padded to PAGE_SIZE)
ph.u_len = phdri[1].p_filesz + (phdri[1].p_offset - phdri[0].p_offset);
fi->seek(phdri[0].p_offset, SEEK_SET);
fi->readx(ibuf, ph.u_len);
checkAlreadyPacked(ibuf + ph.u_len - 1024, 1024);
// prepare filter
ph.filter = 0;
Filter ft(ph.level);
ft.buf_len = ph.u_len;
ft.addvalue = 0;
compressWithFilters(&ft, 1 << 20);
const unsigned lsize = getLoaderSize();
MemBuffer loader(lsize);
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader, lsize);
patch_le32(loader, lsize, "ULEN", ph.u_len);
patchFilter32(loader, lsize, &ft);
while (0!=*p++) ;
shdro[1].sh_name = p - shstrtab;
shdro[1].sh_type = Elf_LE32_Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Elf_LE32_Shdr::SHF_ALLOC | Elf_LE32_Shdr::SHF_EXECINSTR;
shdro[1].sh_offset = fo_off;
shdro[1].sh_size = 1+ 4+ ph.c_len + lsize;
shdro[1].sh_addralign = 1;
char const call = 0xE8; // opcode for CALL d32
fo->write(&call, 1); fo_off+=1;
fo->write(&ph.c_len, sizeof(ph.c_len)); fo_off += 4; // XXX LE32
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
fo->write(loader, lsize); fo_off += lsize;
verifyOverlappingDecompression();
// .note with 1st page --------------------------------
fi->seek(0, SEEK_SET);
ph.u_len = phdri[0].p_offset;
fi->readx(ibuf, ph.u_len);
compress(ibuf, obuf);
while (0!=*p++) ;
shdro[2].sh_name = p - shstrtab;
shdro[2].sh_type = Elf_LE32_Shdr::SHT_NOTE;
shdro[2].sh_offset = fo_off;
shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len;
shdro[2].sh_addralign = 1;
fo->write(&ph.u_len, sizeof(ph.u_len)); // XXX LE32
fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size;
// .note with rest --------------------------------
fi->seek(phdri[1].p_offset + phdri[1].p_filesz, SEEK_SET);
ph.u_len = file_size - (phdri[1].p_offset + phdri[1].p_filesz);
fi->readx(ibuf, ph.u_len);
compress(ibuf, obuf);
// while (0!=*p++) ; // name is the same
shdro[3].sh_name = p - shstrtab;
shdro[3].sh_type = Elf_LE32_Shdr::SHT_NOTE;
shdro[3].sh_offset = fo_off;
shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len;
shdro[3].sh_addralign = 1;
fo->write(&ph.u_len, sizeof(ph.u_len)); // XXX LE32
fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size;
while (0!=*p++) ;
shdro[4].sh_name = p - shstrtab;
shdro[4].sh_type = Elf_LE32_Shdr::SHT_STRTAB;
shdro[4].sh_offset = fo_off;
shdro[4].sh_size = 1+ sizeof(shstrtab); // 1+: terminating '\0'
shdro[4].sh_addralign = 1;
fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size;
#if 0 /*{ no symbols! */
while (0!=*p++) ;
fo_off = ~3 & (3+ fo_off);
shdro[5].sh_name = p - shstrtab;
shdro[5].sh_type = Elf_LE32_Shdr::SHT_SYMTAB;
shdro[5].sh_offset = fo_off;
shdro[5].sh_size = 16; // XXX ?
shdro[5].sh_link = 6; // to .strtab for symbols
shdro[5].sh_addralign = 4;
shdro[5].sh_entsize = 16; // XXX Elf32_Sym
fo->seek(fo_off, SEEK_SET);
fo->write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); fo_off += 16;
while (0!=*p++) ;
shdro[6].sh_name = p - shstrtab;
shdro[6].sh_type = Elf_LE32_Shdr::SHT_STRTAB;
shdro[6].sh_offset = fo_off;
shdro[6].sh_size = 1; // XXX ?
shdro[6].sh_addralign = 1;
fo->write("", 1); fo_off += 1;
#endif /*}*/
fo_off = ~3 & (3+ fo_off);
fo->seek(fo_off, SEEK_SET);
ehdro.e_shoff = fo_off;
fo->write(shdro, sizeof(shdro));
fo->seek(0, SEEK_SET);
fo->write(&ehdro, sizeof(ehdro));
if (!checkFinalCompressionRatio(fo))
throwNotCompressible();
}
/*************************************************************************
// unpack
**************************************************************************/
int PackVmlinuxI386::canUnpack()
{
fi->seek(0, SEEK_SET);
fi->readx(&ehdri, sizeof(ehdri));
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46\x01\x01\x01", 7) // ELF 32-bit LSB
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|| ehdri.e_machine != 3 // Intel 80386
|| ehdri.e_version != 1 // version
|| ehdri.e_type != Elf_LE32_Ehdr::ET_REL
|| ehdri.e_shnum < 4
|| file_size < (ehdri.e_shnum * sizeof(Elf_LE32_Shdr) + ehdri.e_shoff)
)
return false;
// find the .shstrtab section
char shstrtab[40];
Elf_LE32_Shdr *p, *p_shstrtab=0;
shdri = new Elf_LE32_Shdr[ehdri.e_shnum];
fi->seek(ehdri.e_shoff, SEEK_SET);
fi->readx(shdri, ehdri.e_shnum * sizeof(Elf_LE32_Shdr));
int j;
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
if (Elf_LE32_Shdr::SHT_STRTAB==p->sh_type
&& p->sh_size <= sizeof(shstrtab)
&& (p->sh_size + p->sh_offset) <= file_size
&& (10+ p->sh_name) <= p->sh_size // 1+ strlen(".shstrtab")
) {
fi->seek(p->sh_offset, SEEK_SET);
fi->readx(shstrtab, p->sh_size);
if (0==strcmp(".shstrtab", &shstrtab[p->sh_name])) {
p_shstrtab = p;
break;
}
}
}
if (0==p_shstrtab) {
return false;
}
// check for .text .note .note and sane (.sh_size + .sh_offset)
p_note0 = p_note1 = p_text = 0;
for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) {
if (file_size < (p->sh_size + p->sh_offset)
|| p_shstrtab->sh_size < (5+ p->sh_name) ) {
continue;
}
if (0==strcmp(".text", &shstrtab[p->sh_name])) {
p_text = p;
}
if (0==strcmp(".note", &shstrtab[p->sh_name])) {
if (0==p_note0) {
p_note0 = p;
} else
if (0==p_note1) {
p_note1 = p;
}
}
}
if (0==p_text || 0==p_note0 || 0==p_note1) {
return false;
}
char buf[1024];
fi->seek(p_text->sh_offset + p_text->sh_size - sizeof(buf), SEEK_SET);
fi->readx(buf, sizeof(buf));
if (!getPackHeader(buf, sizeof(buf)))
return false;
return true;
}
void PackVmlinuxI386::unpack(OutputFile *fo)
{
struct {
unsigned char opcode;
unsigned char d32[4];
} call;
PackHeader const ph_tmp(ph);
fi->seek(p_note0->sh_offset, SEEK_SET);
fi->readx(&ph.u_len, sizeof(ph.u_len)); // XXX LE32
ibuf.alloc(ph.c_len = p_note0->sh_size - sizeof(ph.u_len));
fi->readx(ibuf, ph.c_len);
obuf.allocForUncompression(ph.u_len);
decompress(ibuf, obuf, false);
fo->write(obuf, ph.u_len);
obuf.dealloc();
ibuf.dealloc();
ph = ph_tmp;
fi->seek(p_text->sh_offset, SEEK_SET);
fi->readx(&call, 5);
if (0xE8!=call.opcode
|| *(int *)&call.d32!=(int)ph.c_len // XXX LE32
) {
throwCantUnpack(".text corrupted");
}
ibuf.alloc(ph.c_len);
fi->readx(ibuf, ph.c_len);
obuf.allocForUncompression(ph.u_len);
decompress(ibuf, obuf);
Filter ft(ph.level);
ft.init(ph.filter, 0);
ft.cto = (unsigned char) ph.filter_cto;
ft.unfilter(obuf, ph.u_len);
fo->write(obuf, ph.u_len);
obuf.dealloc();
ibuf.dealloc();
fi->seek(p_note1->sh_offset, SEEK_SET);
fi->readx(&ph.u_len, sizeof(ph.u_len)); // XXX LE32
ibuf.alloc(ph.c_len = p_note1->sh_size - sizeof(ph.u_len));
fi->readx(ibuf, p_note1->sh_size - sizeof(ph.u_len));
obuf.allocForUncompression(ph.u_len);
decompress(ibuf, obuf, false);
fo->write(obuf, ph.u_len);
obuf.dealloc();
ibuf.dealloc();
ph = ph_tmp;
}
//
// Example usage within build system of Linux kernel-2.6.7:
//
//----- arch/i386/boot/compressed/Makefile
//#
//# linux/arch/i386/boot/compressed/Makefile
//#
//# create a compressed vmlinux image from the original vmlinux
//#
//
//targets := vmlinux upx-head.o upx-piggy.o
//
//LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
//
//$(obj)/vmlinux: $(obj)/upx-head.o $(obj)/upx-piggy.o FORCE
// $(call if_changed,ld)
// @:
//
//$(obj)/upx-piggy.o: vmlinux FORCE
// rm -f $(obj)/upx-piggy.o
// upx -o $(obj)/upx-piggy.o $<
//-----
//
//----- arch/i386/boot/compressed/upx-head.S
//#include <asm/segment.h>
//
// .text
//startup_32: .globl startup_32
// pushl $0; popf # subsumes "cli; cld"; also clears NT for buggy BIOS
//
// pushl $ __BOOT_DS; pop %ds # %ds= __BOOT_DS
// push %ds; pop %es # %es= __BOOT_DS
//
// movl $ startup_32,%eax # base address of uncompressed execution
// pushl $ __BOOT_CS
///* Fall into .text of upx-compressed vmlinux. */
//-----
//
// Example test jig:
// gcc -o test-piggy -nostartfiles -nostdlib test-piggy.o piggy.o
// gdb test-piggy
// (gdb) run >dumped
//----- test-piggy.S
//#include <asm/mman.h>
//#include <asm/unistd.h>
//
//dump:
// movl $0x456789,%edx # length MODIFY THIS VALUE TO SUIT YOUR CASE
// movl $0x100000,%ecx # base
// movl $1,%ebx # stdout
// movl $ __NR_write,%eax
// int $0x80
// nop
// hlt
//mmap:
// pushl %ebx
// leal 2*4(%esp),%ebx
// pushl $ __NR_mmap; popl %eax
// int $0x80
// popl %ebx
// ret $6*4
//
//_start: .globl _start
// nop
// int3 # enter debugger!
// pushl $0
// pushl $0
// pushl $ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED
// pushl $ PROT_EXEC | PROT_WRITE | PROT_READ
// pushl $0x600000 # 6MB
// pushl $0x100000 # 1MB
// call mmap
// push %cs
///* Fall into .text of upx-compressed vmlinux. */
//-----
/*
vi:ts=4:et
*/

76
src/p_vmlinx.h Normal file
View File

@ -0,0 +1,76 @@
/* p_vmlinx.h --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2004 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
markus@oberhumer.com ml1050@cdata.tvnet.hu
*/
#ifndef __UPX_P_VMLINX_H
#define __UPX_P_VMLINX_H
#include "p_elf.h"
/*************************************************************************
// vmlinx/i386 (bare binary Linux kernel image)
**************************************************************************/
class PackVmlinuxI386 : public Packer
{
typedef Packer super;
public:
PackVmlinuxI386(InputFile *f);
virtual ~PackVmlinuxI386();
virtual int getVersion() const { return 13; }
virtual int getFormat() const { return UPX_F_VMLINUX_i386; }
virtual const char *getName() const { return "vmlinux/386"; }
virtual const int *getCompressionMethods(int method, int level) const;
virtual const int *getFilters() const;
virtual void pack(OutputFile *fo);
virtual void unpack(OutputFile *fo);
virtual bool canPack();
virtual int canUnpack();
protected:
virtual int buildLoader(const Filter *ft);
// virtual const upx_byte *getLoader() const;
// virtual int getLoaderSize() const;
Elf_LE32_Ehdr ehdri; // from input file
Elf_LE32_Phdr phdri[2]; // from input file
Elf_LE32_Shdr *shdri; // from input file
Elf_LE32_Shdr *p_text;
Elf_LE32_Shdr *p_note0;
Elf_LE32_Shdr *p_note1;
};
#endif /* already included */
/*
vi:ts=4:et
*/

View File

@ -373,6 +373,7 @@ bool Packer::patchFilter32(void *loader, int lsize, const Filter *ft)
if (ft->id < 0x80) {
if (0x40 <= ft->id && ft->id < 0x50
&& ( UPX_F_LINUX_i386 ==ph.format
|| UPX_F_VMLINUX_i386 ==ph.format
|| UPX_F_VMLINUZ_i386 ==ph.format
|| UPX_F_BVMLINUZ_i386==ph.format ) ) {
// "push byte '?'"

View File

@ -49,6 +49,7 @@
#include "p_w16ne.h"
#include "p_w32pe.h"
#include "p_vmlinz.h"
#include "p_vmlinx.h"
#include "p_ps1.h"
@ -182,6 +183,8 @@ static Packer* try_packers(InputFile *f, try_function func)
//
// linux kernel
//
if ((p = func(new PackVmlinuxI386(f),f)) != NULL)
return p;
if ((p = func(new PackVmlinuzI386(f),f)) != NULL)
return p;
if ((p = func(new PackBvmlinuzI386(f),f)) != NULL)
@ -224,6 +227,7 @@ static Packer* try_packers(InputFile *f, try_function func)
return p;
if ((p = func(new PackCom(f),f)) != NULL)
return p;
return NULL;
}

View File

@ -35,7 +35,7 @@ STUBS = \
l_lx_exec86.h fold_exec86.h \
l_lx_elf86.h fold_elf86.h \
l_lx_sh86.h fold_sh86.h \
l_vmlinz.h
l_vmlinz.h l_vmlinx.h
# experimental:
ifneq ($(strip $(wildcard $(srcdir)/l_ext2.asm)),)
@ -221,6 +221,10 @@ l_vmlinz.h: l_vmlinz.asx
$(NASM) -f bin -o $T.bin $<
$(BIN2H) $T.bin nrv_loader $@
l_vmlinx.h: l_vmlinx.asx
$(NASM) -f bin -o $T.bin $<
$(BIN2H) $T.bin nrv_loader $@
l_vxd.h: l_vxd.asx
$(NASM) -f bin -o $T.bin $<
$(BIN2H) $T.bin nrv_loader $@
@ -398,6 +402,7 @@ l_t_n2e.h: n2e_d.ash bits.ash $(DEPS1) ../version.h
l_t_n2es.h: n2e_d.ash bits.ash $(DEPS1) ../version.h
l_tmt.h: $(DEPS2) $(DEPS3)
l_vmlinz.h: $(DEPS2) $(DEPS3)
l_vmlinx.h: $(DEPS2) $(DEPS3)
l_vxd.h: $(DEPS2) $(DEPS3)
l_wcle.h: $(DEPS2) $(DEPS3)
l_w32pe.h: $(DEPS2) $(DEPS3)

142
src/stub/l_vmlinx.asm Normal file
View File

@ -0,0 +1,142 @@
; l_vmlinx.asm -- loader & decompressor for the vmlinux/i386 format
;
; 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) 2004 John 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 Reiser
; <jreiser@users.sourceforge.net>
%define jmps jmp short
%define jmpn jmp near
%include "macros.ash"
BITS 32
SECTION .text
ORG 0
; =============
; ============= ENTRY POINT
; =============
start:
; In:
; %eax= &uncompressed [and final entry]; %ds= %es= __BOOT_DS
; %esp: &compressed; __BOOT_CS
; __LINUX000__
pop edx ; &compressed; length at -4(%edx)
push eax ; MATCH00(1/2) entry address; __BOOT_CS
push edi ; MATCH01 save
push esi ; MATCH02 save
%ifdef __LXCALLT1__
push eax ; MATCH03 src unfilter
%endif; __LXDUMMY0__
%ifdef __LXCKLLT1__
push eax ; MATCH03 src unfilter
push byte '?' ; MATCH04 cto unfilter
%endif; __LXMOVEUP__
push 'ULEN' ; MATCH05 uncompressed length
call move_up ; MATCH06
; =============
; ============= DECOMPRESSION
; =============
%include "n2b_d32.ash"
%include "n2d_d32.ash"
%include "n2e_d32.ash"
%include "cl1_d32.ash"
; =============
; ============= UNFILTER
; =============
pop ecx ; MATCH05 len
%ifdef __LXCKLLT9__
pop edx ; MATCH04 cto
pop edi ; MATCH03 src
ckt32 edi, dl
%endif; __LXDUMMY2__
%ifdef __LXCALLT9__
pop edi ; MATCH03 src
cjt32 0
%endif; __LINUX990__
pop esi ; MATCH02 restore
pop edi ; MATCH01 restore
xor ebx, ebx ; booting the 1st cpu
retf ; MATCH00 set cs
%define UNLAP 0x10
%define ALIGN (~0<<4)
; must have 0==(UNLAP &~ ALIGN)
move_up:
pop esi ; MATCH06 &decompressor
mov ecx,[-4+ esi] ; length of decompressor+unfilter
mov ebp,eax ; &uncompressed
add eax,[esp] ; MATCH05 ULEN + base; entry to decompressor
add eax, byte ~ALIGN + UNLAP
and eax, byte ALIGN
std
; copy decompressor
lea esi,[-1+ ecx + esi] ; unmoved top -1 of decompressor
lea edi,[-1+ ecx + eax] ; moved top -1 of decompressor
rep
movsb
mov ecx,[-4+ edx] ; length of compressed data
add ecx, byte 3
and ecx, byte ~3 ; pad to 0 mod 4
add edx,ecx ; unmoved top of compressed data
; copy compressed data
lea esi,[-4+ edx] ; unmoved top -4 of compressed data
lea edi,[-4+ eax] ; moved top -4 of compressed data
shr ecx,2
rep
movsd
cld
lea esi,[4+ edi] ; &compressed [after move]
mov edi,ebp ; &uncompressed
or ebp, byte -1 ; decompressor assumption
jmp eax ; enter moved decompressor
; =============
; ============= CUT HERE
; =============
%include "header.ash"
eof:
; __LITHEEND__
section .data
dd -1
dw eof
; vi:ts=8:et:nowrap

View File

@ -120,7 +120,7 @@ checka20:
pop ecx ; MATCH05 len
pop edx ; MATCH04 cto
pop edi ; MATCH03 src
ckt32 0, dl
ckt32 edi, dl
%endif; __LZDUMMY2__
%ifdef __LZCALLT9__
pop edi ; MATCH03 src