vmlinux/i386: fix filters, 0x400000 start, integration with kernel build
This commit is contained in:
+73
-45
@@ -65,11 +65,22 @@ const int *PackVmlinuxI386::getCompressionMethods(int method, int level) const
|
|||||||
const int *PackVmlinuxI386::getFilters() const
|
const int *PackVmlinuxI386::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x49,
|
0x49, 0x46,
|
||||||
-1 };
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copied from PackUnix 2006-10-13.
|
||||||
|
int PackVmlinuxI386::getStrategy(Filter &/*ft*/)
|
||||||
|
{
|
||||||
|
// Called just before reading and compressing each block.
|
||||||
|
// Might want to adjust blocksize, etc.
|
||||||
|
|
||||||
|
// If user specified the filter, then use it (-2==strategy).
|
||||||
|
// Else try the first two filters, and pick the better (2==strategy).
|
||||||
|
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
||||||
|
}
|
||||||
|
|
||||||
static int __acc_cdecl_qsort
|
static int __acc_cdecl_qsort
|
||||||
compare_Phdr(void const *aa, void const *bb)
|
compare_Phdr(void const *aa, void const *bb)
|
||||||
{
|
{
|
||||||
@@ -102,6 +113,12 @@ compare_Phdr(void const *aa, void const *bb)
|
|||||||
// LOAD 0x249000 0x02348000 0x02348000 0x81800 0xcb0fc RWE 0x1000
|
// LOAD 0x249000 0x02348000 0x02348000 0x81800 0xcb0fc RWE 0x1000
|
||||||
// STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
|
// STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
|
||||||
//
|
//
|
||||||
|
//----- kernel-2.6.18-1.2778 Fedora Core 6 test 3
|
||||||
|
//Program Headers(3)
|
||||||
|
// Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
||||||
|
// LOAD 0x001000 0xc0400000 0x00400000 0x279820 0x279820 R E 0x1000
|
||||||
|
// LOAD 0x27b000 0xc067a000 0x0067a000 0x10ee64 0x1b07e8 RWE 0x1000
|
||||||
|
// NOTE 0x000000 0x00000000 0x00000000 0x00000 0x00000 R 0x4
|
||||||
|
|
||||||
bool PackVmlinuxI386::canPack()
|
bool PackVmlinuxI386::canPack()
|
||||||
{
|
{
|
||||||
@@ -121,7 +138,7 @@ bool PackVmlinuxI386::canPack()
|
|||||||
|| ehdri.e_phoff != sizeof(ehdri) // Phdrs not contiguous with Ehdr
|
|| ehdri.e_phoff != sizeof(ehdri) // Phdrs not contiguous with Ehdr
|
||||||
|| ehdri.e_phentsize!=sizeof(Elf32_Phdr)
|
|| ehdri.e_phentsize!=sizeof(Elf32_Phdr)
|
||||||
|| ehdri.e_type!=Elf32_Ehdr::ET_EXEC
|
|| ehdri.e_type!=Elf32_Ehdr::ET_EXEC
|
||||||
|| 0x00100000!=(0x001fffff & ehdri.e_entry) // entry not an odd 1MB
|
|| 0!=(0x000fffff & ehdri.e_entry) // entry not on whole 1MB
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -190,8 +207,10 @@ int PackVmlinuxI386::buildLoader(const Filter *ft)
|
|||||||
|
|
||||||
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||||
{
|
{
|
||||||
if (ft->id == 0)
|
if (ft->id == 0) {
|
||||||
|
linker->defineSymbol("filter_length", 0);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
assert(ft->calls > 0);
|
assert(ft->calls > 0);
|
||||||
|
|
||||||
linker->defineSymbol("filter_cto", ft->cto);
|
linker->defineSymbol("filter_cto", ft->cto);
|
||||||
@@ -245,7 +264,7 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
|||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, getStrategy(ft), getFilters(), &cconf);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
||||||
@@ -268,11 +287,23 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
|||||||
shdro[1].sh_size = 1+ 4+ ph.c_len + lsize;
|
shdro[1].sh_size = 1+ 4+ ph.c_len + lsize;
|
||||||
shdro[1].sh_addralign = 1;
|
shdro[1].sh_addralign = 1;
|
||||||
|
|
||||||
unsigned char const call = 0xE8; // opcode for CALL d32
|
{
|
||||||
fo->write(&call, 1); fo_off+=1;
|
static const
|
||||||
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4); fo_off += 4;
|
#include "stub/i386-linux.kernel.head-vmlinux.h"
|
||||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
|
||||||
fo->write(loader, lsize); fo_off += lsize;
|
// ENTRY_POINT
|
||||||
|
fo->write(&head_stack[0], sizeof(head_stack)-2*(1+ 4) +1);
|
||||||
|
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
|
||||||
|
|
||||||
|
// COMPRESSED_LENGTH
|
||||||
|
fo->write(&head_stack[sizeof(head_stack)-(1+ 4)], 1);
|
||||||
|
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4);
|
||||||
|
|
||||||
|
fo_off += sizeof(head_stack);
|
||||||
|
|
||||||
|
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||||
|
fo->write(loader, lsize); fo_off += lsize;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
||||||
@@ -495,7 +526,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Example usage within build system of Linux kernel-2.6.7:
|
// Example usage within build system of Linux kernel-2.6.18:
|
||||||
//
|
//
|
||||||
//----- arch/i386/boot/compressed/Makefile
|
//----- arch/i386/boot/compressed/Makefile
|
||||||
//#
|
//#
|
||||||
@@ -507,7 +538,6 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
|
|||||||
//targets := vmlinux upx-head.o upx-piggy.o
|
//targets := vmlinux upx-head.o upx-piggy.o
|
||||||
//
|
//
|
||||||
//LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
|
//LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
|
||||||
//EXTRA_AFLAGS += -DIMAGE_OFFSET=$(IMAGE_OFFSET)
|
|
||||||
//
|
//
|
||||||
//$(obj)/vmlinux: $(obj)/upx-head.o $(obj)/upx-piggy.o FORCE
|
//$(obj)/vmlinux: $(obj)/upx-head.o $(obj)/upx-piggy.o FORCE
|
||||||
// $(call if_changed,ld)
|
// $(call if_changed,ld)
|
||||||
@@ -517,44 +547,42 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
|
|||||||
// rm -f $@
|
// rm -f $@
|
||||||
// upx --best -o $@ $<
|
// upx --best -o $@ $<
|
||||||
// touch $@
|
// touch $@
|
||||||
|
//
|
||||||
|
//#
|
||||||
|
//# The ORIGINAL build sequence using gzip is:
|
||||||
|
//# vmlinux Elf executable at top level in tree
|
||||||
|
//# (in same directory as MAINTAINERS)
|
||||||
|
//# In arch/i386:
|
||||||
|
//# boot/compressed/vmlinux.bin by objcopy -O binary
|
||||||
|
//# boot/compressed/vmlinux.bin.gz by gzip
|
||||||
|
//# boot/compressed/piggy.o by ld --format binary --oformat elf32-i386
|
||||||
|
//#
|
||||||
|
//# The 3 steps above create a linkable
|
||||||
|
//# compressed blob.
|
||||||
|
//# In arch/i386:
|
||||||
|
//# boot/compressed/vmlinux by ld head.o misc.o piggy.o
|
||||||
|
//# boot/vmlinux.bin by objcopy
|
||||||
|
//# boot/bzImage by arch/i386/boot/tools/build with
|
||||||
|
//# bootsect and setup
|
||||||
|
//#
|
||||||
|
//#
|
||||||
|
//# The MODIFIED build sequence using upx is:
|
||||||
|
//# vmlinux Elf executable at top level in tree
|
||||||
|
//# (in same directory as MAINTAINERS)
|
||||||
|
//# In arch/i386:
|
||||||
|
//# boot/compressed/upx-piggy.o by upx format vmlinux/386
|
||||||
|
//#
|
||||||
|
//# In arch/i386/boot:
|
||||||
|
//# boot/compressed/vmlinux by ld upx-head.o upx-piggy.o
|
||||||
|
//# boot/vmlinux.bin by objcopy
|
||||||
|
//# boot/bzImage by arch/i386/boot/tools/build with
|
||||||
|
//# bootsect and setup
|
||||||
|
//#
|
||||||
//-----
|
//-----
|
||||||
//
|
//
|
||||||
//----- arch/i386/boot/compressed/upx-head.S
|
//----- arch/i386/boot/compressed/upx-head.S
|
||||||
// .text
|
|
||||||
//startup_32: .globl startup_32 # In: %esi=0x90000 setup data "real_mode pointer"
|
//startup_32: .globl startup_32 # In: %esi=0x90000 setup data "real_mode pointer"
|
||||||
// #cli # this must be true already
|
// /* All code is in stub/src/i386-linux.kernel.head-vmlinux.S */
|
||||||
//
|
|
||||||
// /* The only facts about segments here, that are true for all kernels:
|
|
||||||
// * %cs is a valid "flat" code segment; no other segment reg is valid;
|
|
||||||
// * the next segment after %cs is a valid "flat" data segment, but
|
|
||||||
// * no segment register designates it yet.
|
|
||||||
// */
|
|
||||||
// movl %cs,%eax; addl $1<<3,%eax # the next segment after %cs
|
|
||||||
// movl %eax,%ds
|
|
||||||
// movl %eax,%es
|
|
||||||
// leal 0x9000(%esi),%ecx # 0x99000 typical
|
|
||||||
// movl %ecx,-8(%ecx) # 32-bit offset for stack pointer
|
|
||||||
// movl %eax,-4(%ecx) # segment for stack pointer
|
|
||||||
// lss -8(%ecx),%esp # %ss:%esp= %ds:0x99000
|
|
||||||
// /* Linux Documentation/i386/boot.txt "SAMPLE BOOT CONFIGURATION" says
|
|
||||||
// 0x8000-0x8FFF Stack and heap [inside the "real mode segment",
|
|
||||||
// just below the command line at offset 0x9000].
|
|
||||||
//
|
|
||||||
// arch/i386/boot/compressed/head.S "Do the decompression ..." says
|
|
||||||
// %esi contains the "real mode pointer" [as a 32-bit addr].
|
|
||||||
//
|
|
||||||
// In any case, avoid EBDA (Extended BIOS Data Area) below 0xA0000.
|
|
||||||
// boot.txt says 0x9A000 is the limit. LILO goes up to 0x9B000.
|
|
||||||
// */
|
|
||||||
//
|
|
||||||
// pushl $0; popf # subsumes "cli; cld"; also clears NT for buggy BIOS
|
|
||||||
//
|
|
||||||
//#ifndef IMAGE_OFFSET /*{*/
|
|
||||||
//#define IMAGE_OFFSET 0x100000
|
|
||||||
//#endif /*}*/
|
|
||||||
// movl $ IMAGE_OFFSET,%eax # destination of uncompression (and entry point)
|
|
||||||
// push %cs
|
|
||||||
/* Fall into .text of upx-compressed vmlinux. */
|
|
||||||
//-----
|
//-----
|
||||||
|
|
||||||
// Approximate translation for Linux 2.4.x:
|
// Approximate translation for Linux 2.4.x:
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
virtual const char *getName() const { return "vmlinux/386"; }
|
virtual const char *getName() const { return "vmlinux/386"; }
|
||||||
virtual const int *getCompressionMethods(int method, int level) const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
virtual int getStrategy(Filter &);
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|||||||
+8
-1
@@ -70,7 +70,7 @@ STUBS += i386-linux.elf.interp-entry.h
|
|||||||
STUBS += i386-linux.elf.interp-fold.h
|
STUBS += i386-linux.elf.interp-fold.h
|
||||||
STUBS += i386-linux.elf.shell-entry.h
|
STUBS += i386-linux.elf.shell-entry.h
|
||||||
STUBS += i386-linux.elf.shell-fold.h
|
STUBS += i386-linux.elf.shell-fold.h
|
||||||
STUBS += i386-linux.kernel.vmlinux.h
|
STUBS += i386-linux.kernel.vmlinux.h i386-linux.kernel.head-vmlinux.h
|
||||||
STUBS += i386-linux.kernel.vmlinuz.h
|
STUBS += i386-linux.kernel.vmlinuz.h
|
||||||
STUBS += i386-win32.pe.h
|
STUBS += i386-win32.pe.h
|
||||||
STUBS += m68k-atari.tos.h
|
STUBS += m68k-atari.tos.h
|
||||||
@@ -581,6 +581,13 @@ i386-linux.kernel.vmlinu%.h : $(srcdir)/src/$$T.S
|
|||||||
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
||||||
$(call tc,bin2h) --ident=nrv_loader tmp/$T.bin $@
|
$(call tc,bin2h) --ident=nrv_loader tmp/$T.bin $@
|
||||||
|
|
||||||
|
i386-linux.kernel.head-vmlinux.h : tc_list = arch-i386 default
|
||||||
|
|
||||||
|
i386-linux.kernel.head-vmlinux.h : $(srcdir)/src/$$T.S
|
||||||
|
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.tmp
|
||||||
|
$(call tc,objcopy) --output-target binary --only-section .text tmp/$T.tmp tmp/$T.bin
|
||||||
|
$(call tc,bin2h) --ident=head_stack tmp/$T.bin $@
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // i386-win32.pe
|
# // i386-win32.pe
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* i386-linux.kernel.head-vmlinux.h -- created from i386-linux.kernel.head-vmlinux.bin, 39 (0x27) bytes
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2006 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2006 Laszlo Molnar
|
||||||
|
Copyright (C) 2000-2006 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
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define HEAD_STACK_SIZE 39
|
||||||
|
#define HEAD_STACK_ADLER32 0x7a591357
|
||||||
|
#define HEAD_STACK_CRC32 0xf4f6740a
|
||||||
|
|
||||||
|
unsigned char head_stack[39] = {
|
||||||
|
140,200,131,192, 8,142,216,142,192,141,142, 0,144, 0, 0,137, /* 0x 0 */
|
||||||
|
73,248,137, 65,252, 15,178, 97,248,106, 0,157, 14,184, 0, 0, /* 0x 10 */
|
||||||
|
0, 0,232,252,255,255,255 /* 0x 20 */
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user