1
0
mirror of https://github.com/upx/upx synced 2025-10-05 19:20:23 +08:00

is_pie; O_BINFO; remove LUNMP000, LUNMP001

modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
This commit is contained in:
John Reiser 2017-04-06 14:15:07 -07:00
parent b23b7ef85e
commit 491e8640b2
2 changed files with 65 additions and 25 deletions

View File

@ -206,7 +206,7 @@ PackLinuxElf64::checkEhdr(Elf64_Ehdr const *ehdr) const
PackLinuxElf::PackLinuxElf(InputFile *f) PackLinuxElf::PackLinuxElf(InputFile *f)
: super(f), e_phnum(0), dynstr(NULL), : super(f), e_phnum(0), dynstr(NULL),
sz_phdrs(0), sz_elf_hdrs(0), sz_pack2(0), sz_pack2a(0), 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), 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), e_machine(0), ei_class(0), ei_data(0), ei_osabi(0), osabi_note(NULL),
o_elf_shnum(0) o_elf_shnum(0)
@ -516,7 +516,7 @@ PackLinuxElf::addStubEntrySections(Filter const *)
if (hasLoaderSection("ELFMAINXu")) { if (hasLoaderSection("ELFMAINXu")) {
// brk() trouble if static // brk() trouble if static
all_pages |= (Elf32_Ehdr::EM_ARM==e_machine && 0x8000==load_va); all_pages |= (Elf32_Ehdr::EM_ARM==e_machine && 0x8000==load_va);
addLoader((all_pages ? "LUNMP000" : "LUNMP001"), "ELFMAINXu", NULL); addLoader(/*(all_pages ? "LUNMP000" : "LUNMP001"),*/ "ELFMAINXu", NULL);
} }
//addLoader(getDecompressorSections(), NULL); //addLoader(getDecompressorSections(), NULL);
addLoader( addLoader(
@ -529,7 +529,7 @@ PackLinuxElf::addStubEntrySections(Filter const *)
addLoader("CFLUSH"); addLoader("CFLUSH");
addLoader("ELFMAINY,IDENTSTR,+40,ELFMAINZ", NULL); addLoader("ELFMAINY,IDENTSTR,+40,ELFMAINZ", NULL);
if (hasLoaderSection("ELFMAINZu")) { if (hasLoaderSection("ELFMAINZu")) {
addLoader((all_pages ? "LUNMP000" : "LUNMP001"), "ELFMAINZu", NULL); addLoader(/*(all_pages ? "LUNMP000" : "LUNMP001"),*/ "ELFMAINZu", NULL);
} }
addLoader("FOLDEXEC", NULL); addLoader("FOLDEXEC", NULL);
} }
@ -537,7 +537,17 @@ PackLinuxElf::addStubEntrySections(Filter const *)
void PackLinuxElf::defineSymbols(Filter const *) void PackLinuxElf::defineSymbols(Filter const *)
{ {
// empty linker->defineSymbol("O_BINFO", o_binfo);
}
void PackLinuxElf32::defineSymbols(Filter const *ft)
{
PackLinuxElf::defineSymbols(ft);
}
void PackLinuxElf64::defineSymbols(Filter const *ft)
{
PackLinuxElf::defineSymbols(ft);
} }
PackLinuxElf32::PackLinuxElf32(InputFile *f) PackLinuxElf32::PackLinuxElf32(InputFile *f)
@ -904,13 +914,15 @@ void PackLinuxElf32x86::addStubEntrySections(Filter const *ft)
if (Elf32_Ehdr::ET_DYN==get_te16(&ehdri.e_type)) { if (Elf32_Ehdr::ET_DYN==get_te16(&ehdri.e_type)) {
addLoader("LEXECDYN", NULL); addLoader("LEXECDYN", NULL);
} }
addLoader(((opt->o_unix.unmap_all_pages|is_big) ? "LUNMP000" : "LUNMP001"), addLoader(/*((opt->o_unix.unmap_all_pages|is_big) ? "LUNMP000" : "LUNMP001"),*/
"LEXEC025", NULL); "LEXEC025", NULL);
addLoader("FOLDEXEC", NULL); addLoader("FOLDEXEC", NULL);
} }
void PackLinuxElf32x86::defineSymbols(Filter const *const ft) void PackLinuxElf32x86::defineSymbols(Filter const *const ft)
{ {
PackLinuxElf32::defineSymbols(ft);
if (0x80==(ft->id & 0xF0)) { if (0x80==(ft->id & 0xF0)) {
int const mru = ft->n_mru ? 1+ ft->n_mru : 0; int const mru = ft->n_mru ? 1+ ft->n_mru : 0;
if (mru && mru!=256) { if (mru && mru!=256) {
@ -1044,15 +1056,17 @@ PackLinuxElf64::buildLinuxLoader(
} }
void void
PackLinuxElf64amd::defineSymbols(Filter const *) PackLinuxElf64amd::defineSymbols(Filter const *ft)
{ {
PackLinuxElf64::defineSymbols(ft);
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info); 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, // 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 // will fit below the uncompressed program in memory. But we don't
// know the final total compressed size yet, so use the uncompressed // know the final total compressed size yet, so use the uncompressed
// size (total over all PT_LOAD64) as an upper bound. // 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 upx_uint64_t lo_va_user = ~0ull; // infinity
for (int j= e_phnum; --j>=0; ) { for (int j= e_phnum; --j>=0; ) {
if (PT_LOAD64 == get_te32(&phdri[j].p_type)) { if (PT_LOAD64 == get_te32(&phdri[j].p_type)) {
@ -1074,7 +1088,7 @@ PackLinuxElf64amd::defineSymbols(Filter const *)
unsigned lenu; unsigned lenu;
len += (7&-lsize) + lsize; len += (7&-lsize) + lsize;
is_big = (lo_va_user < (lo_va_stub + len + 2*page_size)); is_big = (lo_va_user < (lo_va_stub + len + 2*page_size));
if (is_big && ehdri.ET_EXEC==get_te16(&ehdri.e_type)) { if (is_pie || (is_big /*&& ehdri.ET_EXEC==get_te16(&ehdri.e_type)*/)) {
// .e_entry is set later by PackLinuxElf64::updateLoader // .e_entry is set later by PackLinuxElf64::updateLoader
set_te64( &elfout.ehdr.e_entry, set_te64( &elfout.ehdr.e_entry,
get_te64(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub); get_te64(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub);
@ -1111,7 +1125,7 @@ PackLinuxElf64amd::defineSymbols(Filter const *)
ACC_UNUSED(cntc); ACC_UNUSED(cntc);
linker->defineSymbol("LENU", lenu); // len for unmap linker->defineSymbol("LENU", lenu); // len for unmap
linker->defineSymbol("ADRC", adrc); // addr for copy //linker->defineSymbol("ADRC", adrc); // addr for copy
//linker->defineSymbol("ADRU", adru); // addr for unmap //linker->defineSymbol("ADRU", adru); // addr for unmap
ACC_UNUSED(adru); ACC_UNUSED(adru);
#define EI_NIDENT 16 /* <elf.h> */ #define EI_NIDENT 16 /* <elf.h> */
@ -1599,8 +1613,10 @@ bool PackLinuxElf32::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.) // Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
@ -1789,8 +1805,10 @@ PackLinuxElf64ppcle::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)? // 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)?
@ -1803,8 +1821,10 @@ PackLinuxElf64ppcle::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.) // Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
// If there is an existing DT_INIT, and if everything that the dynamic // If there is an existing DT_INIT, and if everything that the dynamic
@ -1983,8 +2003,10 @@ PackLinuxElf64amd::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)? // 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)?
@ -1997,8 +2019,10 @@ PackLinuxElf64amd::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.) // Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
@ -2178,8 +2202,10 @@ PackLinuxElf64arm::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)? // 2016-10-09 DT_JMPREL is no more (binutils-2.26.1)?
@ -2192,8 +2218,10 @@ PackLinuxElf64arm::canPack()
char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr; char const *const symnam = get_te32(&dynsym[symnum].st_name) + dynstr;
if (0==strcmp(symnam, "__libc_start_main") if (0==strcmp(symnam, "__libc_start_main")
|| 0==strcmp(symnam, "__uClibc_main") || 0==strcmp(symnam, "__uClibc_main")
|| 0==strcmp(symnam, "__uClibc_start_main")) || 0==strcmp(symnam, "__uClibc_start_main")) {
is_pie = true;
goto proceed; goto proceed;
}
} }
// Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.) // Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
@ -2350,10 +2378,11 @@ PackLinuxElf32::generateElfHdr(
memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack)); memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack));
set_te16(&h2->ehdr.e_phnum, phnum_o); 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; set_te32(&h2->phdr[0].p_filesz, sizeof(*h2)); // + identsize;
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz; h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
for (unsigned j=0; j < 3; ++j) { for (unsigned j=0; j < phnum_o; ++j) {
if (PT_LOAD32==get_te32(&h3->phdr[j].p_type)) { if (PT_LOAD32==get_te32(&h3->phdr[j].p_type)) {
set_te32(&h3->phdr[j].p_align, page_size); set_te32(&h3->phdr[j].p_align, page_size);
} }
@ -2374,7 +2403,7 @@ PackLinuxElf32::generateElfHdr(
set_te32(&h2->phdr[1].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W); set_te32(&h2->phdr[1].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W);
} }
if (ph.format==getFormat()) { if (ph.format==getFormat()) {
assert((2+ !!gnu_stack) == get_te16(&h2->ehdr.e_phnum)); assert((2+ !!gnu_stack) == phnum_o);
set_te32(&h2->phdr[0].p_flags, ~Elf32_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags)); set_te32(&h2->phdr[0].p_flags, ~Elf32_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags));
if (!gnu_stack) { if (!gnu_stack) {
memset(&h2->linfo, 0, sizeof(h2->linfo)); memset(&h2->linfo, 0, sizeof(h2->linfo));
@ -2600,6 +2629,7 @@ PackLinuxElf64::generateElfHdr(
memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack)); memcpy(&h2->phdr[phnum_o++], gnu_stack, sizeof(*gnu_stack));
set_te16(&h2->ehdr.e_phnum, phnum_o); 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; set_te64(&h2->phdr[0].p_filesz, sizeof(*h2)); // + identsize;
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz; h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
@ -2635,7 +2665,7 @@ PackLinuxElf64::generateElfHdr(
set_te32(&h2->phdr[1].p_flags, Elf64_Phdr::PF_R | Elf64_Phdr::PF_W); set_te32(&h2->phdr[1].p_flags, Elf64_Phdr::PF_R | Elf64_Phdr::PF_W);
} }
if (ph.format==getFormat()) { if (ph.format==getFormat()) {
assert((2+ !!gnu_stack) == get_te16(&h2->ehdr.e_phnum)); assert((2+ !!gnu_stack) == phnum_o);
set_te32(&h2->phdr[0].p_flags, ~Elf64_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags)); set_te32(&h2->phdr[0].p_flags, ~Elf64_Phdr::PF_W & get_te32(&h2->phdr[0].p_flags));
if (!gnu_stack) { if (!gnu_stack) {
memset(&h2->linfo, 0, sizeof(h2->linfo)); memset(&h2->linfo, 0, sizeof(h2->linfo));
@ -3042,7 +3072,6 @@ int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
// compress extents // compress extents
unsigned hdr_u_len = sizeof(Elf32_Ehdr) + sz_phdrs; 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_in = xct_off - (is_shlib ? hdr_u_len : 0);
unsigned total_out = xct_off; unsigned total_out = xct_off;
@ -3152,7 +3181,6 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
// compress extents // compress extents
unsigned hdr_u_len = sizeof(Elf64_Ehdr) + sz_phdrs; 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_in = xct_off - (is_shlib ? hdr_u_len : 0);
unsigned total_out = xct_off; unsigned total_out = xct_off;
@ -3267,8 +3295,10 @@ int PackLinuxElf32::ARM_is_QNX(void)
return 0; 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 lsize = /*getLoaderSize()*/ 4 * 1024; // upper bound; avoid circularity
unsigned lo_va_user = ~0u; // infinity unsigned lo_va_user = ~0u; // infinity
for (int j= e_phnum; --j>=0; ) { for (int j= e_phnum; --j>=0; ) {
@ -3322,8 +3352,10 @@ void PackLinuxElf32armBe::defineSymbols(Filter const *ft)
ARM_defineSymbols(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 lsize = /*getLoaderSize()*/ 4 * 1024; // upper bound; avoid circularity
upx_uint64_t lo_va_user = ~0ul; // infinity upx_uint64_t lo_va_user = ~0ul; // infinity
for (int j= e_phnum; --j>=0; ) { for (int j= e_phnum; --j>=0; ) {
@ -3367,8 +3399,10 @@ void PackLinuxElf64arm::defineSymbols(Filter const * /*ft*/)
linker->defineSymbol("MFLG", mflg); 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); 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, // We want to know if compressed data, plus stub, plus a couple pages,
@ -3440,8 +3474,10 @@ void PackLinuxElf32mipseb::defineSymbols(Filter const * /*ft*/)
//linker->dumpSymbols(); // debug //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); 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, // We want to know if compressed data, plus stub, plus a couple pages,

View File

@ -81,8 +81,10 @@ protected:
unsigned lg2_page; // log2(PAGE_SIZE) unsigned lg2_page; // log2(PAGE_SIZE)
unsigned page_size; // 1u<<lg2_page unsigned page_size; // 1u<<lg2_page
bool is_big; // stub style: must use area above the brk bool is_big; // stub style: must use area above the brk
bool is_pie; // is Position-Independent-Executable (ET_DYN main program)
unsigned xct_off; // shared library: file offset of SHT_EXECINSTR unsigned xct_off; // shared library: file offset of SHT_EXECINSTR
unsigned hatch_off; // file offset of escape hatch unsigned hatch_off; // file offset of escape hatch
unsigned o_binfo; // offset to first b_info
upx_uint64_t load_va; // PT_LOAD[0].p_vaddr upx_uint64_t load_va; // PT_LOAD[0].p_vaddr
upx_uint64_t xct_va; // minimum SHT_EXECINSTR virtual address upx_uint64_t xct_va; // minimum SHT_EXECINSTR virtual address
upx_uint64_t jni_onload_va; // runtime &JNI_OnLoad upx_uint64_t jni_onload_va; // runtime &JNI_OnLoad
@ -126,6 +128,7 @@ protected:
void const *proto, void const *proto,
unsigned const brka unsigned const brka
); );
virtual void defineSymbols(Filter const *);
virtual void buildLinuxLoader( virtual void buildLinuxLoader(
upx_byte const *const proto, // assembly-only sections upx_byte const *const proto, // assembly-only sections
unsigned const szproto, unsigned const szproto,
@ -247,6 +250,7 @@ protected:
void const *proto, void const *proto,
unsigned const brka unsigned const brka
); );
virtual void defineSymbols(Filter const *);
virtual void buildLinuxLoader( virtual void buildLinuxLoader(
upx_byte const *const proto, // assembly-only sections upx_byte const *const proto, // assembly-only sections
unsigned const szproto, unsigned const szproto,