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

work in progress for --android-shlib

modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
	modified:   stub/src/arm64-linux.shlib-init.S
This commit is contained in:
John Reiser 2018-01-11 09:39:26 -08:00
parent 28d1789783
commit cacb239040
5 changed files with 750 additions and 739 deletions

View File

@ -321,19 +321,21 @@ 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);
set_te32(&disp, asl_delta + firstpc_va - load_va);
}
fo->write(&disp, sizeof(disp));
fo->write(&disp, sizeof(disp)); // DT_INIT.d_val
len += sizeof(disp);
set_te32(&disp, hatch_off);
fo->write(&disp, sizeof(disp));
fo->write(&disp, sizeof(disp)); // offset(hatch)
len += sizeof(disp);
if (opt->o_unix.android_shlib) {
xct_off += asl_delta; // the extra page
}
set_te32(&disp, xct_off);
fo->write(&disp, sizeof(disp));
fo->write(&disp, sizeof(disp)); // offset(dst for f_exp)
len += sizeof(disp);
}
sz_pack2 = len; // 0 mod 8
@ -368,6 +370,8 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
fo->write(&hdr, sizeof(hdr));
flen = fpad4(fo);
set_te32(&elfout.phdr[0].p_filesz, sz_pack2 + lsize);
set_te32(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
if (0==xct_off) { // not shared library; adjust PT_LOAD
v_hole = page_mask & (~page_mask + v_hole + get_te32(&elfout.phdr[0].p_vaddr));
set_te32(&elfout.phdr[1].p_vaddr, v_hole);
@ -404,8 +408,8 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
set_te32(&phdr->p_align, align);
}
off += (align-1) & (ioff - off);
fi->seek(ioff, SEEK_SET); fi->readx(ibuf, len);
fo->seek( off, SEEK_SET); fo->write(ibuf, len);
fo->seek( off, SEEK_SET);
fo->write(ioff + file_image, len);
so_slide = off - ioff;
set_te32(&phdr->p_offset, so_slide + ioff);
}
@ -442,9 +446,25 @@ off_t PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
fo->rewrite(&word, sizeof(word));
flen = fo->seek(0, SEEK_END);
}
ehdri.e_shnum = 0;
ehdri.e_shoff = 0;
ehdri.e_shstrndx = 0;
if (opt->o_unix.android_shlib) {
// Update {DYNAMIC}.sh_offset by so_slide.
Elf32_Shdr *shdr = shdri;
for (unsigned j = 0; j < e_shnum; ++shdr, ++j) {
if (Elf32_Shdr::SHT_DYNAMIC == get_te32(&shdr->sh_type)) {
upx_uint32_t offset = get_te32(&shdr->sh_offset);
set_te32(&shdr->sh_offset, so_slide - asl_delta + offset );
fo->seek(j * sizeof(Elf32_Shdr) - asl_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;
}
}
return flen;
}
@ -500,7 +520,6 @@ 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);
@ -529,8 +548,8 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
set_te64(&phdr->p_align, align);
}
off += (align-1) & (ioff - off);
fi->seek(ioff, SEEK_SET); fi->readx(ibuf, len);
fo->seek( off, SEEK_SET); fo->write(ibuf, len);
fo->seek( off, SEEK_SET);
fo->write(ioff + file_image, len);
so_slide = off - ioff;
set_te64(&phdr->p_offset, so_slide + ioff);
}
@ -538,11 +557,6 @@ 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
}
@ -578,8 +592,8 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
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);
set_te64(&shdr->sh_offset, so_slide - asl_delta + offset );
fo->seek(j * sizeof(Elf64_Shdr) - asl_delta + xct_off, SEEK_SET);
fo->rewrite(shdr, sizeof(*shdr));
fo->seek(0, SEEK_END);
break;
@ -1761,6 +1775,14 @@ bool PackLinuxElf32::canPack()
if (sec_dynsym)
sec_dynstr = get_te32(&sec_dynsym->sh_link) + shdri;
sec_strndx = &shdri[get_te16(&ehdr->e_shstrndx)];
shstrtab = (char const *)(get_te32(&sec_strndx->sh_offset) + file_image);
if (Elf32_Shdr::SHT_STRTAB != get_te32(&sec_strndx->sh_type)
|| 0!=strcmp((char const *)".shstrtab",
&shstrtab[get_te32(&sec_strndx->sh_name)]) ) {
throwCantPack("bad e_shstrndx");
}
phdr= phdri;
for (int j= e_phnum; --j>=0; ++phdr)
if (Elf32_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) {
@ -1954,7 +1976,7 @@ PackLinuxElf64::canPack()
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
if (sec_dynsym)
sec_dynstr = get_te64(&sec_dynsym->sh_link) + shdri;
sec_dynstr = get_te32(&sec_dynsym->sh_link) + shdri;
sec_strndx = &shdri[get_te16(&ehdr->e_shstrndx)];
shstrtab = (char const *)(get_te64(&sec_strndx->sh_offset) + file_image);
@ -2483,7 +2505,7 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
sz_phdrs = e_phnum * get_te16(&ehdri.e_phentsize);
// Remember all PT_NOTE, and find lg2_page from PT_LOAD.
Elf32_Phdr const *phdr = phdri;
Elf32_Phdr *phdr = phdri;
note_size = 0;
for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
if (phdr->PT_NOTE32 == get_te32(&phdr->p_type)) {
@ -2521,32 +2543,128 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
progid = 0; // getRandomId(); not useful, so do not clutter
if (0!=xct_off) { // shared library
fi->seek(0, SEEK_SET);
fi->readx(ibuf, xct_off);
sz_elf_hdrs = xct_off;
fo->write(ibuf, 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" ("Oreo"),
// we will splice-in a 4KiB page that contains an "extra" copy
// of the Shdr and shstrtab.
xct_va += asl_delta;
//xct_off += asl_delta; // not yet
// Relocate PT_DYNAMIC (in 2nd PT_LOAD)
Elf32_Dyn *dyn = const_cast<Elf32_Dyn *>(dynseg);
for (; dyn->d_tag; ++dyn) {
unsigned d_tag = get_te32(&dyn->d_tag);
if (Elf32_Dyn::DT_INIT_ARRAY == d_tag
|| Elf32_Dyn::DT_FINI_ARRAY == d_tag
|| Elf32_Dyn::DT_PREINIT_ARRAY == d_tag) {
unsigned d_val = get_te32(&dyn->d_val);
set_te32(&dyn->d_val, asl_delta + d_val);
}
}
// Relocate dynsym (DT_SYMTAB) which is below xct_va
Elf32_Sym *sym = const_cast<Elf32_Sym *>(dynsym);
unsigned off_dynsym = get_te32(&sec_dynsym->sh_offset);
unsigned sz_dynsym = get_te32(&sec_dynsym->sh_size);
for (int j = sz_dynsym / sizeof(Elf32_Sym); --j>=0; ++sym) {
unsigned symval = get_te32(&sym->st_value);
unsigned symsec = get_te16(&sym->st_shndx);
if (Elf32_Sym::SHN_UNDEF != symsec
&& Elf32_Sym::SHN_ABS != symsec
&& xct_off <= symval) {
set_te32(&sym->st_value, asl_delta + symval);
}
}
fo->seek(off_dynsym, SEEK_SET); fo->rewrite(dynsym, sz_dynsym);
set_te32(&ehdri.e_shoff, sz_elf_hdrs);
fo->seek(0, SEEK_SET); fo->rewrite(&ehdri, sizeof(ehdri));
// Relocate Phdr virtual addresses, but not physical offsets and sizes
/* Elf32_Phdr * */ phdr = phdri;
for (int j = e_phnum; --j>=0; ++phdr) {
unsigned offset = get_te32(&phdr->p_offset);
if (xct_off <= offset) { // above the extra page
//set_te32(&phdr->p_offset, asl_delta + offset); // physical
unsigned addr = get_te32(&phdr->p_paddr);
set_te32(&phdr->p_paddr, asl_delta + addr);
addr = get_te32(&phdr->p_vaddr);
set_te32(&phdr->p_vaddr, asl_delta + addr);
}
// .p_filesz,.p_memsz are updated in ::pack3
}
fo->rewrite(phdri, e_phnum * sizeof(Elf32_Phdr)); // adjacent to Ehdr
// Relocate Shdr; and Rela, Rel (below xct_off)
Elf32_Shdr *shdr = shdri;
unsigned sz_shstrtab = get_te32(&sec_strndx->sh_size);
for (int j = e_shnum; --j>=0; ++shdr) {
unsigned sh_type = get_te32(&shdr->sh_type);
unsigned sh_size = get_te32(&shdr->sh_size);
unsigned sh_offset = get_te32(&shdr->sh_offset);
unsigned sh_entsize = get_te32(&shdr->sh_entsize);
if (xct_off <= sh_offset) {
set_te32(&shdr->sh_offset, asl_delta + sh_offset);
uint32_t addr = get_te32(&shdr->sh_addr);
set_te32(&shdr->sh_addr, asl_delta + addr);
}
if (Elf32_Shdr::SHT_RELA== sh_type) {
if (sizeof(Elf32_Rela) != sh_entsize) {
char msg[50];
snprintf(msg, sizeof(msg), "bad Rela.sh_entsize %u", sh_entsize);
throwCantPack(msg);
}
Elf32_Rela *rela = (Elf32_Rela *)(sh_offset + file_image);
for (int k = sh_size / sh_entsize; --k >= 0; ++rela) {
unsigned r_offset = get_te32(&rela->r_offset);
if (xct_off <= r_offset) {
set_te32(&rela->r_offset, asl_delta + r_offset);
}
}
fo->seek(sh_offset, SEEK_SET);
fo->rewrite(sh_offset + file_image, sh_size);
}
if (Elf32_Shdr::SHT_REL == sh_type) {
if (sizeof(Elf32_Rel) != sh_entsize) {
char msg[50];
snprintf(msg, sizeof(msg), "bad Rel.sh_entsize %u", sh_entsize);
throwCantPack(msg);
}
Elf32_Rel *rel = (Elf32_Rel *)(sh_offset + file_image);
for (int k = sh_size / sh_entsize; --k >= 0; ++rel) {
unsigned r_offset = get_te32(&rel->r_offset);
if (xct_off <= r_offset) {
set_te32(&rel->r_offset, asl_delta + r_offset);
}
}
fo->seek(sh_offset, SEEK_SET);
fo->rewrite(sh_offset + file_image, sh_size);
}
}
// New copy of Shdr
set_te32(&sec_strndx->sh_offset, (e_shnum * sizeof(Elf32_Shdr)) + sz_elf_hdrs);
fo->seek(xct_off, SEEK_SET); fo->write(shdri, e_shnum * sizeof(Elf32_Shdr));
// New copy of Shdr[.e_shstrndx].[ sh_offset, +.sh_size )
fo->write(shstrtab, sz_shstrtab);
sz_elf_hdrs = fpad4(fo);
//xct_off += asl_delta; // wait until ::pack3
}
memset(&linfo, 0, sizeof(linfo));
fo->write(&linfo, sizeof(linfo));
}
// if the preserve build-id option was specified
if (opt->o_unix.preserve_build_id) {
Elf32_Shdr *shdr = NULL;
Elf32_Shdr *tmp = shdri;
if (! shdri) {
shdr = New(Elf32_Shdr, e_shnum);
fi->seek(0,SEEK_SET);
fi->seek(ehdri.e_shoff,SEEK_SET);
fi->readx((void*)shdr,ehdri.e_shentsize*ehdri.e_shnum);
// set this so we can use elf_find_section_name
shdri = (Elf32_Shdr *)shdr;
// set this so we can use elf_find_section_name
e_shnum = get_te16(&ehdri.e_shnum);
if (!shdri) {
shdri = (Elf32_Shdr *)&file_image[get_te32(&ehdri.e_shoff)];
}
//set the shstrtab
sec_strndx = &shdri[get_te16(&ehdri.e_shstrndx)];
@ -2579,14 +2697,6 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
shdrout.shdr[2].sh_name = 20;
shdrout.shdr[2].sh_size = 29; //size of our static shstrtab
}
// repoint shdr in case it is used by code some where else
if (shdr) {
shdri = tmp;
delete [] shdr;
shdr = NULL;
sec_strndx = NULL;
}
}
}
@ -2732,9 +2842,8 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
// 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);
xct_va += delta;
//xct_off += delta; // not yet
xct_va += asl_delta;
//xct_off += asl_delta; // not yet
// Relocate PT_DYNAMIC (in 2nd PT_LOAD)
Elf64_Dyn *dyn = const_cast<Elf64_Dyn *>(dynseg);
@ -2744,7 +2853,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|| Elf64_Dyn::DT_FINI_ARRAY == d_tag
|| Elf64_Dyn::DT_PREINIT_ARRAY == d_tag) {
uint64_t d_val = get_te64(&dyn->d_val);
set_te64(&dyn->d_val, delta + d_val);
set_te64(&dyn->d_val, asl_delta + d_val);
}
}
@ -2758,7 +2867,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
if (Elf64_Sym::SHN_UNDEF != symsec
&& Elf64_Sym::SHN_ABS != symsec
&& xct_off <= symval) {
set_te64(&sym->st_value, delta + symval);
set_te64(&sym->st_value, asl_delta + symval);
}
}
fo->seek(off_dynsym, SEEK_SET); fo->rewrite(dynsym, sz_dynsym);
@ -2771,11 +2880,11 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
for (int j = e_phnum; --j>=0; ++phdr) {
uint64_t offset = get_te64(&phdr->p_offset);
if (xct_off <= offset) { // above the extra page
//set_te64(&phdr->p_offset, delta + offset); // physical
//set_te64(&phdr->p_offset, asl_delta + offset); // physical
uint64_t addr = get_te64(&phdr->p_paddr);
set_te64(&phdr->p_paddr, delta + addr);
set_te64(&phdr->p_paddr, asl_delta + addr);
addr = get_te64(&phdr->p_vaddr);
set_te64(&phdr->p_vaddr, delta + addr);
set_te64(&phdr->p_vaddr, asl_delta + addr);
}
// .p_filesz,.p_memsz are updated in ::pack3
}
@ -2790,9 +2899,9 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
uint64_t sh_offset = get_te64(&shdr->sh_offset);
uint64_t sh_entsize = get_te64(&shdr->sh_entsize);
if (xct_off <= sh_offset) {
set_te64(&shdr->sh_offset, delta + sh_offset);
set_te64(&shdr->sh_offset, asl_delta + sh_offset);
uint64_t addr = get_te64(&shdr->sh_addr);
set_te64(&shdr->sh_addr, delta + addr);
set_te64(&shdr->sh_addr, asl_delta + addr);
}
if (Elf64_Shdr::SHT_RELA== sh_type) {
if (sizeof(Elf64_Rela) != sh_entsize) {
@ -2804,7 +2913,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
for (int k = sh_size / sh_entsize; --k >= 0; ++rela) {
uint64_t r_offset = get_te64(&rela->r_offset);
if (xct_off <= r_offset) {
set_te64(&rela->r_offset, delta + r_offset);
set_te64(&rela->r_offset, asl_delta + r_offset);
}
}
fo->seek(sh_offset, SEEK_SET);
@ -2820,7 +2929,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
for (int k = sh_size / sh_entsize; --k >= 0; ++rel) {
uint64_t r_offset = get_te64(&rel->r_offset);
if (xct_off <= r_offset) {
set_te64(&rel->r_offset, delta + r_offset);
set_te64(&rel->r_offset, asl_delta + r_offset);
}
}
fo->seek(sh_offset, SEEK_SET);
@ -2835,11 +2944,8 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
// New copy of Shdr[.e_shstrndx].[ sh_offset, +.sh_size )
fo->write(shstrtab, sz_shstrtab);
// Fill the 4KiB page
MemBuffer spacer(delta - (sz_shstrtab + e_shnum * sizeof(Elf64_Shdr)));
spacer.clear(); fo->write(spacer, spacer.getSize());
sz_elf_hdrs += delta;
xct_off += delta;
sz_elf_hdrs = fpad4(fo);
//xct_off += asl_delta; // wait until ::pack3
}
memset(&linfo, 0, sizeof(linfo));
fo->write(&linfo, sizeof(linfo));
@ -2849,24 +2955,9 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
if (opt->o_unix.preserve_build_id) {
// set this so we can use elf_find_section_name
e_shnum = get_te16(&ehdri.e_shnum);
// there is a class member similar to this, but I did not
// want to assume it would be available
Elf64_Shdr *tmp = shdri;
Elf64_Shdr *shdr = NULL;
if (! shdri) {
shdr = New(Elf64_Shdr, e_shnum);
fi->seek(0,SEEK_SET);
fi->seek(ehdri.e_shoff,SEEK_SET);
fi->readx((void*)shdr,ehdri.e_shentsize*ehdri.e_shnum);
// set this so we can use elf_find_section_name
shdri = (Elf64_Shdr *)shdr;
if (!shdri) {
shdri = (Elf64_Shdr *)&file_image[get_te32(&ehdri.e_shoff)];
}
//set the shstrtab
sec_strndx = &shdri[get_te16(&ehdri.e_shstrndx)];
@ -2899,12 +2990,6 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
shdrout.shdr[2].sh_name = 20;
shdrout.shdr[2].sh_size = 29; //size of our static shstrtab
}
if (shdr) {
shdri = tmp;
delete [] shdr;
shdr = NULL;
}
}
}
@ -3003,7 +3088,7 @@ int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
? (sizeof(Elf32_Ehdr) + sz_phdrs) // main executable
: xct_off; // shared library
if (ft.id < 0x40) {
// FIXME: ?? ft.addvalue += delta;
// FIXME: ?? ft.addvalue += asl_delta;
}
x.offset += delta;
x.size -= delta;
@ -3112,7 +3197,7 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
? (sizeof(Elf64_Ehdr) + sz_phdrs) // main executable
: xct_off; // shared library
if (ft.id < 0x40) {
// FIXME: ?? ft.addvalue += delta;
// FIXME: ?? ft.addvalue += asl_delta;
}
x.offset += delta;
x.size -= delta;
@ -3277,82 +3362,6 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
fo->write(buildid_data,shdrout.shdr[1].sh_size);
}
if (0!=xct_off) { // shared library
if (opt->o_unix.android_shlib && shdri) { // dlopen() checks Elf32_Shdr vs Elf32_Phdr
unsigned load0_hi = ~0u;
Elf32_Phdr const *phdr = phdri;
for (unsigned j = 0; j < e_phnum; ++j, ++phdr) {
unsigned load0_lo = get_te32(&phdr->p_vaddr);
unsigned load0_sz = get_te32(&phdr->p_memsz);
if (PT_LOAD32==get_te32(&phdr->p_type)
&& (xct_off - load0_lo) < load0_sz) {
load0_hi = load0_lo + load0_sz;
break;
}
}
MemBuffer smap(e_shnum); smap.clear(); // smap[0] = 0; // SHN_UNDEF
MemBuffer snew(e_shnum * sizeof(*shdri));
Elf32_Shdr const *shdr = shdri;
unsigned k = 0;
for (unsigned j = 0; j < e_shnum; ++j, ++shdr) {
// Select some Elf32_Shdr by .sh_type
unsigned const type = get_te32(&shdr->sh_type);
unsigned const flags = get_te32(&shdr->sh_flags);
if (((Elf32_Shdr::SHT_STRTAB == type) && (Elf32_Shdr::SHF_ALLOC & flags))
|| ((Elf32_Shdr::SHT_DYNAMIC == type) && (Elf32_Shdr::SHF_ALLOC & flags))
|| ((Elf32_Shdr::SHT_ARM_ATTRIBUTES == type))
|| ( ((1+ Elf32_Shdr::SHT_LOOS) <= type) // SHT_ANDROID_REL
&& ((2+ Elf32_Shdr::SHT_LOOS) >= type)) // SHT_ANDROID_RELA
) {
Elf32_Shdr *const sptr = k + (Elf32_Shdr *)(void *)snew;
unsigned va = get_te32(&shdr->sh_addr);
if (xct_off <= va && va <= load0_hi) {
throwCantPack("Android-required Shdr in packed region");
}
*sptr = *shdr; // copy old Elf32_Shdr
smap[j] = 1+ k++; // for later forwarding
}
}
if (k && fo) {
unsigned const new_shoff = fpad4(fo);
unsigned xtra_off = ((1+ k) * sizeof(*shdri)) + new_shoff; // 1+: shdr_undef
set_te32(&ehdri.e_shoff, new_shoff);
set_te16(&ehdri.e_shentsize, sizeof(*shdri));
set_te16(&ehdri.e_shnum, 1+ k);
Elf32_Shdr shdr_undef; memset(&shdr_undef, 0, sizeof(shdr_undef));
fo->write(&shdr_undef, sizeof(shdr_undef));
unsigned arm_attr_offset = 0;
unsigned arm_attr_size = 0;
for (unsigned j = 0; j < k; ++j) { // forward .sh_link
Elf32_Shdr *const sptr = j + (Elf32_Shdr *)(void *)snew;
unsigned const type = get_te32(&sptr->sh_type);
// work-around for https://bugs.launchpad.net/bugs/1712938
if (Elf32_Shdr::SHT_ARM_ATTRIBUTES == type) {
arm_attr_offset = get_te32(&sptr->sh_offset);
arm_attr_size = get_te32(&sptr->sh_size);
set_te32(&sptr->sh_offset, xtra_off);
xtra_off += get_te32(&sptr->sh_size);
}
if (Elf32_Shdr::SHT_STRTAB == type) { // any SHT_STRTAB should work
set_te16(&elfout.ehdr.e_shstrndx, 1+ j); // 1+: shdr_undef
set_te16( &ehdri.e_shstrndx, 1+ j); // 1+: shdr_undef
}
unsigned sh_offset = get_te32(&sptr->sh_offset);
if (xct_off <= sh_offset) {
set_te32(&sptr->sh_offset, so_slide + sh_offset);
}
sptr->sh_name = 0; // we flushed .e_shstrndx
set_te16(&sptr->sh_link, smap[sptr->sh_link]);
set_te16(&sptr->sh_info, smap[sptr->sh_info]); // ?
}
fo->write(snew, k * sizeof(*shdri));
if (arm_attr_offset) {
fo->write(&file_image[arm_attr_offset], arm_attr_size);
}
}
}
}
// Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
@ -3415,11 +3424,6 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
fo->write(buildid_data,shdrout.shdr[1].sh_size);
}
if (0!=xct_off) { // shared library
if (opt->o_unix.android_shlib && shdri) {
//xct_off += (1<<12);
}
}
// Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel
// tries to make .bss, which requires PF_W.
// But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.
@ -3431,7 +3435,7 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
if (0!=xct_off) { // shared library
fo->rewrite(&ehdri, sizeof(ehdri));
fo->rewrite(phdri, e_phnum * sizeof(*phdri));
fo->seek(xct_off, SEEK_SET);
fo->seek(sz_elf_hdrs, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo));
}
else {

View File

@ -68,6 +68,7 @@ protected:
static unsigned gnu_hash(char const *) /*const*/;
protected:
unsigned int const asl_delta = (1u<<12); // --android-shlib extra page
unsigned e_type;
unsigned e_phnum; /* Program header table entry count */
unsigned e_shnum;
@ -174,7 +175,7 @@ protected:
Elf32_Sym const *jni_onload_sym;
char const *shstrtab; // via Elf32_Shdr
Elf32_Shdr const *sec_strndx;
Elf32_Shdr *sec_strndx;
Elf32_Shdr const *sec_dynsym;
Elf32_Shdr const *sec_dynstr;

File diff suppressed because it is too large Load Diff

View File

@ -120,10 +120,13 @@ sp_frame = 24 * NBPW
.endm
section ELFMAINX
// .long distance back to first b_info
// .long offset(.) // detect relocation
// .long offset(user DT_INIT)
// .long offset(escape_hatch)
// .long offset({l_info; p_info; b_info; compressed data})
// .long offset(xct_off) dst of f_exp
_start: .globl _start
brk #0 // debugging
slot f_argc // 0
slot f_argv // 1
@ -132,8 +135,6 @@ sp_frame = 24 * NBPW
slot f_PMASK // 4 PAGE_MASK
slot f_my_ra // 5
_start: .globl _start
// brk #0 // debugging
stp arg1,arg2,[sp,#f_argc - sp_frame]! // f_argv
stp arg3,x0, [sp,#f_envp] // %f_uinit
str lr, [sp,#f_my_ra]
@ -213,22 +214,24 @@ main:
// 12. goto user DT_INIT
mov rdx,lr // &f_decompress
add rsi,rdx,# _start - f_decompress - 4*4
add rsi,rdx,# _start - f_decompress - 5*4
#define lodsl ldr eax,[rsi],#4
#define lodslu lodsl
lodsl; mov tmp,eax // distance back to 1st b_info
mov rcx,rsi
lodsl; sub rcx,rcx,rax; //str ecx,[sp,#o_reloc]
sub tmpx,rsi,tmpx // &b_info
lodsl; add rax,rcx,rax; str rax,[sp,#f_uinit] // reloc DT_INIT for step 12
slot o_hatch // 6
lodsl; add rax,rcx,rax; str rax,[sp,#o_hatch] // reloc &hatch for step 10
lodsl; add rdi,rcx,rax // &l_info; also destination for decompress
add rsi,rdi,#sz_l_info + sz_p_info // &b_info
lodsl; add rdi,rcx,rax // destination for decompress
mov rsi,tmpx // &b_info
slot p_unmap,2 // 7
ldr eax,[rsi,#sz_cpr]; add rsi,rsi,#sz_b_info // sz_cpr
ldr eax,[rsi,#sz_cpr]; add rsi,rsi,#sz_b_info
add rsi,rsi,rax // skip unpack helper block
ldr ecx,[sp,#f_PMASK]
@ -318,6 +321,7 @@ supervise:
ldr rax,[sp,#o_uncpr]
ldp arg1,arg2,[sp,#0*NBPW + p_uncpr]
ldp arg3,arg4,[sp,#2*NBPW + p_uncpr]
brk #0
blr rax // decompress
bl L620
@ -349,6 +353,7 @@ L620: // Implant escape hatch at end of .text
ldp arg1,arg2,[sp,#0*NBPW + p_unmap]
mov w8,#__NR_munmap
ldp arg3,arg4,[sp,#2*NBPW + f_argc] // f_uinit
brk #0
br arg5 // goto hatch
movsl_subr:

View File

@ -2,21 +2,21 @@ file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 ELFMAINX 00000010 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, RELOC, READONLY
1 NRV_HEAD 00000000 0000000000000000 0000000000000000 00000050 2**0 CONTENTS, READONLY
2 NRV_TAIL 00000000 0000000000000000 0000000000000000 00000050 2**0 CONTENTS, READONLY
3 NRV2E 00000128 0000000000000000 0000000000000000 00000050 2**0 CONTENTS, READONLY
4 NRV2D 0000011c 0000000000000000 0000000000000000 00000178 2**0 CONTENTS, READONLY
5 NRV2B 000000f0 0000000000000000 0000000000000000 00000294 2**0 CONTENTS, READONLY
6 LZMA_ELF00 000000d0 0000000000000000 0000000000000000 00000384 2**0 CONTENTS, RELOC, READONLY
7 LZMA_DEC20 00000968 0000000000000000 0000000000000000 00000454 2**0 CONTENTS, READONLY
8 LZMA_DEC10 0000049c 0000000000000000 0000000000000000 00000dbc 2**0 CONTENTS, READONLY
9 LZMA_DEC30 00000000 0000000000000000 0000000000000000 00001258 2**0 CONTENTS, READONLY
10 ELFMAINY 0000003e 0000000000000000 0000000000000000 00001258 2**0 CONTENTS, READONLY
11 ELFMAINZ 00000000 0000000000000000 0000000000000000 00001296 2**0 CONTENTS, READONLY
12 ELFMAJNZ 00000024 0000000000000000 0000000000000000 00001296 2**0 CONTENTS, READONLY
13 ANDMAJNZ 00000004 0000000000000000 0000000000000000 000012ba 2**0 CONTENTS, READONLY
14 ELFMAKNZ 00000290 0000000000000000 0000000000000000 000012be 2**0 CONTENTS, READONLY
0 ELFMAINX 00000014 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, RELOC, READONLY
1 NRV_HEAD 00000000 0000000000000000 0000000000000000 00000054 2**0 CONTENTS, READONLY
2 NRV_TAIL 00000000 0000000000000000 0000000000000000 00000054 2**0 CONTENTS, READONLY
3 NRV2E 00000128 0000000000000000 0000000000000000 00000054 2**0 CONTENTS, READONLY
4 NRV2D 0000011c 0000000000000000 0000000000000000 0000017c 2**0 CONTENTS, READONLY
5 NRV2B 000000f0 0000000000000000 0000000000000000 00000298 2**0 CONTENTS, READONLY
6 LZMA_ELF00 000000d0 0000000000000000 0000000000000000 00000388 2**0 CONTENTS, RELOC, READONLY
7 LZMA_DEC20 00000968 0000000000000000 0000000000000000 00000458 2**0 CONTENTS, READONLY
8 LZMA_DEC10 0000049c 0000000000000000 0000000000000000 00000dc0 2**0 CONTENTS, READONLY
9 LZMA_DEC30 00000000 0000000000000000 0000000000000000 0000125c 2**0 CONTENTS, READONLY
10 ELFMAINY 0000003e 0000000000000000 0000000000000000 0000125c 2**0 CONTENTS, READONLY
11 ELFMAINZ 00000000 0000000000000000 0000000000000000 0000129a 2**0 CONTENTS, READONLY
12 ELFMAJNZ 00000024 0000000000000000 0000000000000000 0000129a 2**0 CONTENTS, READONLY
13 ANDMAJNZ 00000004 0000000000000000 0000000000000000 000012be 2**0 CONTENTS, READONLY
14 ELFMAKNZ 000002a4 0000000000000000 0000000000000000 000012c2 2**0 CONTENTS, READONLY
SYMBOL TABLE:
0000000000000000 l d LZMA_DEC30 0000000000000000 LZMA_DEC30
0000000000000000 l d ELFMAINZ 0000000000000000 ELFMAINZ
@ -42,7 +42,7 @@ SYMBOL TABLE:
RELOCATION RECORDS FOR [ELFMAINX]:
OFFSET TYPE VALUE
000000000000000c R_AARCH64_CALL26 ELFMAINZ
0000000000000010 R_AARCH64_CALL26 ELFMAINZ
RELOCATION RECORDS FOR [LZMA_ELF00]:
OFFSET TYPE VALUE