1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

pack2() fixes for --android-shlib

WIP for https://github.com/upx/upx/issues/599
	modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser 2022-10-18 14:33:01 -07:00 committed by Markus F.X.J. Oberhumer
parent 5d9f71bb13
commit 2e29f9fa5f

View File

@ -3694,6 +3694,7 @@ void PackLinuxElf64ppc::pack1(OutputFile *fo, Filter &ft)
generateElfHdr(fo, stub_powerpc64_linux_elf_fold, getbrk(phdri, e_phnum) ); generateElfHdr(fo, stub_powerpc64_linux_elf_fold, getbrk(phdri, e_phnum) );
} }
//FIXME: probably should be part of ::pack2()
void PackLinuxElf64::asl_pack1_Shdrs(OutputFile *fo) void PackLinuxElf64::asl_pack1_Shdrs(OutputFile *fo)
{ {
// In order to pacify the runtime linker on Android "O" ("Oreo"), // In order to pacify the runtime linker on Android "O" ("Oreo"),
@ -3852,7 +3853,7 @@ void PackLinuxElf64::asl_pack1_Shdrs(OutputFile *fo)
} }
} }
fo->seek(sh_offset, SEEK_SET); fo->seek(sh_offset, SEEK_SET);
fo->rewrite(relb, sh_size); fo->rewrite(relb, sh_size); // FIXME BUG! fo not ready
}; break; }; break;
case Elf64_Shdr::SHT_REL: { case Elf64_Shdr::SHT_REL: {
if (sizeof(Elf64_Rel) != sh_entsize) { if (sizeof(Elf64_Rel) != sh_entsize) {
@ -3925,6 +3926,8 @@ void PackLinuxElf64::asl_pack1_Shdrs(OutputFile *fo)
fo->write(shstrtab, sz_shstrtab); fo->write(shstrtab, sz_shstrtab);
sz_elf_hdrs = fpad8(fo); sz_elf_hdrs = fpad8(fo);
total_out = sz_elf_hdrs;
total_in = xct_off;
//xct_off += asl_delta; // wait until ::pack3 //xct_off += asl_delta; // wait until ::pack3
memset(&linfo, 0, sizeof(linfo)); memset(&linfo, 0, sizeof(linfo));
@ -4321,25 +4324,42 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
{ {
Extent x; Extent x;
unsigned k; unsigned k;
bool const is_shlib = (0!=xct_off); unsigned const is_asl = (!!opt->o_unix.android_shlib) << 1; // bit 1
unsigned const is_shlib = (0!=xct_off) | is_asl;
// count passes, set ptload vars // count passes, set ptload vars
uip->ui_total_passes = 0; uip->ui_total_passes = 0;
for (k = 0; k < e_phnum; ++k) { for (k = 0; k < e_phnum; ++k) {
if (PT_LOAD64==get_te32(&phdri[k].p_type)) { if (PT_LOAD64==get_te32(&phdri[k].p_type)) {
uip->ui_total_passes++; if (!is_shlib) {
uip->ui_total_passes++;
}
else {
unsigned p_flags = get_te32(&phdri[k].p_flags);
if (Elf64_Phdr::PF_W & p_flags) {
// rtld might write, so cannot compress
}
else {
upx_uint64_t p_filesz = get_te64(&phdri[k].p_filesz);
// First PT_LOAD (partial) only if has instructions
if (k || xct_off < p_filesz) {
uip->ui_total_passes++;
}
}
}
if (find_LOAD_gap(phdri, k, e_phnum)) { if (find_LOAD_gap(phdri, k, e_phnum)) {
uip->ui_total_passes++; uip->ui_total_passes++;
} }
} }
} }
uip->ui_total_passes -= !!is_shlib; // not .data of shlib
// compress extents // compress extents
unsigned hdr_u_len = sizeof(Elf64_Ehdr) + sz_phdrs; unsigned hdr_u_len = sizeof(Elf64_Ehdr) + sz_phdrs;
total_in = (is_shlib ? 0 : xct_off); if (!(is_shlib & is_asl)) {
total_out = (is_shlib ? 0 : xct_off); total_in = 0;
total_out = 0;
}
uip->ui_pass = 0; uip->ui_pass = 0;
ft.addvalue = 0; ft.addvalue = 0;
@ -4363,9 +4383,9 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
x.offset = get_te64(&phdri[k].p_offset); x.offset = get_te64(&phdri[k].p_offset);
x.size = get_te64(&phdri[k].p_filesz); x.size = get_te64(&phdri[k].p_filesz);
if (is_shlib) { if (is_shlib) {
if (x.offset <= xct_off) { if (x.offset <= xct_off) { // first PT_LOAD
unsigned const len = umin(x.size, xct_off - x.offset); unsigned const len = umin(x.size, xct_off - x.offset);
if (len) { if (len && !is_asl) { // asl_pack1_Shdrs aleady handled
fi->seek(x.offset, SEEK_SET); fi->seek(x.offset, SEEK_SET);
fi->readx(ibuf, x.size); fi->readx(ibuf, x.size);
total_in += len; total_in += len;
@ -4394,9 +4414,14 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
x.offset = 0; x.offset = 0;
x.size = sz_elf_hdrs; x.size = sz_elf_hdrs;
if (is_asl) {
x.size = hdr_u_len;
}
unsigned in_size = x.size;
packExtent(x, nullptr, fo, 0, 0, true); packExtent(x, nullptr, fo, 0, 0, true);
total_in -= sz_elf_hdrs; total_in -= in_size;
// The rest of first PT_LOAD (above xct_off)
x.offset = xct_off; x.offset = xct_off;
x.size = get_te64(&phdri[k].p_filesz) - len; x.size = get_te64(&phdri[k].p_filesz) - len;
packExtent(x, &ft, fo, 0, 0, true); packExtent(x, &ft, fo, 0, 0, true);