diff --git a/src/p_elf.h b/src/p_elf.h index c4ff8e5e..9e0b0880 100644 --- a/src/p_elf.h +++ b/src/p_elf.h @@ -65,19 +65,20 @@ struct Elf_LE32_Phdr LE32 p_memsz; /* Segment size in memory */ LE32 p_flags; /* Segment flags */ LE32 p_align; /* Segment alignment */ + + // Values for p_type + enum { PT_LOAD = 1 }; /* Loadable program segment */ + + // Values for p_flags + enum { PF_X = (1 << 0) }; /* Segment is executable */ + enum { PF_W = (1 << 1) }; /* Segment is writable */ + enum { PF_R = (1 << 2) }; /* Segment is readable */ }; -// Values for p_type -#define PT_LOAD 1 /* Loadable program segment */ - -// Values for p_flags -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ - #endif /* already included */ + /* vi:ts=4:et */ diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index ac09c65b..ec75eb56 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -39,23 +39,29 @@ #include "p_lx_exc.h" #include "p_lx_elf.h" +#define PT_LOAD Elf_LE32_Phdr::PT_LOAD + + +/************************************************************************* +// +**************************************************************************/ static const #include "stub/l_le_n2b.h" static const #include "stub/l_le_n2d.h" + +PackLinuxI386elf::PackLinuxI386elf(InputFile *f) : + super(f), phdri(NULL) +{ +} + PackLinuxI386elf::~PackLinuxI386elf() { delete[] phdri; } -PackLinuxI386elf::PackLinuxI386elf(InputFile *f) - :super(f) - ,phdri(NULL) -{ -} - const upx_byte *PackLinuxI386elf::getLoader() const { if (M_IS_NRV2B(opt->method)) @@ -78,26 +84,6 @@ int PackLinuxI386elf::getLoaderSize() const } -static inline off_t min_off_t(off_t a, off_t b) -{ - return a < b ? a : b; -} - -static inline off_t max_off_t(off_t a, off_t b) -{ - return a > b ? a : b; -} - -static off_t getbrk(Elf_LE32_Phdr const *phdr, int e_phnum) -{ - off_t brka = 0; - for (int j = 0; j < e_phnum; ++phdr, ++j) if (PT_LOAD==phdr->p_type) { - brka = max_off_t(brka, phdr->p_vaddr + phdr->p_memsz); - } - return brka; -} - - void PackLinuxI386elf::updateLoader(OutputFile *fo) { #define PAGE_MASK (~0<<12) @@ -165,7 +151,9 @@ void PackLinuxI386elf::patchLoader() bool PackLinuxI386elf::canPack() { - unsigned char buf[sizeof(Elf_LE32_Ehdr) + 16*sizeof(Elf_LE32_Phdr)]; + unsigned char buf[sizeof(Elf_LE32_Ehdr) + 14*sizeof(Elf_LE32_Phdr)]; + assert(sizeof(buf) <= 512); + exetype = 0; // FIXME: add special checks for uncompresed "vmlinux" kernel @@ -181,20 +169,20 @@ bool PackLinuxI386elf::canPack() // additional requirements for linux/elf386 if (ehdr->e_ehsize != sizeof(*ehdr)) { - throwCantPack("invalid Ehdr e_ehsize"); + throwCantPack("invalid Ehdr e_ehsize; try `--force-execve'"); return false; } if (ehdr->e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr - throwCantPack("non-contiguous Ehdr/Phdr"); + throwCantPack("non-contiguous Ehdr/Phdr; try `--force-execve'"); return false; } // The first PT_LOAD must cover the beginning of the file (0==p_offset). Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr const *)(buf + ehdr->e_phoff); for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) { - if (j >= 16) + if (j >= 14) return false; - if (PT_LOAD==phdr->p_type) { + if (phdr->PT_LOAD == phdr->p_type) { if (phdr->p_offset!=0) return false; exetype = 1; @@ -214,9 +202,9 @@ void PackLinuxI386elf::packExtent( ) { fi->seek(x.offset, SEEK_SET); - for (off_t rest = x.size; 0!=rest; ) + for (off_t rest = x.size; 0 != rest; ) { - int l = fi->readx(ibuf, min_off_t(rest, opt->unix.blocksize)); + int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize)); if (l == 0) break; rest -= l; diff --git a/src/p_lx_exc.cpp b/src/p_lx_exc.cpp index c71af26f..e86f2989 100644 --- a/src/p_lx_exc.cpp +++ b/src/p_lx_exc.cpp @@ -34,6 +34,8 @@ #include "p_unix.h" #include "p_lx_exc.h" +#define PT_LOAD Elf_LE32_Phdr::PT_LOAD + /************************************************************************* // linux/386 (generic "execve" format) @@ -85,7 +87,7 @@ int PackLinuxI386::getLoaderPrefixSize() const /************************************************************************* -// +// some ELF utitlity functions **************************************************************************/ // basic check of an Linux ELF Ehdr @@ -113,6 +115,24 @@ int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const } +off_t PackLinuxI386::getbrk(const Elf_LE32_Phdr *phdr, int e_phnum) const +{ + off_t brka = 0; + for (int j = 0; j < e_phnum; ++phdr, ++j) { + if (phdr->PT_LOAD == phdr->p_type) { + off_t b = phdr->p_vaddr + phdr->p_memsz; + if (b > brka) + brka = b; + } + } + return brka; +} + + +/************************************************************************* +// +**************************************************************************/ + bool PackLinuxI386::canPack() { if (exetype != 0) @@ -225,7 +245,7 @@ void PackLinuxI386::patchLoaderChecksum() void PackLinuxI386::updateLoader(OutputFile *fo) { #define PAGE_MASK (~0<<12) - Elf_LE32_Ehdr *ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader; + Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader; ehdr->e_phnum = 2; // The first Phdr maps the stub (instructions, data, bss) rwx. @@ -237,7 +257,7 @@ void PackLinuxI386::updateLoader(OutputFile *fo) phdro->p_offset = lsize; phdro->p_paddr = phdro->p_vaddr = 0x00400000 + (lsize &~ PAGE_MASK); phdro->p_memsz = phdro->p_filesz = fo->getBytesWritten() - lsize; - phdro->p_flags = PF_R; + phdro->p_flags = phdro->PF_R; phdro->p_align = -PAGE_MASK; patchLoaderChecksum(); diff --git a/src/p_lx_exc.h b/src/p_lx_exc.h index 5d98db0d..3ac537b6 100644 --- a/src/p_lx_exc.h +++ b/src/p_lx_exc.h @@ -46,16 +46,20 @@ public: virtual bool canPack(); protected: + // loader util virtual const upx_byte *getLoader() const; virtual int getLoaderSize() const; virtual int getLoaderPrefixSize() const; - virtual int checkEhdr(const Elf_LE32_Ehdr *ehdr) const; - + // patch util virtual void patchLoader(); virtual void patchLoaderChecksum(); virtual void updateLoader(OutputFile *); + // ELF util + virtual int checkEhdr(const Elf_LE32_Ehdr *ehdr) const; + virtual off_t getbrk(const Elf_LE32_Phdr *phdr, int e_phnum) const; + enum { UPX_ELF_MAGIC = 0x5850557f // "\x7fUPX" }; diff --git a/src/p_lx_sh.cpp b/src/p_lx_sh.cpp index c8f7f2ff..cfdee4ae 100644 --- a/src/p_lx_sh.cpp +++ b/src/p_lx_sh.cpp @@ -39,19 +39,25 @@ #include "p_lx_exc.h" #include "p_lx_sh.h" +#define PT_LOAD Elf_LE32_Phdr::PT_LOAD + + +/************************************************************************* +// +**************************************************************************/ + static const #include "stub/l_sh_n2b.h" static const #include "stub/l_sh_n2d.h" -PackLinuxI386sh::~PackLinuxI386sh() + +PackLinuxI386sh::PackLinuxI386sh(InputFile *f) : + super(f), o_shname(0), l_shname(0) { } -PackLinuxI386sh::PackLinuxI386sh(InputFile *f) - :super(f) - ,o_shname(0) - ,l_shname(0) +PackLinuxI386sh::~PackLinuxI386sh() { } @@ -77,21 +83,6 @@ int PackLinuxI386sh::getLoaderSize() const } -static inline off_t max_off_t(off_t a, off_t b) -{ - return a > b ? a : b; -} - -static off_t getbrk(Elf_LE32_Phdr const *phdr, int e_phnum) -{ - off_t brka = 0; - for (int j = 0; j < e_phnum; ++phdr, ++j) if (PT_LOAD==phdr->p_type) { - brka = max_off_t(brka, phdr->p_vaddr + phdr->p_memsz); - } - return brka; -} - - void PackLinuxI386sh::patchLoader() { lsize = getLoaderSize();