WIP: handling shared library

modified:   p_lx_elf.cpp
	modified:   p_unix.cpp
	modified:   p_unix.h
This commit is contained in:
John Reiser 2021-05-22 16:03:53 -07:00 committed by Markus F.X.J. Oberhumer
parent ef5b55b4d1
commit d5263a56ce
3 changed files with 44 additions and 9 deletions

View File

@ -599,7 +599,8 @@ off_t PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
fo->rewrite(&file_image[off2], 2*sizeof(word));
}
}
else if (xct_off < ioff) { // Slide subsequent PT_LOAD.
else if (j && (Elf64_Phdr::PF_W & get_te64(&phdr->p_flags))
&& xct_off < ioff) { // Slide subsequent PT_LOAD.
// AMD64 chip supports page sizes of 4KiB, 2MiB, and 1GiB;
// the operating system chooses one. .p_align typically
// is a forward-looking 2MiB. In 2009 Linux chooses 4KiB.
@ -3712,11 +3713,13 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
progid = 0; // getRandomId(); not useful, so do not clutter
sz_elf_hdrs = sizeof(ehdri) + sz_phdrs;
if (0!=xct_off) { // shared library
sz_elf_hdrs = xct_off;
lowmem.alloc(xct_off + (!opt->o_unix.android_shlib
? 0
: e_shnum * sizeof(Elf64_Shdr)));
memcpy(lowmem, file_image, xct_off); // android omits Shdr here
}
if (0!=xct_off && opt->o_unix.android_shlib) { // Android shared library
sz_elf_hdrs = xct_off;
fo->write(lowmem, xct_off); // < SHF_EXECINSTR (typ: in .plt or .init)
if (opt->o_unix.android_shlib) {
// In order to pacify the runtime linker on Android "O" ("Oreo"),
@ -4225,9 +4228,39 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
}
x.offset = get_te64(&phdri[k].p_offset);
x.size = get_te64(&phdri[k].p_filesz);
if (!is_shlib || hdr_u_len < (u64_t)x.size) {
if (is_shlib) {
if (x.offset <= xct_off) {
unsigned const len = umin(x.size, xct_off - x.offset);
if (len) {
fi->seek(x.offset, SEEK_SET);
fi->readx(ibuf, x.size);
total_in += len;
fo->seek(x.offset, SEEK_SET);
fo->write(ibuf, len);
total_out += len;
}
if (len != x.size) {
x.offset = 0;
x.size = sz_elf_hdrs;
packExtent(x, nullptr, fo, 0, 0, true);
total_in -= sz_elf_hdrs;
x.offset = xct_off;
x.size = get_te64(&phdri[k].p_filesz) - len;
packExtent(x, &ft, fo, 0, 0, true);
}
}
else {
if (!(Elf64_Phdr::PF_W & get_te64(&phdri[k].p_flags))) {
packExtent(x, &ft, fo, 0, 0, true);
}
// else wait until slide
}
}
else if (hdr_u_len < (u64_t)x.size) {
if (0 == nx) { // 1st PT_LOAD64 must cover Ehdr at 0==p_offset
unsigned const delta = (is_shlib ? xct_off : hdr_u_len);
unsigned const delta = hdr_u_len;
if (ft.id < 0x40) {
// FIXME: ?? ft.addvalue += asl_delta;
}
@ -4247,7 +4280,7 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
// sometimes marks as PF_X anyway. So filter only first segment.
if (k == nk_f || !is_shlib) {
packExtent(x,
(k==nk_f ? &ft : nullptr ), fo, hdr_u_len);
(k==nk_f ? &ft : nullptr ), fo, hdr_u_len, 0, true);
}
else {
total_in += x.size;

View File

@ -321,7 +321,8 @@ void PackUnix::packExtent(
Filter *ft,
OutputFile *fo,
unsigned hdr_u_len,
unsigned b_extra
unsigned b_extra,
bool inhibit_compression_check
)
{
unsigned const init_u_adler = ph.u_adler;
@ -363,7 +364,7 @@ void PackUnix::packExtent(
ft->cto = 0;
compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
0, 0, 0, hdr_ibuf, hdr_u_len);
0, 0, 0, hdr_ibuf, hdr_u_len, inhibit_compression_check);
}
else {
(void) compress(ibuf, ph.u_len, obuf); // ignore return value

View File

@ -74,7 +74,8 @@ protected:
};
virtual void packExtent(const Extent &x,
Filter *, OutputFile *,
unsigned hdr_len = 0, unsigned b_extra = 0);
unsigned hdr_len = 0, unsigned b_extra = 0 ,
bool inhibit_compression_check = false);
virtual void unpackExtent(unsigned wanted, OutputFile *fo,
unsigned &c_adler, unsigned &u_adler,
bool first_PF_X, unsigned szb_info, bool is_rewrite = false);