work in progress for --android-shlib

modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser 2018-01-08 14:04:38 -08:00
parent 633eb98e34
commit 28d1789783

View File

@ -321,6 +321,10 @@ off_t PackLinuxElf::pack3(OutputFile *fo, Filter &ft) // return length of output
? jni_onload_va
: elf_unsigned_dynamic(Elf32_Dyn::DT_INIT) );
set_te32(&disp, firstpc_va - load_va);
unsigned const delta = (1<<12);
if (opt->o_unix.android_shlib) { // the extra page
set_te32(&disp, delta + firstpc_va - load_va);
}
fo->write(&disp, sizeof(disp));
len += sizeof(disp);
@ -496,6 +500,7 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
unsigned off = fo->st_size();
unsigned off_init = 0; // where in file
upx_uint64_t va_init = sz_pack2; // virtual address
unsigned const delta = (1u<<12); // for android_shlib
so_slide = 0;
for (int j = e_phnum; --j>=0; ++phdr) {
upx_uint64_t const len = get_te64(&phdr->p_filesz);
@ -533,6 +538,11 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
va_init += get_te64(&phdr->p_vaddr);
set_te64(&phdr->p_filesz, sz_pack2 + lsize);
set_te64(&phdr->p_memsz, sz_pack2 + lsize);
if (opt->o_unix.android_shlib) { // the extra page
//va_init += delta; // sz_pack2 already includes delta?
set_te64(&phdr->p_filesz, delta + sz_pack2 + lsize);
set_te64(&phdr->p_memsz, delta + sz_pack2 + lsize);
}
}
continue; // all done with this PT_LOAD
}
@ -555,13 +565,28 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
if (xct_off < ioff)
set_te64(&phdr->p_offset, so_slide + ioff);
} // end each Phdr
if (off_init) { // change DT_INIT.d_val
fo->seek(off_init, SEEK_SET);
upx_uint64_t word; set_te64(&word, va_init);
fo->rewrite(&word, sizeof(word));
flen = fo->seek(0, SEEK_END);
}
if (!opt->o_unix.android_shlib) {
if (opt->o_unix.android_shlib) {
// Update {DYNAMIC}.sh_offset by so_slide.
Elf64_Shdr *shdr = shdri;
for (unsigned j = 0; j < e_shnum; ++shdr, ++j) {
if (Elf64_Shdr::SHT_DYNAMIC == get_te32(&shdr->sh_type)) {
upx_uint64_t offset = get_te64(&shdr->sh_offset);
set_te64(&shdr->sh_offset, so_slide - delta + offset );
fo->seek(j * sizeof(Elf64_Shdr) - delta + xct_off, SEEK_SET);
fo->rewrite(shdr, sizeof(*shdr));
fo->seek(0, SEEK_END);
break;
}
}
}
else { // !opt->o_unix.android_shlib)
ehdri.e_shnum = 0;
ehdri.e_shoff = 0;
ehdri.e_shstrndx = 0;
@ -2704,7 +2729,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
sz_elf_hdrs = xct_off;
fo->write(file_image, xct_off); // before the first SHF_EXECINSTR (typ ".plt")
if (opt->o_unix.android_shlib) {
// In order to pacify the runtime linker on Android "O",
// In order to pacify the runtime linker on Android "O" ("Oreo"),
// we will splice-in a 4KiB page that contains an "extra" copy
// of the Shdr and shstrtab.
unsigned const delta = (1u<<12);
@ -2752,14 +2777,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
addr = get_te64(&phdr->p_vaddr);
set_te64(&phdr->p_vaddr, delta + addr);
}
if (0 // physical: not yet
&& 0==phdr->p_offset && Elf64_Phdr::PT_LOAD==get_te32(&phdr->p_type)) {
// Extend by the extra page.
uint64_t size = get_te64(&phdr->p_filesz);
set_te64(&phdr->p_filesz, delta + size);
size = get_te64(&phdr->p_memsz);
set_te64(&phdr->p_memsz, delta + size);
}
// .p_filesz,.p_memsz are updated in ::pack3
}
fo->rewrite(phdri, e_phnum * sizeof(Elf64_Phdr)); // adjacent to Ehdr