WIP: de-compression of old-style shlib

modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser
2021-09-06 08:43:20 -07:00
committed by Markus F.X.J. Oberhumer
parent 02bd9cc403
commit bd441e83ae
+22 -8
View File
@@ -4673,7 +4673,7 @@ PackLinuxElf64::unRela64(
fo->rewrite(rela0, relasz);
}
// File layout of compressed .so shared library:
// File layout of compressed .so (new-style: 3 or 4 PT_LOAD) shared library:
// 1. new Elf headers: Ehdr, PT_LOAD (r-x), PT_LOAD (rw-, if any), non-PT_LOAD Phdrs
// 2. Space for (original - 2) PT_LOAD Phdr
// 3. Remaining original contents of file below xct_off
@@ -4748,8 +4748,14 @@ void PackLinuxElf64::un_shlib_1(
}
}
// Decompress first Extent. Old style covers [0, xct_off);
// new style covers just Elf headers: the rest below xct_off is constant!
// Decompress first Extent. Old style covers [0, xct_off)
// which includes rtld constant data and eXecutable app code below DT_INIT.
// In old style, the first compressed Extent is redundant
// except for the compressed original Elf headers.
// New style covers just Elf headers: the rest below xct_off is
// rtld constant data: DT_*HASH, DT_SYMTAB, DT_STRTAB, etc.
// New style puts eXecutable app code in second PT_LOAD
// in order to mark Elf headers and rtld data as non-eXecutable.
fi->seek(xct_off, SEEK_SET);
struct {
struct l_info l;
@@ -4774,14 +4780,16 @@ void PackLinuxElf64::un_shlib_1(
u_fi.readx((void *)o_elfhdrs,o_elfhdrs.getSize());
u_fi.close();
// New style: not compressed, up to xct_off
if (ph.u_len < xct_off) {
Elf64_Phdr const *t_phdr = (Elf64_Phdr const *)(1+ (Elf64_Ehdr const *)(void const *)o_elfhdrs);
unsigned t_flags = get_te32(&t_phdr->p_flags);
// New style: 1st PT_LOAD has no eXecutable code
if (!(Elf64_Phdr::PF_X & t_flags)) {
if (fo) {
fo->write(&ibuf[ph.u_len], xct_off - ph.u_len);
}
}
// Now handle compressed PT_LOADs
// Now handle compressed PT_LOADs.
// Phdr are parallel from input to output, except perhaps PT_NULL.
Elf64_Phdr const *i_phdr = phdri;
Elf64_Phdr const *o_phdr = (Elf64_Phdr const *)(1+ (Elf64_Ehdr const *)(void const *)o_elfhdrs);
int once = 0;
@@ -4820,6 +4828,12 @@ void PackLinuxElf64::un_shlib_1(
}
}
}
}
else { // Old style
Elf64_Phdr const *o_phdr = (Elf64_Phdr const *)(1+ (Elf64_Ehdr const *)(void const *)o_elfhdrs);
fi->seek(o_phdr->p_offset, SEEK_CUR); // DEBUG no-op
}
// position fi at loader offset
fi->seek(loader_offset, SEEK_SET);
}