mirror of
https://github.com/upx/upx.git
synced 2024-11-23 04:39:59 +00:00
PT_MIPS_ABIFLAGS, compression side only, 32-bit only
modified: p_elf_enum.h modified: p_lx_elf.cpp modified: p_lx_elf.h
This commit is contained in:
parent
3c294d9721
commit
72ccca9faf
@ -103,6 +103,11 @@ class Dummy {
|
|||||||
PT_NUM = 8, /* Number of defined types in low range */
|
PT_NUM = 8, /* Number of defined types in low range */
|
||||||
PT_GNU_STACK = 0x6474e551, /* Indicates stack executability */
|
PT_GNU_STACK = 0x6474e551, /* Indicates stack executability */
|
||||||
PT_GNU_RELRO = 0x6474e552, /* Read-only after relocation */
|
PT_GNU_RELRO = 0x6474e552, /* Read-only after relocation */
|
||||||
|
PT_MIPS_REGINFO = 0x70000000,
|
||||||
|
/* Register usage information. */ //
|
||||||
|
// PT_MIPS_RTPROC = 0x70000001, /* Runtime procedure table. */
|
||||||
|
// PT_MIPS_OPTIONS = 0x70000002,
|
||||||
|
PT_MIPS_ABIFLAGS = 0x70000003, /* FP mode requirement. */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { // p_flags
|
enum { // p_flags
|
||||||
|
128
src/p_lx_elf.cpp
128
src/p_lx_elf.cpp
@ -307,7 +307,8 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sz_phdrs = e_phnum * e_phentsize;
|
sz_phdrs = e_phnum * e_phentsize;
|
||||||
sz_elf_hdrs = sz_phdrs + sizeof(Elf32_Ehdr);
|
sz_elf_hdrs = sz_phdrs + sizeof(Elf32_Ehdr) +
|
||||||
|
n_phdrx * sizeof(Elf32_Phdr); // phdrx bodies later: ::generateElfHdr
|
||||||
|
|
||||||
if (f && Elf32_Ehdr::ET_DYN!=e_type) {
|
if (f && Elf32_Ehdr::ET_DYN!=e_type) {
|
||||||
unsigned const len = file_size; // (sz_phdrs + e_phoff) except --preserve-build-id
|
unsigned const len = file_size; // (sz_phdrs + e_phoff) except --preserve-build-id
|
||||||
@ -952,7 +953,7 @@ void PackLinuxElf64::defineSymbols(Filter const *ft)
|
|||||||
|
|
||||||
PackLinuxElf32::PackLinuxElf32(InputFile *f)
|
PackLinuxElf32::PackLinuxElf32(InputFile *f)
|
||||||
: super(f), phdri(nullptr), shdri(nullptr),
|
: super(f), phdri(nullptr), shdri(nullptr),
|
||||||
gnu_stack(nullptr),
|
gnu_stack(nullptr), n_phdrx(0), sz_phdrx(0),
|
||||||
page_mask(~0u<<lg2_page),
|
page_mask(~0u<<lg2_page),
|
||||||
dynseg(nullptr), hashtab(nullptr), hashend(nullptr),
|
dynseg(nullptr), hashtab(nullptr), hashend(nullptr),
|
||||||
gashtab(nullptr), gashend(nullptr), dynsym(nullptr),
|
gashtab(nullptr), gashend(nullptr), dynsym(nullptr),
|
||||||
@ -974,7 +975,7 @@ PackLinuxElf32::~PackLinuxElf32()
|
|||||||
|
|
||||||
PackLinuxElf64::PackLinuxElf64(InputFile *f)
|
PackLinuxElf64::PackLinuxElf64(InputFile *f)
|
||||||
: super(f), phdri(nullptr), shdri(nullptr),
|
: super(f), phdri(nullptr), shdri(nullptr),
|
||||||
gnu_stack(nullptr),
|
gnu_stack(nullptr), n_phdrx(0), sz_phdrx(0),
|
||||||
page_mask(~0ull<<lg2_page),
|
page_mask(~0ull<<lg2_page),
|
||||||
dynseg(nullptr), hashtab(nullptr), hashend(nullptr),
|
dynseg(nullptr), hashtab(nullptr), hashend(nullptr),
|
||||||
gashtab(nullptr), gashend(nullptr), dynsym(nullptr),
|
gashtab(nullptr), gashend(nullptr), dynsym(nullptr),
|
||||||
@ -1032,7 +1033,8 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sz_phdrs = e_phnum * e_phentsize;
|
sz_phdrs = e_phnum * e_phentsize;
|
||||||
sz_elf_hdrs = sz_phdrs + sizeof(Elf64_Ehdr);
|
sz_elf_hdrs = sz_phdrs + sizeof(Elf64_Ehdr) +
|
||||||
|
n_phdrx * sizeof(Elf32_Phdr); // phdrx bodies later: ::generateElfHdr
|
||||||
|
|
||||||
if (f && Elf64_Ehdr::ET_DYN!=e_type) {
|
if (f && Elf64_Ehdr::ET_DYN!=e_type) {
|
||||||
unsigned const len = file_size; // (sz_phdrs + e_phoff) except --preserve-build-id
|
unsigned const len = file_size; // (sz_phdrs + e_phoff) except --preserve-build-id
|
||||||
@ -2493,6 +2495,25 @@ PackLinuxElf32::canPackOSABI(Elf32_Ehdr const *ehdr)
|
|||||||
}
|
}
|
||||||
hatch_off = ~3u & (3+ get_te32(&phdr->p_memsz));
|
hatch_off = ~3u & (3+ get_te32(&phdr->p_memsz));
|
||||||
}
|
}
|
||||||
|
if (PT_GNU_STACK32 == p_type) {
|
||||||
|
if (END_PHDRX <= n_phdrx) {
|
||||||
|
throwCantPack("too many Phdr %u", (unsigned)(phdr - phdri));
|
||||||
|
}
|
||||||
|
phdrx[n_phdrx++] = phdr;
|
||||||
|
}
|
||||||
|
if (EM_MIPS == e_machine
|
||||||
|
&& (Elf32_Phdr::PT_MIPS_ABIFLAGS == p_type
|
||||||
|
|| Elf32_Phdr::PT_MIPS_REGINFO == p_type)
|
||||||
|
) {
|
||||||
|
if (END_PHDRX <= n_phdrx) {
|
||||||
|
throwCantPack("too many Phdr %u", (unsigned)(phdr - phdri));
|
||||||
|
}
|
||||||
|
phdrx[n_phdrx++] = phdr;
|
||||||
|
unsigned mask = -1+ get_te32(&phdr->p_align);
|
||||||
|
sz_phdrx = ~mask & (mask + sz_phdrx);
|
||||||
|
sz_phdrx += get_te32(&phdr->p_memsz);
|
||||||
|
|
||||||
|
}
|
||||||
if (PT_NOTE32 == p_type) {
|
if (PT_NOTE32 == p_type) {
|
||||||
unsigned const x = get_te32(&phdr->p_memsz);
|
unsigned const x = get_te32(&phdr->p_memsz);
|
||||||
if ( sizeof(elfout.notes) < x // beware overflow of note_size
|
if ( sizeof(elfout.notes) < x // beware overflow of note_size
|
||||||
@ -3474,7 +3495,9 @@ PackLinuxElf32::generateElfHdr(
|
|||||||
h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr;
|
h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr;
|
||||||
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
|
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
|
||||||
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
|
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
|
||||||
memset(&h3->linfo, 0, sizeof(h3->linfo));
|
if (3 <= get_te16(&h3->ehdr.e_phnum)) {
|
||||||
|
phdrx[n_phdrx++] = &((cprElfHdr3 const *)proto)->phdr[2]; // probably PT_GNU_STACK
|
||||||
|
}
|
||||||
|
|
||||||
h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC)
|
h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC)
|
||||||
h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = ei_osabi;
|
h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = ei_osabi;
|
||||||
@ -3483,13 +3506,14 @@ PackLinuxElf32::generateElfHdr(
|
|||||||
h3->ehdr.e_flags = ehdri.e_flags;
|
h3->ehdr.e_flags = ehdri.e_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned const phnum_i = get_te16(&h2->ehdr.e_phnum);
|
if (ph.format != getFormat()) {
|
||||||
unsigned phnum_o = phnum_i;
|
assert(false); // unknown ph.format, PackLinuxElf32
|
||||||
|
}
|
||||||
assert(get_te32(&h2->ehdr.e_phoff) == sizeof(Elf32_Ehdr));
|
assert(get_te32(&h2->ehdr.e_phoff) == sizeof(Elf32_Ehdr));
|
||||||
h2->ehdr.e_shoff = 0;
|
|
||||||
assert(get_te16(&h2->ehdr.e_ehsize) == sizeof(Elf32_Ehdr));
|
assert(get_te16(&h2->ehdr.e_ehsize) == sizeof(Elf32_Ehdr));
|
||||||
assert(get_te16(&h2->ehdr.e_phentsize) == sizeof(Elf32_Phdr));
|
assert(get_te16(&h2->ehdr.e_phentsize) == sizeof(Elf32_Phdr));
|
||||||
|
|
||||||
|
h2->ehdr.e_shoff = 0;
|
||||||
if (o_elf_shnum) {
|
if (o_elf_shnum) {
|
||||||
set_te16(&h2->ehdr.e_shentsize, sizeof(Elf32_Shdr));
|
set_te16(&h2->ehdr.e_shentsize, sizeof(Elf32_Shdr));
|
||||||
h2->ehdr.e_shnum = o_elf_shnum;
|
h2->ehdr.e_shnum = o_elf_shnum;
|
||||||
@ -3504,22 +3528,12 @@ PackLinuxElf32::generateElfHdr(
|
|||||||
h2->ehdr.e_shstrndx = 0;
|
h2->ehdr.e_shstrndx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sz_elf_hdrs = sizeof(*h2) - sizeof(linfo); // default
|
unsigned phnum_o = 2 + n_phdrx; // C_BASE, C_TEXT
|
||||||
if (gnu_stack) {
|
set_te16(&h2->ehdr.e_phnum, phnum_o);
|
||||||
sz_elf_hdrs += sizeof(Elf32_Phdr);
|
|
||||||
memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack));
|
|
||||||
set_te16(&h2->ehdr.e_phnum, phnum_o);
|
|
||||||
}
|
|
||||||
o_binfo = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr)*phnum_o + sizeof(l_info) + sizeof(p_info);
|
|
||||||
set_te32(&h2->phdr[C_TEXT].p_filesz, sizeof(*h2)); // + identsize;
|
set_te32(&h2->phdr[C_TEXT].p_filesz, sizeof(*h2)); // + identsize;
|
||||||
h2->phdr[C_TEXT].p_memsz = h2->phdr[C_TEXT].p_filesz;
|
h2->phdr[C_TEXT].p_memsz = h2->phdr[C_TEXT].p_filesz;
|
||||||
|
|
||||||
for (unsigned j=0; j < phnum_i; ++j) {
|
|
||||||
if (is_LOAD32(&h3->phdr[j])) {
|
|
||||||
set_te32(&h3->phdr[j].p_align, page_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info for OS kernel to set the brk()
|
// Info for OS kernel to set the brk()
|
||||||
if (brka) {
|
if (brka) {
|
||||||
// linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary
|
// linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary
|
||||||
@ -3541,21 +3555,49 @@ PackLinuxElf32::generateElfHdr(
|
|||||||
set_te32(&h2->phdr[C_BASE].p_memsz, brka - lo_va_user);
|
set_te32(&h2->phdr[C_BASE].p_memsz, brka - lo_va_user);
|
||||||
set_te32(&h2->phdr[C_BASE].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W);
|
set_te32(&h2->phdr[C_BASE].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W);
|
||||||
}
|
}
|
||||||
if (ph.format==getFormat()) {
|
set_te32(&h3->phdr[C_BASE].p_align, page_size);
|
||||||
assert((2u+ !!gnu_stack) == phnum_o);
|
set_te32(&h3->phdr[C_TEXT].p_align, page_size);
|
||||||
set_te32(&h2->phdr[C_TEXT].p_flags, ~Elf32_Phdr::PF_W & get_te32(&h2->phdr[C_TEXT].p_flags));
|
set_te32(&h2->phdr[C_TEXT].p_flags, ~Elf32_Phdr::PF_W & get_te32(&h2->phdr[C_TEXT].p_flags));
|
||||||
if (!gnu_stack) {
|
fo->write(h2, sizeof(Elf32_Ehdr) + 2* sizeof(Elf32_Phdr)); // C_BASE, C_TEXT
|
||||||
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
|
||||||
fo->write(h2, sizeof(*h2));
|
u64_t const zero_pad = 0;
|
||||||
}
|
unsigned uva0 = get_te32(&h2->phdr[C_TEXT].p_vaddr);
|
||||||
else {
|
unsigned off_o = 0;
|
||||||
memset(&h3->linfo, 0, sizeof(h3->linfo));
|
for (unsigned phase = 0; phase < 2; ++phase) { // 0: Phdrs; 1: bodies
|
||||||
fo->write(h3, sizeof(*h3));
|
off_o = sizeof(Elf32_Ehdr) + phnum_o * sizeof(Elf32_Phdr);
|
||||||
|
for (unsigned j = 0; j < n_phdrx; ++j) {
|
||||||
|
Elf32_Phdr phtmp = *phdrx[j];
|
||||||
|
phtmp.p_vaddr = phtmp.p_paddr = 0;
|
||||||
|
unsigned const off_i = get_te32(&phtmp.p_offset);
|
||||||
|
unsigned const memsz = get_te32(&phtmp.p_memsz);
|
||||||
|
unsigned pad = 0;
|
||||||
|
if (memsz) { // align
|
||||||
|
unsigned alm1 = -1 + umin(8u, get_te32(&phtmp.p_align));
|
||||||
|
pad = alm1 & -off_o;
|
||||||
|
off_o += pad;
|
||||||
|
set_te32(&phtmp.p_vaddr, off_o + uva0); phtmp.p_paddr = phtmp.p_vaddr;
|
||||||
|
}
|
||||||
|
if (0==phase) {
|
||||||
|
set_te32(&phtmp.p_offset, (memsz ? off_o : 0));
|
||||||
|
fo->write(&phtmp, sizeof(phtmp)); // Phdr
|
||||||
|
}
|
||||||
|
if (1==phase) {
|
||||||
|
if (pad) fo->write(&zero_pad, pad);
|
||||||
|
if (memsz) fo->write(&file_image[off_i], memsz); // body
|
||||||
|
}
|
||||||
|
off_o += memsz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
off_o = fpad4(fo, off_o);
|
||||||
assert(false); // unknown ph.format, PackLinuxElf32
|
sz_phdrx = off_o - (sizeof(Elf32_Ehdr) + phnum_o * sizeof(Elf32_Phdr));
|
||||||
}
|
set_te32(&h2->phdr[C_BASE].p_filesz, off_o);
|
||||||
|
|
||||||
|
sz_elf_hdrs = sizeof(Elf32_Ehdr) + phnum_o * sizeof(Elf32_Phdr)
|
||||||
|
+ sz_phdrx + sizeof(l_info);
|
||||||
|
o_binfo = sz_elf_hdrs + sizeof(p_info);
|
||||||
|
|
||||||
|
l_info tmp; memset(&tmp, 0, sizeof(tmp));
|
||||||
|
fo->write(&tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -5135,6 +5177,8 @@ int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||||||
fi->seek(x.size + x.offset, SEEK_SET);
|
fi->seek(x.size + x.offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
if (hdr_u_len) { // first time
|
if (hdr_u_len) { // first time
|
||||||
|
fo->seek(sz_phdrx, SEEK_CUR);
|
||||||
|
|
||||||
linfo.l_checksum = 0; // preliminary
|
linfo.l_checksum = 0; // preliminary
|
||||||
linfo.l_magic = UPX_MAGIC_LE32;
|
linfo.l_magic = UPX_MAGIC_LE32;
|
||||||
set_le16(&linfo.l_lsize, lsize); // preliminary (0)
|
set_le16(&linfo.l_lsize, lsize); // preliminary (0)
|
||||||
@ -6099,17 +6143,9 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
|
|||||||
set_te32(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
|
set_te32(&eho->phdr[C_TEXT].p_filesz, sz_pack2 + lsize);
|
||||||
eho->phdr[C_TEXT].p_memsz = eho->phdr[C_TEXT].p_filesz;
|
eho->phdr[C_TEXT].p_memsz = eho->phdr[C_TEXT].p_filesz;
|
||||||
|
|
||||||
Elf32_Phdr *phdr = &eho->phdr[C_NOTE];
|
fo->seek(0, SEEK_SET);
|
||||||
if (PT_NOTE32== get_te32(&phdr->p_type)) {
|
fo->rewrite(&eho->ehdr, sizeof(Elf32_Ehdr) + 2* sizeof(Elf32_Phdr)); // C_BASE, C_TEXT
|
||||||
upx_uint32_t const reloc = get_te32(&eho->phdr[C_TEXT].p_vaddr);
|
// fo->rewrite(&linfo, sizeof(linfo)); // FIXME: need? SEEK ?
|
||||||
set_te32( &phdr->p_vaddr,
|
|
||||||
reloc + get_te32(&phdr->p_vaddr));
|
|
||||||
set_te32( &phdr->p_paddr,
|
|
||||||
reloc + get_te32(&phdr->p_paddr));
|
|
||||||
// FIXME fo->rewrite(&elfnote, sizeof(elfnote));
|
|
||||||
}
|
|
||||||
fo->rewrite(eho, sz_elf_hdrs);
|
|
||||||
fo->rewrite(&linfo, sizeof(linfo));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +224,10 @@ protected:
|
|||||||
Elf32_Shdr *shdri; // from input file
|
Elf32_Shdr *shdri; // from input file
|
||||||
Elf32_Shdr *shdro; // for output file
|
Elf32_Shdr *shdro; // for output file
|
||||||
Elf32_Phdr const *gnu_stack; // propagate NX
|
Elf32_Phdr const *gnu_stack; // propagate NX
|
||||||
|
static unsigned const END_PHDRX = 4;
|
||||||
|
Elf32_Phdr const *phdrx[END_PHDRX]; // "extra" arch-specific Phdr
|
||||||
|
unsigned n_phdrx; // number actually used
|
||||||
|
unsigned sz_phdrx; // total size of bodies
|
||||||
unsigned e_phoff;
|
unsigned e_phoff;
|
||||||
unsigned e_shoff;
|
unsigned e_shoff;
|
||||||
unsigned sz_dynseg; // PT_DYNAMIC.p_memsz
|
unsigned sz_dynseg; // PT_DYNAMIC.p_memsz
|
||||||
@ -385,6 +389,10 @@ protected:
|
|||||||
Elf64_Shdr *shdri; // from input file
|
Elf64_Shdr *shdri; // from input file
|
||||||
Elf64_Shdr *shdro; // for output file
|
Elf64_Shdr *shdro; // for output file
|
||||||
Elf64_Phdr const *gnu_stack; // propagate NX
|
Elf64_Phdr const *gnu_stack; // propagate NX
|
||||||
|
static unsigned const END_PHDRX = 4;
|
||||||
|
Elf64_Phdr const *phdrx[END_PHDRX]; // "extra" arch-specific Phdr
|
||||||
|
unsigned n_phdrx; // number actually used
|
||||||
|
unsigned sz_phdrx; // total size of bodies
|
||||||
upx_uint64_t e_phoff;
|
upx_uint64_t e_phoff;
|
||||||
upx_uint64_t e_shoff;
|
upx_uint64_t e_shoff;
|
||||||
upx_uint64_t sz_dynseg; // PT_DYNAMIC.p_memsz
|
upx_uint64_t sz_dynseg; // PT_DYNAMIC.p_memsz
|
||||||
|
Loading…
Reference in New Issue
Block a user