mirror of
https://github.com/upx/upx
synced 2025-10-26 23:36:41 +08:00
Merge branch 'jreiser' into devel
O_BINFO simplifies stubs on linux Elf;
PowerPC64 (big endian: Apple Macintosh G5) and PowerPC* cleanup;
-fpie simplification; shlib for arm64, amd64.
A big merge due to suspending activity on 'devel' branch
during stabilization for release of UPX-3.94.
There were intermediate merges with private branch 'jreiser',
and attempted rebase onto 'devel' did not go well.
Verfication of cases ({ET_EXEC, -fpie, shlib} x {$ARCH}) is in progress.
modified: ../.github/travis_testsuite_1.sh
modified: conf.h
modified: linker.cpp
modified: linker.h
modified: p_lx_elf.cpp
modified: p_lx_elf.h
modified: p_mach.cpp
modified: p_mach.h
modified: p_mach_enum.h
modified: packmast.cpp
modified: stub/Makefile
modified: stub/scripts/xstrip.py
modified: stub/src/amd64-darwin.dylib-entry.S
modified: stub/src/amd64-darwin.macho-entry.S
modified: stub/src/amd64-linux.elf-entry.S
modified: stub/src/amd64-linux.elf-fold.S
modified: stub/src/amd64-linux.elf-main.c
modified: stub/src/arch/powerpc/32/bxx.S
modified: stub/src/arch/powerpc/32/lzma_d.S
modified: stub/src/arch/powerpc/32/nrv2b_d.S
modified: stub/src/arch/powerpc/32/nrv2d_d.S
modified: stub/src/arch/powerpc/32/nrv2e_d.S
modified: stub/src/arch/powerpc/32/ppc_regs.h
new file: stub/src/arch/powerpc/64/Makefile
new file: stub/src/arch/powerpc/64/Makefile.extra
new file: stub/src/arch/powerpc/64/bxx.S
new file: stub/src/arch/powerpc/64/lzma_d.S
new file: stub/src/arch/powerpc/64/lzma_d_cf.S
new file: stub/src/arch/powerpc/64/lzma_d_cs.S
new file: stub/src/arch/powerpc/64/macros.S
new file: stub/src/arch/powerpc/64/nrv2b_d.S
new file: stub/src/arch/powerpc/64/nrv2d_d.S
new file: stub/src/arch/powerpc/64/nrv2e_d.S
new file: stub/src/arch/powerpc/64/ppc_regs.h
modified: stub/src/arch/powerpc/64le/bxx.S
copied: stub/src/arch/powerpc/64le/lzma_d.S -> stub/src/arch/powerpc/64le/lzma_d-common.S
modified: stub/src/arch/powerpc/64le/lzma_d.S
modified: stub/src/arch/powerpc/64le/lzma_d_cs.S
modified: stub/src/arch/powerpc/64le/nrv2b_d.S
modified: stub/src/arch/powerpc/64le/nrv2d_d.S
modified: stub/src/arch/powerpc/64le/nrv2e_d.S
modified: stub/src/arch/powerpc/64le/ppc_regs.h
modified: stub/src/arm.v4a-linux.elf-entry.S
modified: stub/src/arm.v4a-linux.elf-fold.S
modified: stub/src/arm64-darwin.macho-entry.S
modified: stub/src/arm64-linux.elf-entry.S
modified: stub/src/arm64-linux.elf-fold.S
modified: stub/src/arm64-linux.shlib-init.S
modified: stub/src/i386-bsd.elf-entry.S
modified: stub/src/i386-darwin.macho-entry.S
modified: stub/src/i386-linux.elf-entry.S
modified: stub/src/i386-linux.elf-fold.S
modified: stub/src/mipsel.r3000-linux.elf-entry.S
modified: stub/src/mipsel.r3000-linux.elf-fold.S
modified: stub/src/powerpc-darwin.dylib-entry.S
modified: stub/src/powerpc-darwin.macho-entry.S
modified: stub/src/powerpc-darwin.macho-fold.S
modified: stub/src/powerpc-linux.elf-entry.S
modified: stub/src/powerpc-linux.elf-fold.S
modified: stub/src/powerpc-linux.elf-main.c
new file: stub/src/powerpc64-darwin.dylib-entry.S
new file: stub/src/powerpc64-darwin.macho-entry.S
new file: stub/src/powerpc64-darwin.macho-fold.S
new file: stub/src/powerpc64-darwin.macho-main.c
new file: stub/src/powerpc64-linux.elf-entry.S
new file: stub/src/powerpc64-linux.elf-fold.S
new file: stub/src/powerpc64-linux.elf-fold.lds
new file: stub/src/powerpc64-linux.elf-main.c
modified: stub/src/powerpc64-savegpr0.S
modified: stub/src/powerpc64le-darwin.dylib-entry.S
modified: stub/src/powerpc64le-darwin.macho-entry.S
modified: stub/src/powerpc64le-darwin.macho-fold.S
modified: stub/src/powerpc64le-linux.elf-entry.S
modified: stub/src/powerpc64le-linux.elf-fold.S
modified: stub/src/powerpc64le-linux.elf-main.c
and most stub/*.h and stub/tmp/*.dump
This commit is contained in:
624
src/p_lx_elf.cpp
624
src/p_lx_elf.cpp
@@ -216,7 +216,7 @@ PackLinuxElf64::checkEhdr(Elf64_Ehdr const *ehdr) const
|
||||
PackLinuxElf::PackLinuxElf(InputFile *f)
|
||||
: super(f), e_phnum(0), dynstr(NULL),
|
||||
sz_phdrs(0), sz_elf_hdrs(0), sz_pack2(0), sz_pack2a(0),
|
||||
lg2_page(12), page_size(1u<<lg2_page), is_big(0),
|
||||
lg2_page(12), page_size(1u<<lg2_page), is_big(0), is_pie(0),
|
||||
xct_off(0), xct_va(0), jni_onload_va(0),
|
||||
e_machine(0), ei_class(0), ei_data(0), ei_osabi(0), osabi_note(NULL),
|
||||
o_elf_shnum(0)
|
||||
@@ -526,7 +526,7 @@ PackLinuxElf::addStubEntrySections(Filter const *)
|
||||
if (hasLoaderSection("ELFMAINXu")) {
|
||||
// brk() trouble if static
|
||||
all_pages |= (Elf32_Ehdr::EM_ARM==e_machine && 0x8000==load_va);
|
||||
addLoader((all_pages ? "LUNMP000" : "LUNMP001"), "ELFMAINXu", NULL);
|
||||
addLoader("ELFMAINXu", NULL);
|
||||
}
|
||||
//addLoader(getDecompressorSections(), NULL);
|
||||
addLoader(
|
||||
@@ -537,9 +537,13 @@ PackLinuxElf::addStubEntrySections(Filter const *)
|
||||
: NULL), NULL);
|
||||
if (hasLoaderSection("CFLUSH"))
|
||||
addLoader("CFLUSH");
|
||||
addLoader("ELFMAINY,IDENTSTR,+40,ELFMAINZ", NULL);
|
||||
addLoader("ELFMAINY,IDENTSTR", NULL);
|
||||
if (hasLoaderSection("ELFMAINZe")) { // ppc64 big-endian only
|
||||
addLoader("ELFMAINZe", NULL);
|
||||
}
|
||||
addLoader("+40,ELFMAINZ", NULL);
|
||||
if (hasLoaderSection("ELFMAINZu")) {
|
||||
addLoader((all_pages ? "LUNMP000" : "LUNMP001"), "ELFMAINZu", NULL);
|
||||
addLoader("ELFMAINZu", NULL);
|
||||
}
|
||||
addLoader("FOLDEXEC", NULL);
|
||||
}
|
||||
@@ -547,7 +551,67 @@ PackLinuxElf::addStubEntrySections(Filter const *)
|
||||
|
||||
void PackLinuxElf::defineSymbols(Filter const *)
|
||||
{
|
||||
// empty
|
||||
linker->defineSymbol("O_BINFO", o_binfo);
|
||||
}
|
||||
|
||||
void PackLinuxElf32::defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf::defineSymbols(ft);
|
||||
|
||||
// We want to know if compressed data, plus stub, plus a couple pages,
|
||||
// will fit below the uncompressed program in memory. But we don't
|
||||
// know the final total compressed size yet, so use the uncompressed
|
||||
// size (total over all PT_LOAD32) as an upper bound.
|
||||
unsigned len = 0; // XXX: 4GB
|
||||
upx_uint32_t lo_va_user = ~0u; // infinity
|
||||
for (int j= e_phnum; --j>=0; ) {
|
||||
if (PT_LOAD32 == get_te32(&phdri[j].p_type)) {
|
||||
len += (unsigned)get_te32(&phdri[j].p_filesz);
|
||||
upx_uint32_t const va = get_te32(&phdri[j].p_vaddr);
|
||||
if (va < lo_va_user) {
|
||||
lo_va_user = va;
|
||||
}
|
||||
}
|
||||
}
|
||||
lsize = /*getLoaderSize()*/ 64 * 1024; // XXX: upper bound; avoid circularity
|
||||
upx_uint32_t lo_va_stub = get_te32(&elfout.phdr[0].p_vaddr);
|
||||
upx_uint32_t adrm;
|
||||
unsigned lenm;
|
||||
unsigned lenu;
|
||||
len += (7&-lsize) + lsize;
|
||||
upx_uint32_t my_page_size = 4096u;
|
||||
upx_uint32_t my_page_mask = -my_page_size;
|
||||
is_big = (lo_va_user < (lo_va_stub + len + 2 * my_page_size));
|
||||
if (is_pie || (is_big /*&& ehdri.ET_EXEC==get_te16(&ehdri.e_type)*/)) {
|
||||
// .e_entry is set later by PackLinuxElf32::updateLoader
|
||||
set_te32( &elfout.ehdr.e_entry,
|
||||
get_te32(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub);
|
||||
set_te32(&elfout.phdr[0].p_vaddr, lo_va_user);
|
||||
set_te32(&elfout.phdr[0].p_paddr, lo_va_user);
|
||||
lo_va_stub = lo_va_user;
|
||||
adrm = getbrk(phdri, e_phnum) - lo_va_user;
|
||||
lenm = my_page_size + len;
|
||||
lenu = my_page_size + len;
|
||||
}
|
||||
else {
|
||||
adrm = len;
|
||||
lenm = my_page_size;
|
||||
lenu = my_page_size + len;
|
||||
}
|
||||
adrm = my_page_mask & (~my_page_mask + adrm); // round up to page boundary
|
||||
|
||||
if (Elf32_Ehdr::EM_PPC == e_machine) {
|
||||
linker->defineSymbol("LENU", lenu); // len for unmap
|
||||
linker->defineSymbol("LENM", lenm); // len for map
|
||||
linker->defineSymbol("ADRM", adrm); // offset from &Elf32_Ehdr
|
||||
}
|
||||
|
||||
//linker->dumpSymbols(); // debug
|
||||
}
|
||||
|
||||
void PackLinuxElf64::defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf::defineSymbols(ft);
|
||||
}
|
||||
|
||||
PackLinuxElf32::PackLinuxElf32(InputFile *f)
|
||||
@@ -697,6 +761,15 @@ PackLinuxElf64ppcle::getFilters() const
|
||||
return filters;
|
||||
}
|
||||
|
||||
int const *
|
||||
PackLinuxElf64ppc::getFilters() const
|
||||
{
|
||||
static const int filters[] = {
|
||||
0xd0,
|
||||
FT_END };
|
||||
return filters;
|
||||
}
|
||||
|
||||
int const *
|
||||
PackLinuxElf64amd::getFilters() const
|
||||
{
|
||||
@@ -752,15 +825,30 @@ void PackLinuxElf32mipseb::updateLoader(OutputFile *fo)
|
||||
|
||||
void PackLinuxElf32::updateLoader(OutputFile * /*fo*/)
|
||||
{
|
||||
set_te32(&elfout.ehdr.e_entry, sz_pack2 +
|
||||
get_te32(&elfout.phdr[0].p_vaddr));
|
||||
unsigned start = linker->getSymbolOffset("_start");
|
||||
unsigned vbase = get_te32(&elfout.phdr[0].p_vaddr);
|
||||
set_te32(&elfout.ehdr.e_entry, start + sz_pack2 + vbase);
|
||||
}
|
||||
|
||||
void PackLinuxElf64::updateLoader(OutputFile * /*fo*/)
|
||||
{
|
||||
set_te64(&elfout.ehdr.e_entry, sz_pack2 +
|
||||
linker->getSymbolOffset("_start") +
|
||||
get_te64(&elfout.phdr[0].p_vaddr));
|
||||
upx_uint64_t const vbase = get_te64(&elfout.phdr[0].p_vaddr);
|
||||
unsigned start = linker->getSymbolOffset("_start");
|
||||
|
||||
if (get_te16(&elfout.ehdr.e_machine)==Elf64_Ehdr::EM_PPC64
|
||||
&& elfout.ehdr.e_ident[Elf64_Ehdr::EI_DATA]==Elf64_Ehdr::ELFDATA2MSB) {
|
||||
unsigned descr = linker->getSymbolOffset("entry_descr");
|
||||
|
||||
// External relocation of PPC64 function descriptor.
|
||||
upx_uint64_t dot_entry = start + sz_pack2 + vbase;
|
||||
upx_byte *p = getLoader();
|
||||
|
||||
set_te64(&p[descr], dot_entry);
|
||||
set_te64(&elfout.ehdr.e_entry, descr + sz_pack2 + vbase);
|
||||
}
|
||||
else {
|
||||
set_te64(&elfout.ehdr.e_entry, start + sz_pack2 + vbase);
|
||||
}
|
||||
}
|
||||
|
||||
PackLinuxElf32ppc::PackLinuxElf32ppc(InputFile *f)
|
||||
@@ -790,15 +878,33 @@ PackLinuxElf64ppcle::PackLinuxElf64ppcle(InputFile *f)
|
||||
ei_osabi = Elf64_Ehdr::ELFOSABI_LINUX;
|
||||
}
|
||||
|
||||
PackLinuxElf64ppc::PackLinuxElf64ppc(InputFile *f)
|
||||
: super(f), lg2_page(16), page_size(1u<<lg2_page)
|
||||
{
|
||||
e_machine = Elf64_Ehdr::EM_PPC64;
|
||||
ei_class = Elf64_Ehdr::ELFCLASS64;
|
||||
ei_data = Elf64_Ehdr::ELFDATA2MSB;
|
||||
ei_osabi = Elf32_Ehdr::ELFOSABI_LINUX;
|
||||
}
|
||||
|
||||
PackLinuxElf64ppcle::~PackLinuxElf64ppcle()
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxElf64ppc::~PackLinuxElf64ppc()
|
||||
{
|
||||
}
|
||||
|
||||
Linker* PackLinuxElf64ppcle::newLinker() const
|
||||
{
|
||||
return new ElfLinkerPpc64le;
|
||||
}
|
||||
|
||||
Linker* PackLinuxElf64ppc::newLinker() const
|
||||
{
|
||||
return new ElfLinkerPpc64;
|
||||
}
|
||||
|
||||
PackLinuxElf64amd::PackLinuxElf64amd(InputFile *f)
|
||||
: super(f)
|
||||
{
|
||||
@@ -914,13 +1020,14 @@ void PackLinuxElf32x86::addStubEntrySections(Filter const *ft)
|
||||
if (Elf32_Ehdr::ET_DYN==get_te16(&ehdri.e_type)) {
|
||||
addLoader("LEXECDYN", NULL);
|
||||
}
|
||||
addLoader(((opt->o_unix.unmap_all_pages|is_big) ? "LUNMP000" : "LUNMP001"),
|
||||
"LEXEC025", NULL);
|
||||
addLoader("LEXEC025", NULL);
|
||||
addLoader("FOLDEXEC", NULL);
|
||||
}
|
||||
|
||||
void PackLinuxElf32x86::defineSymbols(Filter const *const ft)
|
||||
{
|
||||
PackLinuxElf32::defineSymbols(ft);
|
||||
|
||||
if (0x80==(ft->id & 0xF0)) {
|
||||
int const mru = ft->n_mru ? 1+ ft->n_mru : 0;
|
||||
if (mru && mru!=256) {
|
||||
@@ -1033,6 +1140,21 @@ PackLinuxElf64::buildLinuxLoader(
|
||||
if (r != UPX_E_OK || h.sz_cpr >= h.sz_unc)
|
||||
throwInternalError("loader compression failed");
|
||||
}
|
||||
#if 1 //{ debugging only
|
||||
if (M_IS_LZMA(ph.method)) {
|
||||
ucl_uint tmp_len = h.sz_unc; // LZMA uses this as EOF
|
||||
unsigned char *tmp = New(unsigned char, tmp_len);
|
||||
memset(tmp, 0, tmp_len);
|
||||
int r = upx_decompress(sizeof(h) + cprLoader, h.sz_cpr, tmp, &tmp_len, h.b_method, NULL);
|
||||
if (r == UPX_E_OUT_OF_MEMORY)
|
||||
throwOutOfMemoryException();
|
||||
printf("\n%d %d: %d %d %d\n", h.b_method, r, h.sz_cpr, h.sz_unc, tmp_len);
|
||||
for (unsigned j=0; j < h.sz_unc; ++j) if (tmp[j]!=uncLoader[j]) {
|
||||
printf("%d: %x %x\n", j, tmp[j], uncLoader[j]);
|
||||
}
|
||||
delete[] tmp;
|
||||
}
|
||||
#endif //}
|
||||
unsigned const sz_cpr = h.sz_cpr;
|
||||
set_te32(&h.sz_cpr, h.sz_cpr);
|
||||
set_te32(&h.sz_unc, h.sz_unc);
|
||||
@@ -1054,15 +1176,15 @@ PackLinuxElf64::buildLinuxLoader(
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf64amd::defineSymbols(Filter const *)
|
||||
PackLinuxElf64amd::defineSymbols(Filter const *ft)
|
||||
{
|
||||
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info);
|
||||
PackLinuxElf64::defineSymbols(ft);
|
||||
|
||||
// We want to know if compressed data, plus stub, plus a couple pages,
|
||||
// will fit below the uncompressed program in memory. But we don't
|
||||
// know the final total compressed size yet, so use the uncompressed
|
||||
// size (total over all PT_LOAD64) as an upper bound.
|
||||
unsigned len = 0;
|
||||
unsigned len = 0; // XXX: 4GB
|
||||
upx_uint64_t lo_va_user = ~0ull; // infinity
|
||||
for (int j= e_phnum; --j>=0; ) {
|
||||
if (PT_LOAD64 == get_te32(&phdri[j].p_type)) {
|
||||
@@ -1075,60 +1197,34 @@ PackLinuxElf64amd::defineSymbols(Filter const *)
|
||||
}
|
||||
lsize = /*getLoaderSize()*/ 64 * 1024; // XXX: upper bound; avoid circularity
|
||||
upx_uint64_t lo_va_stub = get_te64(&elfout.phdr[0].p_vaddr);
|
||||
upx_uint64_t adrc;
|
||||
upx_uint64_t adrm;
|
||||
upx_uint64_t adru;
|
||||
upx_uint64_t adrx;
|
||||
unsigned cntc;
|
||||
unsigned lenm;
|
||||
unsigned lenu;
|
||||
len += (7&-lsize) + lsize;
|
||||
is_big = (lo_va_user < (lo_va_stub + len + 2*page_size));
|
||||
if (is_big && ehdri.ET_EXEC==get_te16(&ehdri.e_type)) {
|
||||
upx_uint64_t my_page_size = 4096u;
|
||||
upx_uint64_t my_page_mask = -my_page_size;
|
||||
is_big = (lo_va_user < (lo_va_stub + len + 2 * my_page_size));
|
||||
if (is_pie || (is_big /*&& ehdri.ET_EXEC==get_te16(&ehdri.e_type)*/)) {
|
||||
// .e_entry is set later by PackLinuxElf64::updateLoader
|
||||
set_te64( &elfout.ehdr.e_entry,
|
||||
get_te64(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub);
|
||||
set_te64(&elfout.phdr[0].p_vaddr, lo_va_user);
|
||||
set_te64(&elfout.phdr[0].p_paddr, lo_va_user);
|
||||
lo_va_stub = lo_va_user;
|
||||
adrc = lo_va_stub;
|
||||
adrm = getbrk(phdri, e_phnum);
|
||||
adru = page_mask & (~page_mask + adrm); // round up to page boundary
|
||||
adrx = adru + hlen;
|
||||
lenm = page_size + len;
|
||||
lenu = page_size + len;
|
||||
cntc = len >> 3; // over-estimate; corrected at runtime
|
||||
adrm = getbrk(phdri, e_phnum) - lo_va_user;
|
||||
lenm = my_page_size + len;
|
||||
lenu = my_page_size + len;
|
||||
}
|
||||
else {
|
||||
adrm = lo_va_stub + len;
|
||||
adrc = adrm;
|
||||
adru = lo_va_stub;
|
||||
adrx = lo_va_stub + hlen;
|
||||
lenm = page_size;
|
||||
lenu = page_size + len;
|
||||
cntc = 0;
|
||||
adrm = len;
|
||||
lenm = my_page_size;
|
||||
lenu = my_page_size + len;
|
||||
}
|
||||
adrm = page_mask & (~page_mask + adrm); // round up to page boundary
|
||||
adrc = page_mask & (~page_mask + adrc); // round up to page boundary
|
||||
|
||||
//linker->defineSymbol("ADRX", adrx); // compressed input for eXpansion
|
||||
ACC_UNUSED(adrx);
|
||||
|
||||
// For actual moving, we need the true count, which depends on sz_pack2
|
||||
// and is not yet known. So the runtime stub detects "no move"
|
||||
// if adrm==adrc, and otherwise uses actual sz_pack2 to compute cntc.
|
||||
//linker->defineSymbol("CNTC", cntc); // count for copy
|
||||
ACC_UNUSED(cntc);
|
||||
adrm = my_page_mask & (~my_page_mask + adrm); // round up to page boundary
|
||||
|
||||
linker->defineSymbol("LENU", lenu); // len for unmap
|
||||
linker->defineSymbol("ADRC", adrc); // addr for copy
|
||||
//linker->defineSymbol("ADRU", adru); // addr for unmap
|
||||
ACC_UNUSED(adru);
|
||||
#define EI_NIDENT 16 /* <elf.h> */
|
||||
linker->defineSymbol("JMPU", EI_NIDENT -4 + lo_va_user); // unmap trampoline
|
||||
#undef EI_NIDENT
|
||||
linker->defineSymbol("LENM", lenm); // len for map
|
||||
linker->defineSymbol("ADRM", adrm); // addr for map
|
||||
linker->defineSymbol("ADRM", adrm); // offset from &Elf64_Ehdr
|
||||
|
||||
//linker->dumpSymbols(); // debug
|
||||
}
|
||||
@@ -1360,6 +1456,19 @@ PackLinuxElf64ppcle::buildLoader(const Filter *ft)
|
||||
stub_powerpc64le_linux_elf_fold, sizeof(stub_powerpc64le_linux_elf_fold), ft);
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/powerpc64-linux.elf-entry.h"
|
||||
static const
|
||||
#include "stub/powerpc64-linux.elf-fold.h"
|
||||
|
||||
void
|
||||
PackLinuxElf64ppc::buildLoader(const Filter *ft)
|
||||
{
|
||||
buildLinuxLoader(
|
||||
stub_powerpc64_linux_elf_entry, sizeof(stub_powerpc64_linux_elf_entry),
|
||||
stub_powerpc64_linux_elf_fold, sizeof(stub_powerpc64_linux_elf_fold), ft);
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/amd64-linux.elf-entry.h"
|
||||
static const
|
||||
@@ -1628,13 +1737,12 @@ bool PackLinuxElf32::canPack()
|
||||
if (Elf32_Ehdr::ET_DYN==get_te16(&ehdr->e_type)) {
|
||||
memcpy(&ehdri, ehdr, sizeof(Elf32_Ehdr));
|
||||
|
||||
if (Elf32_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf32_Dyn::DT_FLAGS_1)) {
|
||||
goto proceed; // marked as main program
|
||||
}
|
||||
if (calls_crt1((Elf32_Rel const *)elf_find_dynamic(Elf32_Dyn::DT_REL),
|
||||
if (Elf32_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf32_Dyn::DT_FLAGS_1)
|
||||
|| calls_crt1((Elf32_Rel const *)elf_find_dynamic(Elf32_Dyn::DT_REL),
|
||||
(int)elf_unsigned_dynamic(Elf32_Dyn::DT_RELSZ))
|
||||
|| calls_crt1((Elf32_Rel const *)elf_find_dynamic(Elf32_Dyn::DT_JMPREL),
|
||||
(int)elf_unsigned_dynamic(Elf32_Dyn::DT_PLTRELSZ))) {
|
||||
is_pie = true;
|
||||
goto proceed; // calls C library init for main program
|
||||
}
|
||||
|
||||
@@ -1717,184 +1825,8 @@ proceed: ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PackLinuxElf64ppcle::canPack()
|
||||
{
|
||||
union {
|
||||
unsigned char buf[sizeof(Elf64_Ehdr) + 14*sizeof(Elf64_Phdr)];
|
||||
//struct { Elf64_Ehdr ehdr; Elf64_Phdr phdr; } e;
|
||||
} u;
|
||||
COMPILE_TIME_ASSERT(sizeof(u) <= 1024)
|
||||
|
||||
fi->readx(u.buf, sizeof(u.buf));
|
||||
fi->seek(0, SEEK_SET);
|
||||
Elf64_Ehdr const *const ehdr = (Elf64_Ehdr *) u.buf;
|
||||
|
||||
// now check the ELF header
|
||||
if (checkEhdr(ehdr) != 0)
|
||||
return false;
|
||||
|
||||
// additional requirements for linux/elf386
|
||||
if (get_te16(&ehdr->e_ehsize) != sizeof(*ehdr)) {
|
||||
throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
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).
|
||||
Elf64_Phdr const *phdr = phdri;
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14)
|
||||
return false;
|
||||
unsigned const p_type = get_te32(&phdr->p_type);
|
||||
if (1!=exetype && phdr->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 (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
|
||||
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We want to compress position-independent executable (gcc -pie)
|
||||
// main programs, but compressing a shared library must be avoided
|
||||
// because the result is no longer usable. In theory, there is no way
|
||||
// to tell them apart: both are just ET_DYN. Also in theory,
|
||||
// neither the presence nor the absence of any particular symbol name
|
||||
// can be used to tell them apart; there are counterexamples.
|
||||
// However, we will use the following heuristic suggested by
|
||||
// Peter S. Mazinger <ps.m@gmx.net> September 2005:
|
||||
// If a ET_DYN has __libc_start_main as a global undefined symbol,
|
||||
// then the file is a position-independent executable main program
|
||||
// (that depends on libc.so.6) and is eligible to be compressed.
|
||||
// Otherwise (no __libc_start_main as global undefined): skip it.
|
||||
// Also allow __uClibc_main and __uClibc_start_main .
|
||||
|
||||
if (Elf64_Ehdr::ET_DYN==get_te16(&ehdr->e_type)) {
|
||||
// The DT_SYMTAB has no designated length. Read the whole file.
|
||||
alloc_file_image(file_image, file_size);
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(file_image, file_size);
|
||||
memcpy(&ehdri, ehdr, sizeof(Elf64_Ehdr));
|
||||
phdri= (Elf64_Phdr *)((size_t)e_phoff + file_image); // do not free() !!
|
||||
shdri= (Elf64_Shdr const *)((size_t)e_shoff + file_image); // do not free() !!
|
||||
|
||||
//sec_strndx = &shdri[ehdr->e_shstrndx];
|
||||
//shstrtab = (char const *)(sec_strndx->sh_offset + file_image);
|
||||
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym)
|
||||
sec_dynstr = get_te32(&sec_dynsym->sh_link) + shdri;
|
||||
|
||||
int j= e_phnum;
|
||||
phdr= phdri;
|
||||
for (; --j>=0; ++phdr)
|
||||
if (Elf64_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) {
|
||||
dynseg= (Elf64_Dyn const *)(get_te32(&phdr->p_offset) + file_image);
|
||||
break;
|
||||
}
|
||||
// elf_find_dynamic() returns 0 if 0==dynseg.
|
||||
dynstr= (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
||||
dynsym= (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB);
|
||||
|
||||
// Modified 2009-10-10 to detect a ProgramLinkageTable relocation
|
||||
// which references the symbol, because DT_GNU_HASH contains only
|
||||
// defined symbols, and there might be no DT_HASH.
|
||||
|
||||
if (Elf64_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf64_Dyn::DT_FLAGS_1)) {
|
||||
goto proceed; // marked as main program
|
||||
}
|
||||
if (calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_RELA),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_RELASZ))
|
||||
|| calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_JMPREL),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_PLTRELSZ))) {
|
||||
goto proceed; // calls C library init for main program
|
||||
}
|
||||
|
||||
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
|
||||
// If there is an existing DT_INIT, and if everything that the dynamic
|
||||
// linker ld-linux needs to perform relocations before calling DT_INIT
|
||||
// resides below the first SHT_EXECINSTR Section in one PT_LOAD, then
|
||||
// compress from the first executable Section to the end of that PT_LOAD.
|
||||
// We must not alter anything that ld-linux might touch before it calls
|
||||
// the DT_INIT function.
|
||||
//
|
||||
// Obviously this hack requires that the linker script put pieces
|
||||
// into good positions when building the original shared library,
|
||||
// and also requires ld-linux to behave.
|
||||
|
||||
if (elf_find_dynamic(Elf64_Dyn::DT_INIT)) {
|
||||
if (elf_has_dynamic(Elf64_Dyn::DT_TEXTREL)) {
|
||||
throwCantPack("DT_TEXTREL found; re-compile with -fPIC");
|
||||
goto abandon;
|
||||
}
|
||||
Elf64_Shdr const *shdr = shdri;
|
||||
xct_va = ~0ull;
|
||||
for (j= e_shnum; --j>=0; ++shdr) {
|
||||
if (Elf64_Shdr::SHF_EXECINSTR & get_te32(&shdr->sh_flags)) {
|
||||
xct_va = umin64(xct_va, get_te64(&shdr->sh_addr));
|
||||
}
|
||||
}
|
||||
// Rely on 0==elf_unsigned_dynamic(tag) if no such tag.
|
||||
upx_uint64_t const va_gash = elf_unsigned_dynamic(Elf64_Dyn::DT_GNU_HASH);
|
||||
upx_uint64_t const va_hash = elf_unsigned_dynamic(Elf64_Dyn::DT_HASH);
|
||||
if (xct_va < va_gash || (0==va_gash && xct_va < va_hash)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_STRTAB)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_SYMTAB)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_REL)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_RELA)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_JMPREL)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERDEF)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERSYM)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERNEEDED) ) {
|
||||
throwCantPack("DT_ tag above stub");
|
||||
goto abandon;
|
||||
}
|
||||
for ((shdr= shdri), (j= e_shnum); --j>=0; ++shdr) {
|
||||
upx_uint64_t const sh_addr = get_te64(&shdr->sh_addr);
|
||||
if ( sh_addr==va_gash
|
||||
|| (sh_addr==va_hash && 0==va_gash) ) {
|
||||
shdr= &shdri[get_te32(&shdr->sh_link)]; // the associated SHT_SYMTAB
|
||||
hatch_off = (char *)&ehdri.e_ident[11] - (char *)&ehdri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ACC_UNUSED(shdr);
|
||||
xct_off = elf_get_offset_from_address(xct_va);
|
||||
goto proceed; // But proper packing depends on checking xct_va.
|
||||
}
|
||||
else
|
||||
throwCantPack("need DT_INIT; try \"void _init(void){}\"");
|
||||
abandon:
|
||||
return false;
|
||||
proceed: ;
|
||||
}
|
||||
// XXX Theoretically the following test should be first,
|
||||
// but PackUnix::canPack() wants 0!=exetype ?
|
||||
if (!super::canPack())
|
||||
return false;
|
||||
assert(exetype == 1);
|
||||
|
||||
exetype = 0;
|
||||
|
||||
// set options
|
||||
opt->o_unix.blocksize = blocksize = file_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PackLinuxElf64amd::canPack()
|
||||
PackLinuxElf64::canPack()
|
||||
{
|
||||
union {
|
||||
unsigned char buf[sizeof(Elf64_Ehdr) + 14*sizeof(Elf64_Phdr)];
|
||||
@@ -1940,6 +1872,7 @@ PackLinuxElf64amd::canPack()
|
||||
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
hatch_off = phdr->p_memsz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1983,13 +1916,12 @@ PackLinuxElf64amd::canPack()
|
||||
dynstr= (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
||||
dynsym= (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB);
|
||||
|
||||
if (Elf64_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf64_Dyn::DT_FLAGS_1)) {
|
||||
goto proceed; // marked as main program
|
||||
}
|
||||
if (calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_RELA),
|
||||
if (Elf64_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf64_Dyn::DT_FLAGS_1)
|
||||
|| calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_RELA),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_RELASZ))
|
||||
|| calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_JMPREL),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_PLTRELSZ))) {
|
||||
is_pie = true;
|
||||
goto proceed; // calls C library init for main program
|
||||
}
|
||||
|
||||
@@ -2037,178 +1969,7 @@ PackLinuxElf64amd::canPack()
|
||||
if ( sh_addr==va_gash
|
||||
|| (sh_addr==va_hash && 0==va_gash) ) {
|
||||
shdr= &shdri[get_te32(&shdr->sh_link)]; // the associated SHT_SYMTAB
|
||||
hatch_off = (char *)&ehdri.e_ident[11] - (char *)&ehdri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ACC_UNUSED(shdr);
|
||||
xct_off = elf_get_offset_from_address(xct_va);
|
||||
goto proceed; // But proper packing depends on checking xct_va.
|
||||
}
|
||||
else
|
||||
throwCantPack("need DT_INIT; try \"void _init(void){}\"");
|
||||
abandon:
|
||||
return false;
|
||||
proceed: ;
|
||||
}
|
||||
// XXX Theoretically the following test should be first,
|
||||
// but PackUnix::canPack() wants 0!=exetype ?
|
||||
if (!super::canPack())
|
||||
return false;
|
||||
assert(exetype == 1);
|
||||
|
||||
exetype = 0;
|
||||
|
||||
// set options
|
||||
opt->o_unix.blocksize = blocksize = file_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PackLinuxElf64arm::canPack()
|
||||
{
|
||||
union {
|
||||
unsigned char buf[sizeof(Elf64_Ehdr) + 14*sizeof(Elf64_Phdr)];
|
||||
//struct { Elf64_Ehdr ehdr; Elf64_Phdr phdr; } e;
|
||||
} u;
|
||||
COMPILE_TIME_ASSERT(sizeof(u) <= 1024)
|
||||
|
||||
fi->readx(u.buf, sizeof(u.buf));
|
||||
fi->seek(0, SEEK_SET);
|
||||
Elf64_Ehdr const *const ehdr = (Elf64_Ehdr *) u.buf;
|
||||
|
||||
// now check the ELF header
|
||||
if (checkEhdr(ehdr) != 0)
|
||||
return false;
|
||||
|
||||
// additional requirements for linux/elf386
|
||||
if (get_te16(&ehdr->e_ehsize) != sizeof(*ehdr)) {
|
||||
throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
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).
|
||||
Elf64_Phdr const *phdr = phdri;
|
||||
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14)
|
||||
return false;
|
||||
unsigned const p_type = get_te32(&phdr->p_type);
|
||||
if (1!=exetype && phdr->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 (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
|
||||
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We want to compress position-independent executable (gcc -pie)
|
||||
// main programs, but compressing a shared library must be avoided
|
||||
// because the result is no longer usable. In theory, there is no way
|
||||
// to tell them apart: both are just ET_DYN. Also in theory,
|
||||
// neither the presence nor the absence of any particular symbol name
|
||||
// can be used to tell them apart; there are counterexamples.
|
||||
// However, we will use the following heuristic suggested by
|
||||
// Peter S. Mazinger <ps.m@gmx.net> September 2005:
|
||||
// If a ET_DYN has __libc_start_main as a global undefined symbol,
|
||||
// then the file is a position-independent executable main program
|
||||
// (that depends on libc.so.6) and is eligible to be compressed.
|
||||
// Otherwise (no __libc_start_main as global undefined): skip it.
|
||||
// Also allow __uClibc_main and __uClibc_start_main .
|
||||
|
||||
if (Elf64_Ehdr::ET_DYN==get_te16(&ehdr->e_type)) {
|
||||
// The DT_SYMTAB has no designated length. Read the whole file.
|
||||
alloc_file_image(file_image, file_size);
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(file_image, file_size);
|
||||
memcpy(&ehdri, ehdr, sizeof(Elf64_Ehdr));
|
||||
phdri= (Elf64_Phdr *)((size_t)e_phoff + file_image); // do not free() !!
|
||||
shdri= (Elf64_Shdr const *)((size_t)e_shoff + file_image); // do not free() !!
|
||||
|
||||
//sec_strndx = &shdri[ehdr->e_shstrndx];
|
||||
//shstrtab = (char const *)(sec_strndx->sh_offset + file_image);
|
||||
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym)
|
||||
sec_dynstr = get_te64(&sec_dynsym->sh_link) + shdri;
|
||||
|
||||
int j= e_phnum;
|
||||
phdr= phdri;
|
||||
for (; --j>=0; ++phdr)
|
||||
if (Elf64_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) {
|
||||
dynseg= (Elf64_Dyn const *)(get_te64(&phdr->p_offset) + file_image);
|
||||
break;
|
||||
}
|
||||
// elf_find_dynamic() returns 0 if 0==dynseg.
|
||||
dynstr= (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
||||
dynsym= (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB);
|
||||
|
||||
if (Elf64_Dyn::DF_1_PIE & elf_unsigned_dynamic(Elf64_Dyn::DT_FLAGS_1)) {
|
||||
goto proceed; // marked as main program
|
||||
}
|
||||
if (calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_RELA),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_RELASZ))
|
||||
|| calls_crt1((Elf64_Rela const *)elf_find_dynamic(Elf64_Dyn::DT_JMPREL),
|
||||
(int)elf_unsigned_dynamic(Elf64_Dyn::DT_PLTRELSZ))) {
|
||||
goto proceed; // calls C library init for main program
|
||||
}
|
||||
|
||||
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
|
||||
// If there is an existing DT_INIT, and if everything that the dynamic
|
||||
// linker ld-linux needs to perform relocations before calling DT_INIT
|
||||
// resides below the first SHT_EXECINSTR Section in one PT_LOAD, then
|
||||
// compress from the first executable Section to the end of that PT_LOAD.
|
||||
// We must not alter anything that ld-linux might touch before it calls
|
||||
// the DT_INIT function.
|
||||
//
|
||||
// Obviously this hack requires that the linker script put pieces
|
||||
// into good positions when building the original shared library,
|
||||
// and also requires ld-linux to behave.
|
||||
|
||||
if (elf_find_dynamic(Elf64_Dyn::DT_INIT)) {
|
||||
if (elf_has_dynamic(Elf64_Dyn::DT_TEXTREL)) {
|
||||
throwCantPack("DT_TEXTREL found; re-compile with -fPIC");
|
||||
goto abandon;
|
||||
}
|
||||
Elf64_Shdr const *shdr = shdri;
|
||||
xct_va = ~0ull;
|
||||
for (j= e_shnum; --j>=0; ++shdr) {
|
||||
if (Elf64_Shdr::SHF_EXECINSTR & get_te32(&shdr->sh_flags)) {
|
||||
xct_va = umin64(xct_va, get_te64(&shdr->sh_addr));
|
||||
}
|
||||
}
|
||||
// Rely on 0==elf_unsigned_dynamic(tag) if no such tag.
|
||||
upx_uint64_t const va_gash = elf_unsigned_dynamic(Elf64_Dyn::DT_GNU_HASH);
|
||||
upx_uint64_t const va_hash = elf_unsigned_dynamic(Elf64_Dyn::DT_HASH);
|
||||
if (xct_va < va_gash || (0==va_gash && xct_va < va_hash)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_STRTAB)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_SYMTAB)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_REL)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_RELA)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_JMPREL)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERDEF)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERSYM)
|
||||
|| xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERNEEDED) ) {
|
||||
throwCantPack("DT_ tag above stub");
|
||||
goto abandon;
|
||||
}
|
||||
for ((shdr= shdri), (j= e_shnum); --j>=0; ++shdr) {
|
||||
upx_uint64_t const sh_addr = get_te64(&shdr->sh_addr);
|
||||
if ( sh_addr==va_gash
|
||||
|| (sh_addr==va_hash && 0==va_gash) ) {
|
||||
shdr= &shdri[get_te32(&shdr->sh_link)]; // the associated SHT_SYMTAB
|
||||
hatch_off = (char *)&ehdri.e_ident[11] - (char *)&ehdri;
|
||||
//hatch_off = (char *)&ehdri.e_ident[11] - (char *)&ehdri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2318,6 +2079,7 @@ PackLinuxElf32::generateElfHdr(
|
||||
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[0].p_filesz, sizeof(*h2)); // + identsize;
|
||||
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
|
||||
|
||||
@@ -2342,7 +2104,7 @@ PackLinuxElf32::generateElfHdr(
|
||||
set_te32(&h2->phdr[1].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W);
|
||||
}
|
||||
if (ph.format==getFormat()) {
|
||||
assert((2u+ !!gnu_stack) == get_te16(&h2->ehdr.e_phnum));
|
||||
assert((2u+ !!gnu_stack) == phnum_o);
|
||||
set_te32(&h2->phdr[0].p_flags, ~Elf32_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags));
|
||||
if (!gnu_stack) {
|
||||
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
||||
@@ -2557,7 +2319,7 @@ PackLinuxElf64::generateElfHdr(
|
||||
|
||||
unsigned phnum_o = get_te16(&h2->ehdr.e_phnum);
|
||||
|
||||
assert(get_te32(&h2->ehdr.e_phoff) == sizeof(Elf64_Ehdr));
|
||||
assert(get_te64(&h2->ehdr.e_phoff) == sizeof(Elf64_Ehdr));
|
||||
h2->ehdr.e_shoff = 0;
|
||||
assert(get_te16(&h2->ehdr.e_ehsize) == sizeof(Elf64_Ehdr));
|
||||
assert(get_te16(&h2->ehdr.e_phentsize) == sizeof(Elf64_Phdr));
|
||||
@@ -2577,6 +2339,7 @@ PackLinuxElf64::generateElfHdr(
|
||||
memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack));
|
||||
set_te16(&h2->ehdr.e_phnum, phnum_o);
|
||||
}
|
||||
o_binfo = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr)*phnum_o + sizeof(l_info) + sizeof(p_info);
|
||||
set_te64(&h2->phdr[0].p_filesz, sizeof(*h2)); // + identsize;
|
||||
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
|
||||
|
||||
@@ -2599,11 +2362,10 @@ PackLinuxElf64::generateElfHdr(
|
||||
// anyway by phdr[0].p_align and constant offset from phdr[0].p_vaddr.
|
||||
// However, somebody might complain because (.p_vaddr - .p_offset)
|
||||
// is divisible only by phdr[1].p_align, and not by phdr[0].p_align.
|
||||
set_te64(&h2->phdr[1].p_align, 0x1000);
|
||||
if ( ~page_mask == 0xffff ) /* 64K specific case */
|
||||
set_te64(&h2->phdr[1].p_offset, /*~page_mask*/ 0xffff & brkb);
|
||||
else
|
||||
set_te64(&h2->phdr[1].p_offset, /*~page_mask*/ 0xfff & brkb);
|
||||
if (get_te16(&elfout.ehdr.e_machine) != Elf64_Ehdr::EM_PPC64) {
|
||||
set_te64(&h2->phdr[1].p_align, 0x1000);
|
||||
}
|
||||
set_te64(&h2->phdr[1].p_offset, (-1+ get_te64(&h2->phdr[1].p_align)) & brkb);
|
||||
|
||||
set_te64(&h2->phdr[1].p_vaddr, brkb);
|
||||
set_te64(&h2->phdr[1].p_paddr, brkb);
|
||||
@@ -2612,7 +2374,7 @@ PackLinuxElf64::generateElfHdr(
|
||||
set_te32(&h2->phdr[1].p_flags, Elf64_Phdr::PF_R | Elf64_Phdr::PF_W);
|
||||
}
|
||||
if (ph.format==getFormat()) {
|
||||
assert((2u+ !!gnu_stack) == get_te16(&h2->ehdr.e_phnum));
|
||||
assert((2u+ !!gnu_stack) == phnum_o);
|
||||
set_te32(&h2->phdr[0].p_flags, ~Elf64_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags));
|
||||
if (!gnu_stack) {
|
||||
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
||||
@@ -2829,6 +2591,14 @@ void PackLinuxElf64ppcle::pack1(OutputFile *fo, Filter &ft)
|
||||
generateElfHdr(fo, stub_powerpc64le_linux_elf_fold, getbrk(phdri, e_phnum) );
|
||||
}
|
||||
|
||||
void PackLinuxElf64ppc::pack1(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
super::pack1(fo, ft);
|
||||
if (0!=xct_off) // shared library
|
||||
return;
|
||||
generateElfHdr(fo, stub_powerpc64_linux_elf_fold, getbrk(phdri, e_phnum) );
|
||||
}
|
||||
|
||||
void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
||||
{
|
||||
fi->seek(0, SEEK_SET);
|
||||
@@ -3019,7 +2789,6 @@ int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
||||
|
||||
// compress extents
|
||||
unsigned hdr_u_len = sizeof(Elf32_Ehdr) + sz_phdrs;
|
||||
// TODO: propagate that to the stubs (varies by gnu_stack)
|
||||
|
||||
unsigned total_in = xct_off - (is_shlib ? hdr_u_len : 0);
|
||||
unsigned total_out = xct_off;
|
||||
@@ -3129,7 +2898,6 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
||||
|
||||
// compress extents
|
||||
unsigned hdr_u_len = sizeof(Elf64_Ehdr) + sz_phdrs;
|
||||
// TODO: propagate that to the stubs (varies by gnu_stack)
|
||||
|
||||
unsigned total_in = xct_off - (is_shlib ? hdr_u_len : 0);
|
||||
unsigned total_out = xct_off;
|
||||
@@ -3244,8 +3012,10 @@ int PackLinuxElf32::ARM_is_QNX(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PackLinuxElf32::ARM_defineSymbols(Filter const * /*ft*/)
|
||||
void PackLinuxElf32::ARM_defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf32::defineSymbols(ft);
|
||||
|
||||
lsize = /*getLoaderSize()*/ 4 * 1024; // upper bound; avoid circularity
|
||||
unsigned lo_va_user = ~0u; // infinity
|
||||
for (int j= e_phnum; --j>=0; ) {
|
||||
@@ -3299,8 +3069,10 @@ void PackLinuxElf32armBe::defineSymbols(Filter const *ft)
|
||||
ARM_defineSymbols(ft);
|
||||
}
|
||||
|
||||
void PackLinuxElf64arm::defineSymbols(Filter const * /*ft*/)
|
||||
void PackLinuxElf64arm::defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf64::defineSymbols(ft);
|
||||
|
||||
lsize = /*getLoaderSize()*/ 4 * 1024; // upper bound; avoid circularity
|
||||
upx_uint64_t lo_va_user = ~0ul; // infinity
|
||||
for (int j= e_phnum; --j>=0; ) {
|
||||
@@ -3344,8 +3116,10 @@ void PackLinuxElf64arm::defineSymbols(Filter const * /*ft*/)
|
||||
linker->defineSymbol("MFLG", mflg);
|
||||
}
|
||||
|
||||
void PackLinuxElf32mipseb::defineSymbols(Filter const * /*ft*/)
|
||||
void PackLinuxElf32mipseb::defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf32::defineSymbols(ft);
|
||||
|
||||
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info);
|
||||
|
||||
// We want to know if compressed data, plus stub, plus a couple pages,
|
||||
@@ -3417,8 +3191,10 @@ void PackLinuxElf32mipseb::defineSymbols(Filter const * /*ft*/)
|
||||
//linker->dumpSymbols(); // debug
|
||||
}
|
||||
|
||||
void PackLinuxElf32mipsel::defineSymbols(Filter const * /*ft*/)
|
||||
void PackLinuxElf32mipsel::defineSymbols(Filter const *ft)
|
||||
{
|
||||
PackLinuxElf32::defineSymbols(ft);
|
||||
|
||||
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info);
|
||||
|
||||
// We want to know if compressed data, plus stub, plus a couple pages,
|
||||
|
||||
Reference in New Issue
Block a user