Revamp powerpc{,64le,64}.

Fix 64-bit stack frame (8*8 bytes for spilling a0-a7).  Avoid using r2 (t0).
Prepare for -pie executables.  Prepare for unified strategy in stubs.

	modified:   p_lx_elf.cpp
	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/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
	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/i386-darwin.macho-entry.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
	modified:   stub/src/powerpc64-darwin.dylib-entry.S
	modified:   stub/src/powerpc64-darwin.macho-entry.S
	modified:   stub/src/powerpc64-darwin.macho-fold.S
	modified:   stub/src/powerpc64-darwin.macho-main.c
	modified:   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/i386-darwin.macho-entry.h
	modified:   stub/powerpc-darwin.dylib-entry.h
	modified:   stub/powerpc-darwin.macho-entry.h
	modified:   stub/powerpc-darwin.macho-fold.h
	modified:   stub/powerpc-linux.elf-entry.h
	modified:   stub/powerpc-linux.elf-fold.h
	modified:   stub/powerpc-linux.kernel.vmlinux.h
	modified:   stub/powerpc64-linux.elf-entry.h
	modified:   stub/powerpc64-linux.elf-fold.h
	modified:   stub/powerpc64le-darwin.dylib-entry.h
	modified:   stub/powerpc64le-darwin.macho-entry.h
	modified:   stub/powerpc64le-darwin.macho-fold.h
	modified:   stub/powerpc64le-linux.elf-entry.h
	modified:   stub/powerpc64le-linux.elf-fold.h
	modified:   stub/powerpc64le-linux.kernel.vmlinux.h
	modified:   stub/tmp/i386-darwin.macho-entry.bin.dump
	modified:   stub/tmp/powerpc-darwin.dylib-entry.bin.dump
	modified:   stub/tmp/powerpc-darwin.macho-entry.bin.dump
	modified:   stub/tmp/powerpc-linux.elf-entry.bin.dump
	modified:   stub/tmp/powerpc-linux.elf-fold.map
	modified:   stub/tmp/powerpc64le-darwin.dylib-entry.bin.dump
	modified:   stub/tmp/powerpc64le-darwin.macho-entry.bin.dump
	modified:   stub/tmp/powerpc64le-linux.elf-entry.bin.dump
	modified:   stub/tmp/powerpc64le-linux.elf-fold.map
	modified:   stub/tmp/powerpc64le-linux.kernel.vmlinux.bin.dump
This commit is contained in:
John Reiser
2017-04-19 19:25:05 -07:00
parent 4e05f087f9
commit c4a921283a
64 changed files with 8739 additions and 7226 deletions
+69 -6
View File
@@ -516,7 +516,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(
@@ -533,7 +533,7 @@ PackLinuxElf::addStubEntrySections(Filter const *)
}
addLoader("+40,ELFMAINZ", NULL);
if (hasLoaderSection("ELFMAINZu")) {
addLoader(/*(all_pages ? "LUNMP000" : "LUNMP001"),*/ "ELFMAINZu", NULL);
addLoader("ELFMAINZu", NULL);
}
addLoader("FOLDEXEC", NULL);
}
@@ -547,6 +547,54 @@ void PackLinuxElf::defineSymbols(Filter const *)
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
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)
@@ -765,8 +813,9 @@ 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*/)
@@ -959,8 +1008,7 @@ 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);
}
@@ -1080,6 +1128,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);