mirror of
https://github.com/upx/upx.git
synced 2025-08-11 22:52:30 +08:00
WIP: clarify compressWithFilters; reduce size of obuf for PackLinuxElf64
modified: p_lx_elf.cpp modified: packer.cpp modified: packer.h
This commit is contained in:

committed by
Markus F.X.J. Oberhumer

parent
0e2a9de2b2
commit
663d6b466b
@ -2276,8 +2276,8 @@ bool PackLinuxElf32::canPack()
|
||||
if (r_va == user_init_ava) { // found the Elf32_Rel
|
||||
unsigned r_info = get_te32(&rp->r_info);
|
||||
unsigned r_type = ELF32_R_TYPE(r_info);
|
||||
if (Elf32_Ehdr::EM_ARM == e_machine
|
||||
&& R_ARM_RELATIVE == r_type) {
|
||||
if ((Elf32_Ehdr::EM_ARM == e_machine && R_ARM_RELATIVE == r_type)
|
||||
|| (Elf32_Ehdr::EM_386 == e_machine && R_386_RELATIVE == r_type) ) {
|
||||
user_init_va = get_te32(&file_image[user_init_off]);
|
||||
}
|
||||
else {
|
||||
@ -2464,7 +2464,7 @@ PackLinuxElf64::canPack()
|
||||
return false;
|
||||
}
|
||||
|
||||
// The first PT_LOAD64 must cover the beginning of the file (0==p_offset).
|
||||
upx_uint64_t max_LOADsz = 0, max_offset = 0;
|
||||
Elf64_Phdr const *phdr = phdri;
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14) {
|
||||
@ -2472,23 +2472,27 @@ PackLinuxElf64::canPack()
|
||||
return false;
|
||||
}
|
||||
unsigned const p_type = get_te32(&phdr->p_type);
|
||||
if (1!=exetype && PT_LOAD64 == p_type) { // 1st PT_LOAD
|
||||
exetype = 1;
|
||||
load_va = get_te64(&phdr->p_vaddr); // class data member
|
||||
upx_uint64_t const p_offset = get_te64(&phdr->p_offset);
|
||||
upx_uint64_t const off = ~page_mask & load_va;
|
||||
if (off && off == p_offset) { // specific hint
|
||||
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
|
||||
// Fixing it inside upx fails because packExtent() reads original file.
|
||||
return false;
|
||||
if (PT_LOAD64 == p_type) {
|
||||
// The first PT_LOAD64 must cover the beginning of the file (0==p_offset).
|
||||
if (1!= exetype) {
|
||||
exetype = 1;
|
||||
load_va = get_te64(&phdr->p_vaddr); // class data member
|
||||
upx_uint64_t const p_offset = get_te64(&phdr->p_offset);
|
||||
upx_uint64_t const off = ~page_mask & load_va;
|
||||
if (off && off == p_offset) { // specific hint
|
||||
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
|
||||
// Fixing it inside upx fails because packExtent() reads original file.
|
||||
return false;
|
||||
}
|
||||
if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
|
||||
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
// FIXME: bad for shlib!
|
||||
hatch_off = ~3ul & (3+ get_te64(&phdr->p_memsz));
|
||||
}
|
||||
if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
|
||||
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
// FIXME: bad for shlib!
|
||||
hatch_off = ~3ul & (3+ get_te64(&phdr->p_memsz));
|
||||
break;
|
||||
max_LOADsz = UPX_MAX(max_LOADsz, get_te64(&phdr->p_filesz));
|
||||
max_offset = UPX_MAX(max_offset, get_te64(&phdr->p_filesz) + get_te64(&phdr->p_offset));
|
||||
}
|
||||
}
|
||||
// We want to compress position-independent executable (gcc -pie)
|
||||
@ -2804,7 +2808,8 @@ proceed: ;
|
||||
exetype = 0;
|
||||
|
||||
// set options
|
||||
opt->o_unix.blocksize = blocksize = file_size;
|
||||
// .blocksize: avoid over-allocating
|
||||
opt->o_unix.blocksize = blocksize = UPX_MAX(max_LOADsz, file_size - max_offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3689,6 +3694,18 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
||||
assert(e_phoff == sizeof(Elf64_Ehdr)); // checked by canPack()
|
||||
sz_phdrs = e_phnum * get_te16(&ehdri.e_phentsize);
|
||||
|
||||
// We compress separate pieces (usually each PT_LOAD, plus the gaps in the file
|
||||
// that are not covered by any PT_LOAD), but currently at run time there can be
|
||||
// only one decompressor method.
|
||||
// Therefore we must plan ahead because Packer::compressWithFilters tries
|
||||
// to find the smallest result among the available methods.
|
||||
// In the future we may allow more than one decompression method at run time,
|
||||
// but for now we must choose just one, and force compressWithFilters to use it.
|
||||
int methods[256];
|
||||
int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(M_ALL, ph.level));
|
||||
if (1 < nmethods) {
|
||||
}
|
||||
|
||||
Elf64_Phdr *phdr = phdri;
|
||||
note_size = 0;
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
|
@ -1091,6 +1091,7 @@ void Packer::relocateLoader() {
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// void Packer::compressWithFilters():
|
||||
// Try compression with several methods and filters, choose the best
|
||||
/ or first working one. Needs buildLoader().
|
||||
//
|
||||
@ -1137,7 +1138,7 @@ void Packer::relocateLoader() {
|
||||
// is OK because of the simplicity of not having two output arrays.
|
||||
**************************************************************************/
|
||||
|
||||
static int prepareMethods(int *methods, int ph_method, const int *all_methods) {
|
||||
int Packer::prepareMethods(int *methods, int ph_method, const int *all_methods) const {
|
||||
int nmethods = 0;
|
||||
if (!opt->all_methods || all_methods == nullptr) {
|
||||
methods[nmethods++] = ph_method;
|
||||
@ -1212,11 +1213,18 @@ done:
|
||||
return nfilters;
|
||||
}
|
||||
|
||||
void Packer::compressWithFilters(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr, upx_bytep f_ptr,
|
||||
unsigned f_len, const upx_bytep hdr_ptr, unsigned hdr_len,
|
||||
Filter *parm_ft, const unsigned overlap_range,
|
||||
const upx_compress_config_t *cconf, int filter_strategy,
|
||||
bool inhibit_compression_check) {
|
||||
void Packer::compressWithFilters(
|
||||
upx_bytep i_ptr, unsigned const i_len, // written and restored by filters
|
||||
upx_bytep const o_ptr, // where to put compressed output
|
||||
upx_bytep f_ptr, unsigned const f_len, // subset of [*i_ptr, +i_len)
|
||||
upx_bytep const hdr_ptr, unsigned const hdr_len,
|
||||
Filter *const parm_ft, // updated
|
||||
unsigned const overlap_range,
|
||||
upx_compress_config_t const *const cconf,
|
||||
int filter_strategy, // in+out for prepareFilters
|
||||
bool const inhibit_compression_check
|
||||
)
|
||||
{
|
||||
parm_ft->buf_len = f_len;
|
||||
// struct copies
|
||||
const PackHeader orig_ph = this->ph;
|
||||
@ -1404,18 +1412,26 @@ void Packer::compressWithFilters(upx_bytep i_ptr, unsigned i_len, upx_bytep o_pt
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void Packer::compressWithFilters(Filter *ft, const unsigned overlap_range,
|
||||
const upx_compress_config_t *cconf, int filter_strategy,
|
||||
bool inhibit_compression_check) {
|
||||
compressWithFilters(ft, overlap_range, cconf, filter_strategy, 0, 0, 0, nullptr, 0,
|
||||
inhibit_compression_check);
|
||||
void Packer::compressWithFilters(
|
||||
Filter *ft, const unsigned overlap_range,
|
||||
const upx_compress_config_t *cconf, int filter_strategy,
|
||||
bool inhibit_compression_check)
|
||||
{
|
||||
compressWithFilters( // call the subroutine immediately below
|
||||
ft, overlap_range,
|
||||
cconf, filter_strategy,
|
||||
0, 0, 0,
|
||||
nullptr, 0,
|
||||
inhibit_compression_check);
|
||||
}
|
||||
|
||||
void Packer::compressWithFilters(Filter *ft, const unsigned overlap_range,
|
||||
const upx_compress_config_t *cconf, int filter_strategy,
|
||||
unsigned filter_off, unsigned ibuf_off, unsigned obuf_off,
|
||||
const upx_bytep hdr_ptr, unsigned hdr_len,
|
||||
bool inhibit_compression_check) {
|
||||
void Packer::compressWithFilters(
|
||||
Filter *ft, const unsigned overlap_range,
|
||||
upx_compress_config_t const *cconf, int filter_strategy,
|
||||
unsigned filter_off, unsigned ibuf_off, unsigned obuf_off,
|
||||
upx_bytep const hdr_ptr, unsigned hdr_len,
|
||||
bool inhibit_compression_check)
|
||||
{
|
||||
ibuf.checkState();
|
||||
obuf.checkState();
|
||||
|
||||
@ -1427,8 +1443,13 @@ void Packer::compressWithFilters(Filter *ft, const unsigned overlap_range,
|
||||
|
||||
assert(f_ptr + f_len <= i_ptr + i_len);
|
||||
|
||||
compressWithFilters(i_ptr, i_len, o_ptr, f_ptr, f_len, hdr_ptr, hdr_len, ft, overlap_range,
|
||||
cconf, filter_strategy, inhibit_compression_check);
|
||||
compressWithFilters( // call the first one in this file
|
||||
i_ptr, i_len,
|
||||
o_ptr,
|
||||
f_ptr, f_len,
|
||||
hdr_ptr, hdr_len,
|
||||
ft, overlap_range,
|
||||
cconf, filter_strategy, inhibit_compression_check);
|
||||
|
||||
ibuf.checkState();
|
||||
obuf.checkState();
|
||||
|
22
src/packer.h
22
src/packer.h
@ -177,14 +177,23 @@ protected:
|
||||
bool inhibit_compression_check = false);
|
||||
void compressWithFilters(Filter *ft, const unsigned overlap_range,
|
||||
const upx_compress_config_t *cconf, int filter_strategy,
|
||||
unsigned filter_buf_off, unsigned compress_ibuf_off,
|
||||
unsigned compress_obuf_off, const upx_bytep hdr_ptr, unsigned hdr_len,
|
||||
unsigned filter_buf_off,
|
||||
unsigned compress_ibuf_off,
|
||||
unsigned compress_obuf_off,
|
||||
upx_bytep const hdr_ptr, unsigned hdr_len,
|
||||
bool inhibit_compression_check = false);
|
||||
// real compression driver
|
||||
void compressWithFilters(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr, upx_bytep f_ptr,
|
||||
unsigned f_len, const upx_bytep hdr_ptr, unsigned hdr_len, Filter *ft,
|
||||
const unsigned overlap_range, const upx_compress_config_t *cconf,
|
||||
int filter_strategy, bool inhibit_compression_check = false);
|
||||
void compressWithFilters(
|
||||
upx_bytep i_ptr, unsigned i_len, // written and restored by filters
|
||||
upx_bytep o_ptr,
|
||||
upx_bytep f_ptr, unsigned f_len, // subset of [*i_ptr, +i_len)
|
||||
upx_bytep const hdr_ptr, unsigned hdr_len,
|
||||
Filter *parm_ft, // updated
|
||||
unsigned overlap_range,
|
||||
upx_compress_config_t const *cconf,
|
||||
int filter_strategy,
|
||||
bool inhibit_compression_check = false
|
||||
);
|
||||
|
||||
// util for verifying overlapping decompresion
|
||||
// non-destructive test
|
||||
@ -239,6 +248,7 @@ public:
|
||||
protected:
|
||||
const int *getDefaultCompressionMethods_8(int method, int level, int small = -1) const;
|
||||
const int *getDefaultCompressionMethods_le32(int method, int level, int small = -1) const;
|
||||
int prepareMethods(int *methods, int ph_method, const int *all_methods) const;
|
||||
virtual const char *getDecompressorSections() const;
|
||||
virtual unsigned getDecompressorWrkmemSize() const;
|
||||
virtual void defineDecompressorSymbols();
|
||||
|
Reference in New Issue
Block a user