mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
PackLinuxElf64amd
p_lx_elf.h p_lx_elf.cpp packmast.cpp committer: jreiser <jreiser> 1131570778 +0000
This commit is contained in:
parent
09559bee8c
commit
6737a3ae09
615
src/p_lx_elf.cpp
615
src/p_lx_elf.cpp
|
@ -38,7 +38,8 @@
|
|||
#include "p_lx_exc.h"
|
||||
#include "p_lx_elf.h"
|
||||
|
||||
#define PT_LOAD Elf32_Phdr::PT_LOAD
|
||||
#define PT_LOAD32 Elf32_Phdr::PT_LOAD
|
||||
#define PT_LOAD64 Elf64_Phdr::PT_LOAD
|
||||
|
||||
|
||||
int
|
||||
|
@ -89,6 +90,62 @@ PackLinuxElf32::checkEhdr(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf64::checkEhdr(
|
||||
Elf64_Ehdr const *ehdr,
|
||||
unsigned char e_machine,
|
||||
unsigned char ei_class,
|
||||
unsigned char ei_data
|
||||
) const
|
||||
{
|
||||
const unsigned char * const buf = ehdr->e_ident;
|
||||
|
||||
if (0!=memcmp(buf, "\x7f\x45\x4c\x46", 4) // "\177ELF"
|
||||
|| buf[Elf64_Ehdr::EI_CLASS]!=ei_class
|
||||
|| buf[Elf64_Ehdr::EI_DATA] !=ei_data ) {
|
||||
return -1;
|
||||
}
|
||||
if (!memcmp(buf+8, "FreeBSD", 7)) // branded
|
||||
return 1;
|
||||
|
||||
if (get_native16(&ehdr->e_type) != Elf64_Ehdr::ET_EXEC)
|
||||
return 2;
|
||||
if (get_native16(&ehdr->e_machine) != e_machine)
|
||||
return 3;
|
||||
if (get_native32(&ehdr->e_version) != Elf64_Ehdr::EV_CURRENT)
|
||||
return 4;
|
||||
if (get_native16(&ehdr->e_phnum) < 1)
|
||||
return 5;
|
||||
if (get_native16(&ehdr->e_phentsize) != sizeof(Elf64_Phdr))
|
||||
return 6;
|
||||
|
||||
// check for Linux kernels
|
||||
acc_uint64l_t const entry = get_native64(&ehdr->e_entry);
|
||||
if (entry == 0xC0100000) // uncompressed vmlinux
|
||||
return 1000;
|
||||
if (entry == 0x00001000) // compressed vmlinux
|
||||
return 1001;
|
||||
if (entry == 0x00100000) // compressed bvmlinux
|
||||
return 1002;
|
||||
|
||||
// FIXME: add more checks for kernels
|
||||
|
||||
// FIXME: add special checks for other ELF i386 formats, like
|
||||
// NetBSD, OpenBSD, Solaris, ....
|
||||
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
||||
PackLinuxElf::PackLinuxElf(InputFile *f)
|
||||
: super(f)
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxElf::~PackLinuxElf()
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxElf32::PackLinuxElf32(InputFile *f)
|
||||
: super(f), phdri(NULL)
|
||||
{
|
||||
|
@ -99,8 +156,18 @@ PackLinuxElf32::~PackLinuxElf32()
|
|||
delete[] phdri;
|
||||
}
|
||||
|
||||
PackLinuxElf64::PackLinuxElf64(InputFile *f)
|
||||
: super(f), phdri(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxElf64::~PackLinuxElf64()
|
||||
{
|
||||
delete[] phdri;
|
||||
}
|
||||
|
||||
int const *
|
||||
PackLinuxElf32::getCompressionMethods(int method, int level) const
|
||||
PackLinuxElf::getCompressionMethods(int method, int level) const
|
||||
{
|
||||
// No real dependency on LE32.
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
|
@ -119,6 +186,19 @@ UNUSED(method); UNUSED(level); UNUSED(m_nrv2b);
|
|||
return m_nrv2e;
|
||||
}
|
||||
|
||||
int const *
|
||||
PackLinuxElf64amd::getCompressionMethods(int method, int level) const
|
||||
{
|
||||
// No real dependency on LE32.
|
||||
static const int m_nrv2e[] = { M_NRV2E_LE32, -1 };
|
||||
static const int m_nrv2b[] = { M_NRV2B_LE32, -1 };
|
||||
|
||||
/*return Packer::getDefaultCompressionMethods_le32(method, level);*/
|
||||
// 2005-04-23 FIXME: stub/l_lx_elfppc32.S hardwires ppc_d_nrv2e.S
|
||||
UNUSED(method); UNUSED(level); UNUSED(m_nrv2b);
|
||||
return m_nrv2e;
|
||||
}
|
||||
|
||||
int const *
|
||||
PackLinuxElf32ppc::getFilters() const
|
||||
{
|
||||
|
@ -128,7 +208,22 @@ PackLinuxElf32ppc::getFilters() const
|
|||
return filters;
|
||||
}
|
||||
|
||||
void PackLinuxElf32::patchLoader() { }
|
||||
int const *
|
||||
PackLinuxElf64amd::getFilters() const
|
||||
{
|
||||
static const int filters[] = {
|
||||
0x49, -1
|
||||
};
|
||||
return filters;
|
||||
}
|
||||
|
||||
void PackLinuxElf32::patchLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void PackLinuxElf64::patchLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void PackLinuxElf32::updateLoader(OutputFile *fo)
|
||||
{
|
||||
|
@ -136,16 +231,10 @@ void PackLinuxElf32::updateLoader(OutputFile *fo)
|
|||
get_native32(&elfout.phdr[0].p_vaddr));
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf32::buildLinuxLoader(
|
||||
upx_byte const *const /*proto*/,
|
||||
unsigned const /*szproto*/,
|
||||
upx_byte const *const /*fold*/,
|
||||
unsigned const /*szfold*/,
|
||||
Filter const */*ft*/
|
||||
)
|
||||
void PackLinuxElf64::updateLoader(OutputFile *fo)
|
||||
{
|
||||
return 0;
|
||||
set_native64(&elfout.ehdr.e_entry, fo->getBytesWritten() +
|
||||
get_native64(&elfout.phdr[0].p_vaddr));
|
||||
}
|
||||
|
||||
PackLinuxElf32ppc::PackLinuxElf32ppc(InputFile *f)
|
||||
|
@ -157,6 +246,15 @@ PackLinuxElf32ppc::~PackLinuxElf32ppc()
|
|||
{
|
||||
}
|
||||
|
||||
PackLinuxElf64amd::PackLinuxElf64amd(InputFile *f)
|
||||
: super(f)
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxElf64amd::~PackLinuxElf64amd()
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned
|
||||
umax(unsigned a, unsigned b)
|
||||
{
|
||||
|
@ -218,6 +316,55 @@ PackLinuxElf32ppc::buildLinuxLoader(
|
|||
return getLoaderSize();
|
||||
}
|
||||
|
||||
int
|
||||
PackLinuxElf64amd::buildLinuxLoader(
|
||||
upx_byte const *const proto,
|
||||
unsigned const szproto,
|
||||
upx_byte const *const fold,
|
||||
unsigned const szfold,
|
||||
Filter const */*ft*/
|
||||
)
|
||||
{
|
||||
int eof_empty = -1;
|
||||
initLoader(&eof_empty, 9000, 0, 0);
|
||||
|
||||
struct b_info h; memset(&h, 0, sizeof(h));
|
||||
unsigned fold_hdrlen = 0;
|
||||
unsigned sz_unc=0, sz_cpr;
|
||||
if (0 < szfold) {
|
||||
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
|
||||
fold_hdrlen = umax(0x80, sizeof(hf->ehdr) +
|
||||
get_native16(&hf->ehdr.e_phentsize) * get_native16(&hf->ehdr.e_phnum) +
|
||||
sizeof(l_info) );
|
||||
sz_unc = ((szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen));
|
||||
set_native32(&h.sz_unc, ((szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen)));
|
||||
h.b_method = (unsigned char) ph.method;
|
||||
h.b_ftid = (unsigned char) ph.filter;
|
||||
h.b_cto8 = (unsigned char) ph.filter_cto;
|
||||
}
|
||||
unsigned char const *const uncLoader = fold_hdrlen + fold;
|
||||
|
||||
unsigned char *const cprLoader = new unsigned char[sizeof(h) + sz_unc];
|
||||
if (0 < szfold) {
|
||||
int r = upx_compress(uncLoader, sz_unc, sizeof(h) + cprLoader, &sz_cpr,
|
||||
NULL, ph.method, 10, NULL, NULL );
|
||||
set_native32(&h.sz_cpr, sz_cpr);
|
||||
if (r != UPX_E_OK || sz_cpr >= sz_unc)
|
||||
throwInternalError("loader compression failed");
|
||||
}
|
||||
memcpy(cprLoader, &h, sizeof(h));
|
||||
|
||||
// This adds the definition to the "library", to be used later.
|
||||
linker->addSection("FOLDEXEC", cprLoader, sizeof(h) + sz_cpr);
|
||||
delete [] cprLoader;
|
||||
|
||||
linker->addSection("ELF64AMD", proto, szproto);
|
||||
|
||||
addLoader("ELF64AMD", 0);
|
||||
addLoader("FOLDEXEC", 0);
|
||||
return getLoaderSize();
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/l_lx_elfppc32.h"
|
||||
|
||||
|
@ -232,6 +379,20 @@ PackLinuxElf32ppc::buildLoader(const Filter *ft)
|
|||
linux_elfppc32_fold, sizeof(linux_elfppc32_fold), ft );
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/l_lx_elf64amd.h"
|
||||
|
||||
static const
|
||||
#include "stub/fold_elf64amd.h"
|
||||
|
||||
int
|
||||
PackLinuxElf64amd::buildLoader(const Filter *ft)
|
||||
{
|
||||
return buildLinuxLoader(
|
||||
linux_elf64amd_loader, sizeof(linux_elf64amd_loader),
|
||||
linux_elf64amd_fold, sizeof(linux_elf64amd_fold), ft );
|
||||
}
|
||||
|
||||
bool
|
||||
PackLinuxElf32ppc::canPack()
|
||||
{
|
||||
|
@ -260,13 +421,13 @@ PackLinuxElf32ppc::canPack()
|
|||
return false;
|
||||
}
|
||||
|
||||
// The first PT_LOAD must cover the beginning of the file (0==p_offset).
|
||||
// The first PT_LOAD32 must cover the beginning of the file (0==p_offset).
|
||||
unsigned const e_phnum = get_native16(&ehdr->e_phnum);
|
||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *)(buf + e_phoff);
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14)
|
||||
return false;
|
||||
if (phdr->PT_LOAD == get_native32(&phdr->p_type)) {
|
||||
if (phdr->PT_LOAD32 == get_native32(&phdr->p_type)) {
|
||||
// Just avoid the "rewind" when unpacking?
|
||||
//if (phdr->p_offset != 0) {
|
||||
// throwCantPack("invalid Phdr p_offset; try `--force-execve'");
|
||||
|
@ -294,12 +455,74 @@ PackLinuxElf32ppc::canPack()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PackLinuxElf64amd::canPack()
|
||||
{
|
||||
unsigned char buf[sizeof(Elf64_Ehdr) + 14*sizeof(Elf64_Phdr)];
|
||||
COMPILE_TIME_ASSERT(sizeof(buf) <= 1024);
|
||||
|
||||
exetype = 0;
|
||||
|
||||
fi->readx(buf, sizeof(buf));
|
||||
fi->seek(0, SEEK_SET);
|
||||
Elf64_Ehdr const *const ehdr = (Elf64_Ehdr const *)buf;
|
||||
|
||||
// now check the ELF header
|
||||
if (checkEhdr(ehdr, Elf64_Ehdr::EM_X86_64,
|
||||
Elf64_Ehdr::ELFCLASS64, Elf64_Ehdr::ELFDATA2LSB) != 0)
|
||||
return false;
|
||||
|
||||
// additional requirements for linux/elf386
|
||||
if (get_native16(&ehdr->e_ehsize) != sizeof(*ehdr)) {
|
||||
throwCantPack("invalid Ehdr e_ehsize; try `--force-execve'");
|
||||
return false;
|
||||
}
|
||||
acc_uint64l_t const e_phoff = get_native64(&ehdr->e_phoff);
|
||||
if (e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr
|
||||
throwCantPack("non-contiguous Ehdr/Phdr; try `--force-execve'");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The first PT_LOAD64 must cover the beginning of the file (0==p_offset).
|
||||
unsigned const e_phnum = get_native16(&ehdr->e_phnum);
|
||||
Elf64_Phdr const *phdr = (Elf64_Phdr const *)(buf + e_phoff);
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14)
|
||||
return false;
|
||||
if (phdr->PT_LOAD64 == get_native32(&phdr->p_type)) {
|
||||
// Just avoid the "rewind" when unpacking?
|
||||
//if (phdr->p_offset != 0) {
|
||||
// throwCantPack("invalid Phdr p_offset; try `--force-execve'");
|
||||
// return false;
|
||||
//}
|
||||
|
||||
// detect possible conflict upon invocation
|
||||
acc_uint64l_t const p_vaddr = get_native64(&phdr->p_vaddr);
|
||||
if (p_vaddr < (unsigned)(0x100000 + file_size)
|
||||
|| p_vaddr < (unsigned)(0x100000 + file_size) ) {
|
||||
throwAlreadyPackedByUPX(); // not necessarily, but mostly true
|
||||
return false;
|
||||
}
|
||||
exetype = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!super::canPack())
|
||||
return false;
|
||||
assert(exetype == 1);
|
||||
|
||||
// set options
|
||||
opt->o_unix.blocksize = blocksize = file_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
off_t
|
||||
PackLinuxElf32::getbrk(const Elf32_Phdr *phdr, int e_phnum) const
|
||||
{
|
||||
off_t brka = 0;
|
||||
for (int j = 0; j < e_phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD == get_native32(&phdr->p_type)) {
|
||||
if (PT_LOAD32 == get_native32(&phdr->p_type)) {
|
||||
off_t b = get_native32(&phdr->p_vaddr) + get_native32(&phdr->p_memsz);
|
||||
if (b > brka)
|
||||
brka = b;
|
||||
|
@ -308,6 +531,20 @@ PackLinuxElf32::getbrk(const Elf32_Phdr *phdr, int e_phnum) const
|
|||
return brka;
|
||||
}
|
||||
|
||||
off_t
|
||||
PackLinuxElf64::getbrk(const Elf64_Phdr *phdr, int e_phnum) const
|
||||
{
|
||||
off_t brka = 0;
|
||||
for (int j = 0; j < e_phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD64 == get_native32(&phdr->p_type)) {
|
||||
off_t b = get_native64(&phdr->p_vaddr) + get_native64(&phdr->p_memsz);
|
||||
if (b > brka)
|
||||
brka = b;
|
||||
}
|
||||
}
|
||||
return brka;
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf32::generateElfHdr(
|
||||
OutputFile */*fo*/,
|
||||
|
@ -337,7 +574,7 @@ PackLinuxElf32::generateElfHdr(
|
|||
|
||||
// Info for OS kernel to set the brk()
|
||||
if (brka) {
|
||||
set_native32(&h2->phdr[1].p_type, PT_LOAD); // be sure
|
||||
set_native32(&h2->phdr[1].p_type, PT_LOAD32); // be sure
|
||||
set_native32(&h2->phdr[1].p_offset, 0xfff&brka);
|
||||
set_native32(&h2->phdr[1].p_vaddr, brka);
|
||||
set_native32(&h2->phdr[1].p_paddr, brka);
|
||||
|
@ -346,6 +583,44 @@ PackLinuxElf32::generateElfHdr(
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf64::generateElfHdr(
|
||||
OutputFile */*fo*/,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
)
|
||||
{
|
||||
cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout;
|
||||
cprElfHdr3 *const h3 = (cprElfHdr3 *)&elfout;
|
||||
memcpy(h3, proto, sizeof(*h3)); // reads beyond, but OK
|
||||
|
||||
assert(get_native32(&h2->ehdr.e_phoff) == sizeof(Elf64_Ehdr));
|
||||
h2->ehdr.e_shoff = 0;
|
||||
assert(get_native16(&h2->ehdr.e_ehsize) == sizeof(Elf64_Ehdr));
|
||||
assert(get_native16(&h2->ehdr.e_phentsize) == sizeof(Elf64_Phdr));
|
||||
h2->ehdr.e_shentsize = 0;
|
||||
h2->ehdr.e_shnum = 0;
|
||||
h2->ehdr.e_shstrndx = 0;
|
||||
|
||||
#if 0 //{
|
||||
unsigned identsize;
|
||||
char const *const ident = getIdentstr(&identsize);
|
||||
#endif //}
|
||||
sz_elf_hdrs = sizeof(*h2) - sizeof(linfo); // default
|
||||
set_native64(&h2->phdr[0].p_filesz, sizeof(*h2)); // + identsize;
|
||||
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
|
||||
|
||||
// Info for OS kernel to set the brk()
|
||||
if (brka) {
|
||||
set_native32(&h2->phdr[1].p_type, PT_LOAD32); // be sure
|
||||
set_native64(&h2->phdr[1].p_offset, 0xfff&brka);
|
||||
set_native64(&h2->phdr[1].p_vaddr, brka);
|
||||
set_native64(&h2->phdr[1].p_paddr, brka);
|
||||
h2->phdr[1].p_filesz = 0;
|
||||
h2->phdr[1].p_memsz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf32ppc::generateElfHdr(
|
||||
OutputFile *fo,
|
||||
|
@ -367,6 +642,27 @@ PackLinuxElf32ppc::generateElfHdr(
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf64amd::generateElfHdr(
|
||||
OutputFile *fo,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
)
|
||||
{
|
||||
super::generateElfHdr(fo, proto, brka);
|
||||
|
||||
if (ph.format==UPX_F_LINUX_ELF64_AMD) {
|
||||
cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout;
|
||||
assert(2==get_native16(&h2->ehdr.e_phnum));
|
||||
set_native32(&h2->phdr[0].p_flags, Elf64_Phdr::PF_W | get_native32(&h2->phdr[0].p_flags));
|
||||
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
||||
fo->write(h2, sizeof(*h2));
|
||||
}
|
||||
else {
|
||||
assert(false); // unknown ph.format, PackLinuxElf64amd::generateElfHdr
|
||||
}
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/l_lx_elf86.h"
|
||||
static const
|
||||
|
@ -388,6 +684,22 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter &/*ft*/)
|
|||
generateElfHdr(fo, linux_elfppc32_fold, getbrk(phdri, e_phnum) );
|
||||
}
|
||||
|
||||
void PackLinuxElf64::pack1(OutputFile *fo, Filter &/*ft*/)
|
||||
{
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(&ehdri, sizeof(ehdri));
|
||||
unsigned const e_phoff = get_native32(&ehdri.e_phoff);
|
||||
unsigned const e_phnum = get_native16(&ehdri.e_phnum);
|
||||
assert(e_phoff == sizeof(Elf64_Ehdr)); // checked by canPack()
|
||||
sz_phdrs = e_phnum * get_native16(&ehdri.e_phentsize);
|
||||
|
||||
phdri = new Elf64_Phdr[e_phnum];
|
||||
fi->seek(e_phoff, SEEK_SET);
|
||||
fi->readx(phdri, sz_phdrs);
|
||||
|
||||
generateElfHdr(fo, linux_elf64amd_fold, getbrk(phdri, e_phnum) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
Extent x;
|
||||
|
@ -398,7 +710,7 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||
off_t ptload0hi = 0, ptload1lo = 0, ptload1sz = 0;
|
||||
unsigned const e_phnum = get_native16(&ehdri.e_phnum);
|
||||
for (k = 0; k < e_phnum; ++k) {
|
||||
if (PT_LOAD == get_native32(&phdri[k].p_type)) {
|
||||
if (PT_LOAD32 == get_native32(&phdri[k].p_type)) {
|
||||
x.offset = get_native32(&phdri[k].p_offset);
|
||||
x.size = get_native32(&phdri[k].p_filesz);
|
||||
if (0 == ptload0hi) {
|
||||
|
@ -431,13 +743,13 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||
ft.addvalue = 0;
|
||||
|
||||
int nx = 0;
|
||||
for (k = 0; k < e_phnum; ++k) if (PT_LOAD==get_native32(&phdri[k].p_type)) {
|
||||
for (k = 0; k < e_phnum; ++k) if (PT_LOAD32==get_native32(&phdri[k].p_type)) {
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue = phdri[k].p_vaddr;
|
||||
}
|
||||
x.offset = get_native32(&phdri[k].p_offset);
|
||||
x.size = get_native32(&phdri[k].p_filesz);
|
||||
if (0 == nx) { // 1st PT_LOAD must cover Ehdr at 0==p_offset
|
||||
if (0 == nx) { // 1st PT_LOAD32 must cover Ehdr at 0==p_offset
|
||||
unsigned const delta = sizeof(Elf32_Ehdr) + sz_phdrs;
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue += delta;
|
||||
|
@ -458,7 +770,7 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||
x.size = ptload1lo - ptload0hi;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
}
|
||||
if ((off_t)total_in < file_size) { // non-PT_LOAD stuff
|
||||
if ((off_t)total_in < file_size) { // non-PT_LOAD32 stuff
|
||||
x.offset = total_in;
|
||||
x.size = file_size - total_in;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
|
@ -469,6 +781,87 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||
set_native32(&elfout.phdr[0].p_filesz, fo->getBytesWritten());
|
||||
}
|
||||
|
||||
void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
Extent x;
|
||||
unsigned k;
|
||||
|
||||
// count passes, set ptload vars
|
||||
ui_total_passes = 0;
|
||||
off_t ptload0hi = 0, ptload1lo = 0, ptload1sz = 0;
|
||||
unsigned const e_phnum = get_native16(&ehdri.e_phnum);
|
||||
for (k = 0; k < e_phnum; ++k) {
|
||||
if (PT_LOAD64 == get_native32(&phdri[k].p_type)) {
|
||||
x.offset = get_native64(&phdri[k].p_offset);
|
||||
x.size = get_native64(&phdri[k].p_filesz);
|
||||
if (0 == ptload0hi) {
|
||||
ptload0hi = x.offset + x.size;
|
||||
}
|
||||
else if (0 == ptload1lo) {
|
||||
ptload1lo = x.offset;
|
||||
ptload1sz = x.size;
|
||||
}
|
||||
ui_total_passes++;
|
||||
}
|
||||
}
|
||||
if (0!=ptload1sz && ptload0hi < ptload1lo)
|
||||
ui_total_passes++;
|
||||
|
||||
// compress extents
|
||||
unsigned total_in = 0;
|
||||
unsigned total_out = 0;
|
||||
|
||||
ui_pass = -1; // Compressing Elf headers is invisible to UI.
|
||||
x.offset = 0;
|
||||
x.size = sizeof(Elf64_Ehdr) + sz_phdrs;
|
||||
{
|
||||
int const old_level = ph.level; ph.level = 10;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
ph.level = old_level;
|
||||
}
|
||||
|
||||
ui_pass = 0;
|
||||
ft.addvalue = 0;
|
||||
|
||||
int nx = 0;
|
||||
for (k = 0; k < e_phnum; ++k) if (PT_LOAD64==get_native32(&phdri[k].p_type)) {
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue = phdri[k].p_vaddr;
|
||||
}
|
||||
x.offset = get_native64(&phdri[k].p_offset);
|
||||
x.size = get_native64(&phdri[k].p_filesz);
|
||||
if (0 == nx) { // 1st PT_LOAD64 must cover Ehdr at 0==p_offset
|
||||
unsigned const delta = sizeof(Elf64_Ehdr) + sz_phdrs;
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue += delta;
|
||||
}
|
||||
x.offset += delta;
|
||||
x.size -= delta;
|
||||
}
|
||||
// compressWithFilters() always assumes a "loader", so would
|
||||
// throw NotCompressible for small .data Extents, which PowerPC
|
||||
// sometimes marks as PF_X anyway. So filter only first segment.
|
||||
packExtent(x, total_in, total_out,
|
||||
((0==nx && (Elf64_Phdr::PF_X & get_native64(&phdri[k].p_flags)))
|
||||
? &ft : 0 ), fo );
|
||||
++nx;
|
||||
}
|
||||
if (0!=ptload1sz && ptload0hi < ptload1lo) { // alignment hole?
|
||||
x.offset = ptload0hi;
|
||||
x.size = ptload1lo - ptload0hi;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
}
|
||||
if ((off_t)total_in < file_size) { // non-PT_LOAD64 stuff
|
||||
x.offset = total_in;
|
||||
x.size = file_size - total_in;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
}
|
||||
|
||||
if ((off_t)total_in != file_size)
|
||||
throwEOFException();
|
||||
set_native64(&elfout.phdr[0].p_filesz, fo->getBytesWritten());
|
||||
}
|
||||
|
||||
void PackLinuxElf32ppc::pack3(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
unsigned disp;
|
||||
|
@ -482,6 +875,26 @@ void PackLinuxElf32ppc::pack3(OutputFile *fo, Filter &ft)
|
|||
super::pack3(fo, ft);
|
||||
}
|
||||
|
||||
void PackLinuxElf64amd::pack3(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
unsigned disp; // 32 bits wide
|
||||
unsigned const zero = 0;
|
||||
unsigned len = fo->getBytesWritten();
|
||||
fo->write(&zero, 3& -len); // align to 0 mod 4
|
||||
len += (3& -len) + sizeof(disp);
|
||||
|
||||
// 5: sizeof(CALL instruction at _start which precedes f_decompress
|
||||
set_native32(&disp, 5+ len - sz_elf_hdrs);
|
||||
|
||||
fo->write(&disp, sizeof(disp));
|
||||
|
||||
super::pack3(fo, ft);
|
||||
}
|
||||
|
||||
void PackLinuxElf::pack4(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
super::pack4(fo, ft);
|
||||
}
|
||||
|
||||
void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
|
@ -513,6 +926,27 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
|
|||
fo->rewrite(&linfo, sizeof(linfo));
|
||||
}
|
||||
|
||||
void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
overlay_offset = sz_elf_hdrs + sizeof(linfo);
|
||||
unsigned const zero = 0;
|
||||
unsigned len = fo->getBytesWritten();
|
||||
fo->write(&zero, 3& -len); // align to 0 mod 4
|
||||
len += 3& -len;
|
||||
set_native64(&elfout.phdr[0].p_filesz, len);
|
||||
super::pack4(fo, ft); // write PackHeader and overlay_offset
|
||||
|
||||
#define PAGE_MASK (~0u<<12)
|
||||
// pre-calculate for benefit of runtime disappearing act via munmap()
|
||||
set_native64(&elfout.phdr[0].p_memsz, PAGE_MASK & (~PAGE_MASK + len));
|
||||
#undef PAGE_MASK
|
||||
|
||||
// rewrite Elf header
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->rewrite(&elfout, sz_elf_hdrs);
|
||||
fo->rewrite(&linfo, sizeof(linfo));
|
||||
}
|
||||
|
||||
void PackLinuxElf32::unpack(OutputFile *fo)
|
||||
{
|
||||
#define MAX_ELF_HDR 512
|
||||
|
@ -556,12 +990,12 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||
unsigned u_adler = upx_adler32(NULL, 0);
|
||||
off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;
|
||||
|
||||
// decompress PT_LOAD
|
||||
// decompress PT_LOAD32
|
||||
bool first_PF_X = true;
|
||||
unsigned const phnum = get_native16(&ehdr->e_phnum);
|
||||
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
|
||||
for (unsigned j=0; j < phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD==get_native32(&phdr->p_type)) {
|
||||
if (PT_LOAD32==get_native32(&phdr->p_type)) {
|
||||
unsigned const filesz = get_native32(&phdr->p_filesz);
|
||||
unsigned const offset = get_native32(&phdr->p_offset);
|
||||
if (0==ptload0hi) {
|
||||
|
@ -591,7 +1025,120 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||
unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out,
|
||||
c_adler, u_adler, false, szb_info);
|
||||
}
|
||||
if (total_out != orig_file_size) { // non-PT_LOAD stuff
|
||||
if (total_out != orig_file_size) { // non-PT_LOAD32 stuff
|
||||
if (fo)
|
||||
fo->seek(0, SEEK_END);
|
||||
unpackExtent(orig_file_size - total_out, fo, total_in, total_out,
|
||||
c_adler, u_adler, false, szb_info);
|
||||
}
|
||||
|
||||
// check for end-of-file
|
||||
fi->readx(&bhdr, szb_info);
|
||||
unsigned const sz_unc = ph.u_len = get_native32(&bhdr.sz_unc);
|
||||
|
||||
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
// note: magic is always stored le32
|
||||
unsigned const sz_cpr = get_le32(&bhdr.sz_cpr);
|
||||
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
|
||||
throwCompressedDataViolation();
|
||||
}
|
||||
else { // extra bytes after end?
|
||||
throwCompressedDataViolation();
|
||||
}
|
||||
|
||||
// update header with totals
|
||||
ph.c_len = total_in;
|
||||
ph.u_len = total_out;
|
||||
|
||||
// all bytes must be written
|
||||
if (total_out != orig_file_size)
|
||||
throwEOFException();
|
||||
|
||||
// finally test the checksums
|
||||
if (ph.c_adler != c_adler || ph.u_adler != u_adler)
|
||||
throwChecksumError();
|
||||
#undef MAX_ELF_HDR
|
||||
}
|
||||
|
||||
void PackLinuxElf64::unpack(OutputFile *fo)
|
||||
{
|
||||
#define MAX_ELF_HDR 512
|
||||
char bufehdr[MAX_ELF_HDR];
|
||||
Elf64_Ehdr *const ehdr = (Elf64_Ehdr *)bufehdr;
|
||||
Elf64_Phdr const *phdr = (Elf64_Phdr *)(1+ehdr);
|
||||
|
||||
unsigned szb_info = sizeof(b_info);
|
||||
{
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(bufehdr, MAX_ELF_HDR);
|
||||
acc_uint64l_t const e_entry = get_native64(&ehdr->e_entry);
|
||||
if (e_entry < 0x401180
|
||||
&& ehdr->e_machine==Elf64_Ehdr::EM_386) { /* old style, 8-byte b_info */
|
||||
szb_info = 2*sizeof(unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
fi->seek(overlay_offset, SEEK_SET);
|
||||
p_info hbuf;
|
||||
fi->readx(&hbuf, sizeof(hbuf));
|
||||
unsigned orig_file_size = get_native32(&hbuf.p_filesize);
|
||||
blocksize = get_native32(&hbuf.p_blocksize);
|
||||
if (file_size > (off_t)orig_file_size || blocksize > orig_file_size)
|
||||
throwCantUnpack("file header corrupted");
|
||||
|
||||
ibuf.alloc(blocksize + OVERHEAD);
|
||||
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
|
||||
fi->readx(&bhdr, szb_info);
|
||||
ph.u_len = get_native32(&bhdr.sz_unc);
|
||||
ph.c_len = get_native32(&bhdr.sz_cpr);
|
||||
ph.filter_cto = bhdr.b_cto8;
|
||||
|
||||
// Uncompress Ehdr and Phdrs.
|
||||
fi->readx(ibuf, ph.c_len);
|
||||
decompress(ibuf, (upx_byte *)ehdr, false);
|
||||
|
||||
unsigned total_in = 0;
|
||||
unsigned total_out = 0;
|
||||
unsigned c_adler = upx_adler32(NULL, 0);
|
||||
unsigned u_adler = upx_adler32(NULL, 0);
|
||||
off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;
|
||||
|
||||
// decompress PT_LOAD32
|
||||
bool first_PF_X = true;
|
||||
unsigned const phnum = get_native16(&ehdr->e_phnum);
|
||||
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
|
||||
for (unsigned j=0; j < phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD32==get_native32(&phdr->p_type)) {
|
||||
acc_uint64l_t const filesz = get_native64(&phdr->p_filesz);
|
||||
acc_uint64l_t const offset = get_native64(&phdr->p_offset);
|
||||
if (0==ptload0hi) {
|
||||
ptload0hi = filesz + offset;
|
||||
}
|
||||
else if (0==ptload1lo) {
|
||||
ptload1lo = offset;
|
||||
ptload1sz = filesz;
|
||||
}
|
||||
if (fo)
|
||||
fo->seek(offset, SEEK_SET);
|
||||
if (Elf64_Phdr::PF_X & get_native32(&phdr->p_flags)) {
|
||||
unpackExtent(filesz, fo, total_in, total_out,
|
||||
c_adler, u_adler, first_PF_X, szb_info);
|
||||
first_PF_X = false;
|
||||
}
|
||||
else {
|
||||
unpackExtent(filesz, fo, total_in, total_out,
|
||||
c_adler, u_adler, false, szb_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0!=ptload1sz && ptload0hi < ptload1lo) { // alignment hole?
|
||||
if (fo)
|
||||
fo->seek(ptload0hi, SEEK_SET);
|
||||
unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out,
|
||||
c_adler, u_adler, false, szb_info);
|
||||
}
|
||||
if (total_out != orig_file_size) { // non-PT_LOAD32 stuff
|
||||
if (fo)
|
||||
fo->seek(0, SEEK_END);
|
||||
unpackExtent(orig_file_size - total_out, fo, total_in, total_out,
|
||||
|
@ -717,12 +1264,12 @@ bool PackLinuxI386elf::canPack()
|
|||
return false;
|
||||
}
|
||||
|
||||
// The first PT_LOAD must cover the beginning of the file (0==p_offset).
|
||||
// The first PT_LOAD32 must cover the beginning of the file (0==p_offset).
|
||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *)(buf + ehdr->e_phoff);
|
||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14) // 512 bytes holds Elf32_Ehdr + Elf32_Phdr[0..13]
|
||||
return false;
|
||||
if (phdr->PT_LOAD == phdr->p_type) {
|
||||
if (phdr->PT_LOAD32 == phdr->p_type) {
|
||||
if (phdr->p_offset != 0) {
|
||||
throwCantPack("invalid Phdr p_offset; try `--force-execve'");
|
||||
return false;
|
||||
|
@ -763,7 +1310,7 @@ bool PackLinuxI386elf::canPack()
|
|||
phdri= (Elf32_Phdr *)(ehdr->e_phoff + file_image); // do not free() !!
|
||||
|
||||
int j= ehdr->e_phnum;
|
||||
Elf32_Phdr const *phdr= phdri;
|
||||
phdr= phdri;
|
||||
for (; --j>=0; ++phdr) if (Elf32_Phdr::PT_DYNAMIC==phdr->p_type) {
|
||||
dynseg= (Elf32_Dyn const *)(phdr->p_offset + file_image);
|
||||
break;
|
||||
|
@ -804,7 +1351,7 @@ PackLinuxI386elf::elf_get_offset_from_address(unsigned const addr) const
|
|||
{
|
||||
Elf32_Phdr const *phdr = phdri;
|
||||
int j = ehdri.e_phnum;
|
||||
for (; --j>=0; ++phdr) if (PT_LOAD == phdr->p_type) {
|
||||
for (; --j>=0; ++phdr) if (PT_LOAD32 == phdr->p_type) {
|
||||
unsigned const t = addr - phdr->p_vaddr;
|
||||
if (t < phdr->p_filesz) {
|
||||
return t + phdr->p_offset;
|
||||
|
@ -884,7 +1431,7 @@ void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft)
|
|||
ui_total_passes = 0;
|
||||
off_t ptload0hi = 0, ptload1lo = 0, ptload1sz = 0;
|
||||
for (k = 0; k < ehdri.e_phnum; ++k) {
|
||||
if (PT_LOAD == phdri[k].p_type) {
|
||||
if (PT_LOAD32 == phdri[k].p_type) {
|
||||
x.offset = phdri[k].p_offset;
|
||||
x.size = phdri[k].p_filesz;
|
||||
if (0 == ptload0hi) {
|
||||
|
@ -917,13 +1464,13 @@ void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft)
|
|||
ft.addvalue = 0;
|
||||
|
||||
int nx = 0;
|
||||
for (k = 0; k < ehdri.e_phnum; ++k) if (PT_LOAD==phdri[k].p_type) {
|
||||
for (k = 0; k < ehdri.e_phnum; ++k) if (PT_LOAD32==phdri[k].p_type) {
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue = phdri[k].p_vaddr;
|
||||
}
|
||||
x.offset = phdri[k].p_offset;
|
||||
x.size = phdri[k].p_filesz;
|
||||
if (0 == nx) { // 1st PT_LOAD must cover Ehdr at 0==p_offset
|
||||
if (0 == nx) { // 1st PT_LOAD32 must cover Ehdr at 0==p_offset
|
||||
unsigned const delta = sizeof(Elf32_Ehdr) + sz_phdrs;
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue += delta;
|
||||
|
@ -941,7 +1488,7 @@ void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft)
|
|||
x.size = ptload1lo - ptload0hi;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
}
|
||||
if ((off_t)total_in < file_size) { // non-PT_LOAD stuff
|
||||
if ((off_t)total_in < file_size) { // non-PT_LOAD32 stuff
|
||||
x.offset = total_in;
|
||||
x.size = file_size - total_in;
|
||||
packExtent(x, total_in, total_out, 0, fo);
|
||||
|
@ -1054,11 +1601,11 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||
unsigned u_adler = upx_adler32(NULL, 0);
|
||||
off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;
|
||||
|
||||
// decompress PT_LOAD
|
||||
// decompress PT_LOAD32
|
||||
bool first_PF_X = true;
|
||||
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
|
||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD==phdr->p_type) {
|
||||
if (PT_LOAD32==phdr->p_type) {
|
||||
if (0==ptload0hi) {
|
||||
ptload0hi = phdr->p_filesz + phdr->p_offset;
|
||||
}
|
||||
|
@ -1086,7 +1633,7 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||
unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out,
|
||||
c_adler, u_adler, false, szb_info);
|
||||
}
|
||||
if (total_out != orig_file_size) { // non-PT_LOAD stuff
|
||||
if (total_out != orig_file_size) { // non-PT_LOAD32 stuff
|
||||
if (fo)
|
||||
fo->seek(0, SEEK_END);
|
||||
unpackExtent(orig_file_size - total_out, fo, total_in, total_out,
|
||||
|
|
164
src/p_lx_elf.h
164
src/p_lx_elf.h
|
@ -31,15 +31,51 @@
|
|||
#define __UPX_P_LX_ELF_H
|
||||
|
||||
|
||||
class PackLinuxElf32 : public PackUnix
|
||||
class PackLinuxElf : public PackUnix
|
||||
{
|
||||
typedef PackUnix super;
|
||||
public:
|
||||
PackLinuxElf32(InputFile *f);
|
||||
virtual ~PackLinuxElf32();
|
||||
PackLinuxElf(InputFile *f);
|
||||
virtual ~PackLinuxElf();
|
||||
/*virtual int buildLoader(const Filter *);*/
|
||||
virtual bool canUnpackVersion(int version) const { return (version >= 11); }
|
||||
|
||||
protected:
|
||||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
|
||||
// All other virtual functions in this class must be pure virtual
|
||||
// because they depend on Elf32 or Elf64 data structures, which differ.
|
||||
|
||||
virtual void pack1(OutputFile *, Filter &) = 0; // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &) = 0; // append compressed data
|
||||
//virtual void pack3(OutputFile *, Filter &) = 0; // append loader
|
||||
virtual void pack4(OutputFile *, Filter &) = 0; // append pack header
|
||||
|
||||
virtual void generateElfHdr(
|
||||
OutputFile *,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
) = 0;
|
||||
virtual int buildLinuxLoader(
|
||||
upx_byte const *const proto, // assembly-only sections
|
||||
unsigned const szproto,
|
||||
upx_byte const *const fold, // linked assembly + C section
|
||||
unsigned const szfold,
|
||||
Filter const *ft
|
||||
) = 0;
|
||||
virtual void unpack(OutputFile *fo) = 0;
|
||||
|
||||
protected:
|
||||
unsigned sz_phdrs; // sizeof Phdr[]
|
||||
unsigned sz_elf_hdrs; // all Elf headers
|
||||
};
|
||||
|
||||
class PackLinuxElf32 : public PackLinuxElf
|
||||
{
|
||||
typedef PackLinuxElf super;
|
||||
public:
|
||||
PackLinuxElf32(InputFile *f);
|
||||
virtual ~PackLinuxElf32();
|
||||
protected:
|
||||
virtual int checkEhdr(
|
||||
Elf32_Ehdr const *ehdr,
|
||||
|
@ -47,35 +83,24 @@ protected:
|
|||
unsigned char ei_class,
|
||||
unsigned char ei_data) const;
|
||||
|
||||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
|
||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||
//virtual void pack3(OutputFile *, Filter &); // append loader
|
||||
virtual void pack4(OutputFile *, Filter &); // append pack header
|
||||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual off_t getbrk(const Elf32_Phdr *phdr, int e_phnum) const;
|
||||
virtual void generateElfHdr(
|
||||
OutputFile *,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
);
|
||||
virtual int buildLinuxLoader(
|
||||
upx_byte const *const proto, // assembly-only sections
|
||||
unsigned const szproto,
|
||||
upx_byte const *const fold, // linked assembly + C section
|
||||
unsigned const szfold,
|
||||
Filter const *ft
|
||||
);
|
||||
virtual off_t getbrk(const Elf32_Phdr *phdr, int e_phnum) const;
|
||||
virtual void patchLoader();
|
||||
virtual void updateLoader(OutputFile *fo);
|
||||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
protected:
|
||||
Elf32_Ehdr ehdri; // from input file
|
||||
Elf32_Phdr *phdri; // for input file
|
||||
unsigned sz_phdrs; // sizeof Phdr[]
|
||||
unsigned sz_elf_hdrs; // all Elf headers
|
||||
|
||||
struct cprElfHdr1 {
|
||||
Elf32_Ehdr ehdr;
|
||||
|
@ -101,18 +126,125 @@ protected:
|
|||
cprElfHdr3 elfout;
|
||||
};
|
||||
|
||||
|
||||
class PackLinuxElf64 : public PackLinuxElf
|
||||
{
|
||||
typedef PackLinuxElf super;
|
||||
public:
|
||||
PackLinuxElf64(InputFile *f);
|
||||
virtual ~PackLinuxElf64();
|
||||
/*virtual int buildLoader(const Filter *);*/
|
||||
|
||||
protected:
|
||||
virtual int checkEhdr(
|
||||
Elf64_Ehdr const *ehdr,
|
||||
unsigned char e_machine,
|
||||
unsigned char ei_class,
|
||||
unsigned char ei_data) const;
|
||||
|
||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||
//virtual void pack3(OutputFile *, Filter &); // append loader
|
||||
virtual void pack4(OutputFile *, Filter &); // append pack header
|
||||
virtual void unpack(OutputFile *fo);
|
||||
|
||||
virtual void generateElfHdr(
|
||||
OutputFile *,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
);
|
||||
virtual off_t getbrk(const Elf64_Phdr *phdr, int e_phnum) const;
|
||||
virtual void patchLoader();
|
||||
virtual void updateLoader(OutputFile *fo);
|
||||
|
||||
protected:
|
||||
Elf64_Ehdr ehdri; // from input file
|
||||
Elf64_Phdr *phdri; // for input file
|
||||
|
||||
struct cprElfHdr1 {
|
||||
Elf64_Ehdr ehdr;
|
||||
Elf64_Phdr phdr[1];
|
||||
l_info linfo;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct cprElfHdr2 {
|
||||
Elf64_Ehdr ehdr;
|
||||
Elf64_Phdr phdr[2];
|
||||
l_info linfo;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct cprElfHdr3 {
|
||||
Elf64_Ehdr ehdr;
|
||||
Elf64_Phdr phdr[3];
|
||||
l_info linfo;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
cprElfHdr3 elfout;
|
||||
};
|
||||
|
||||
class PackLinuxElf32Be : public PackLinuxElf32
|
||||
{
|
||||
typedef PackLinuxElf32 super;
|
||||
protected:
|
||||
PackLinuxElf32Be(InputFile *f) : super(f) { }
|
||||
|
||||
virtual acc_uint64l_t get_native64(const void *b) const { return get_be64(b); }
|
||||
virtual unsigned get_native32(const void *b) const { return get_be32(b); }
|
||||
virtual unsigned get_native16(const void *b) const { return get_be16(b); }
|
||||
virtual void set_native64(void *b, acc_uint64l_t v) const { set_be64(b, v); }
|
||||
virtual void set_native32(void *b, unsigned v) const { set_be32(b, v); }
|
||||
virtual void set_native16(void *b, unsigned v) const { set_be16(b, v); }
|
||||
};
|
||||
|
||||
class PackLinuxElf64Le : public PackLinuxElf64
|
||||
{
|
||||
typedef PackLinuxElf64 super;
|
||||
protected:
|
||||
PackLinuxElf64Le(InputFile *f) : super(f) { }
|
||||
|
||||
virtual acc_uint64l_t get_native64(const void *b) const { return get_le64(b); }
|
||||
virtual unsigned get_native32(const void *b) const { return get_le32(b); }
|
||||
virtual unsigned get_native16(const void *b) const { return get_le16(b); }
|
||||
virtual void set_native64(void *b, unsigned long long v) const { set_le64(b, v); }
|
||||
virtual void set_native32(void *b, unsigned v) const { set_le32(b, v); }
|
||||
virtual void set_native16(void *b, unsigned v) const { set_le16(b, v); }
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// linux/elf64amd
|
||||
**************************************************************************/
|
||||
|
||||
class PackLinuxElf64amd : public PackLinuxElf64Le
|
||||
{
|
||||
typedef PackLinuxElf64Le super;
|
||||
public:
|
||||
PackLinuxElf64amd(InputFile *f);
|
||||
virtual ~PackLinuxElf64amd();
|
||||
virtual int getFormat() const { return UPX_F_LINUX_ELF64_AMD; }
|
||||
virtual const char *getName() const { return "linux/ElfAMD"; }
|
||||
virtual const int *getFilters() const;
|
||||
virtual bool canPack();
|
||||
protected:
|
||||
virtual void pack3(OutputFile *, Filter &); // append loader
|
||||
virtual const int *getCompressionMethods(int method, int level) const;
|
||||
virtual int buildLinuxLoader(
|
||||
upx_byte const *const proto, // assembly-only sections
|
||||
unsigned const szproto,
|
||||
upx_byte const *const fold, // linked assembly + C section
|
||||
unsigned const szfold,
|
||||
Filter const *ft
|
||||
);
|
||||
virtual int buildLoader(const Filter *);
|
||||
virtual void generateElfHdr(
|
||||
OutputFile *,
|
||||
void const *proto,
|
||||
unsigned const brka
|
||||
);
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// linux/elf32ppc
|
||||
**************************************************************************/
|
||||
|
|
|
@ -215,6 +215,8 @@ static Packer* try_packers(InputFile *f, try_function func)
|
|||
if ((p = func(new PackLinuxI386interp(f),f)) != NULL)
|
||||
return p;
|
||||
}
|
||||
if ((p = func(new PackLinuxElf64amd(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackLinuxElf32ppc(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackLinuxI386elf(f),f)) != NULL)
|
||||
|
|
Loading…
Reference in New Issue
Block a user