WIP 64-bit shlib

modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser
2021-08-07 06:45:01 -07:00
committed by Markus F.X.J. Oberhumer
parent 076aaf829a
commit c9f6a3583c
+27 -14
View File
@@ -369,8 +369,8 @@ off_t PackLinuxElf::pack3(OutputFile *fo, Filter &ft) // return length of output
if (opt->o_unix.android_shlib) { if (opt->o_unix.android_shlib) {
xct_off += asl_delta; // the extra page xct_off += asl_delta; // the extra page
} }
set_te32(&disp, xct_off); set_te32(&disp, overlay_offset - sizeof(linfo));
fo->write(&disp, sizeof(disp)); // offset(dst for f_exp) fo->write(&disp, sizeof(disp)); // &{l_info; p_info; b_info}
len += sizeof(disp); len += sizeof(disp);
} }
sz_pack2 = len; // 0 mod 8 [see above] sz_pack2 = len; // 0 mod 8 [see above]
@@ -1742,7 +1742,7 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp, unsigned headway)
unsigned bj = get_te32(&buckets[j]); unsigned bj = get_te32(&buckets[j]);
if (bj) { if (bj) {
if (bj < symbias) { if (bj < symbias) {
char msg[50]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH bucket[%d] < symbias{%#x}\n", "bad DT_GNU_HASH bucket[%d] < symbias{%#x}\n",
bj, symbias); bj, symbias);
throwCantPack(msg); throwCantPack(msg);
@@ -1753,7 +1753,7 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp, unsigned headway)
} }
} }
if ((1+ bmax) < symbias) { if ((1+ bmax) < symbias) {
char msg[80]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH (1+ max_bucket)=%#x < symbias=%#x", 1+ bmax, symbias); "bad DT_GNU_HASH (1+ max_bucket)=%#x < symbias=%#x", 1+ bmax, symbias);
throwCantPack(msg); throwCantPack(msg);
} }
@@ -2478,6 +2478,7 @@ PackLinuxElf64::canPack()
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'"); throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
return false; return false;
} }
// FIXME: bad for shlib!
hatch_off = ~3ul & (3+ get_te64(&phdr->p_memsz)); hatch_off = ~3ul & (3+ get_te64(&phdr->p_memsz));
break; break;
} }
@@ -4280,7 +4281,7 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
} }
else { else {
// Read-write PT_LOAD. // Read-write PT_LOAD.
// Might be relocated, so cannot be compressed. // rtld might relocate, so we cannot compress.
// (Could compress if not relocated; complicates run-time.) // (Could compress if not relocated; complicates run-time.)
// Postpone writing until "slide", but account for its size. // Postpone writing until "slide", but account for its size.
total_in += x.size; total_in += x.size;
@@ -4479,6 +4480,12 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
fo->seek(0, SEEK_SET); fo->seek(0, SEEK_SET);
if (0!=xct_off) { // shared library if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) {
Elf32_Phdr *phdro = (Elf32_Phdr *)(&lowmem[sizeof(Elf32_Ehdr)]);
set_te32(&phdro->p_flags, Elf32_Phdr::PF_X | get_te32(&phdro->p_flags));
}
}
fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(*phdri)); fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(*phdri));
fo->seek(sz_elf_hdrs, SEEK_SET); fo->seek(sz_elf_hdrs, SEEK_SET);
fo->rewrite(&linfo, sizeof(linfo)); fo->rewrite(&linfo, sizeof(linfo));
@@ -4542,6 +4549,12 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
fo->seek(0, SEEK_SET); fo->seek(0, SEEK_SET);
if (0!=xct_off) { // shared library if (0!=xct_off) { // shared library
{ // Shouldn't this special case be handled earlier?
if (overlay_offset < xct_off) {
Elf64_Phdr *phdro = (Elf64_Phdr *)(&lowmem[sizeof(Elf64_Ehdr)]);
set_te64(&phdro->p_flags, Elf64_Phdr::PF_X | get_te64(&phdro->p_flags));
}
}
fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(Elf64_Phdr)); fo->rewrite(&lowmem[0], sizeof(ehdri) + e_phnum * sizeof(Elf64_Phdr));
//fo->seek(xct_off, SEEK_SET); // FIXME //fo->seek(xct_off, SEEK_SET); // FIXME
//fo->rewrite(&linfo, sizeof(linfo)); //fo->rewrite(&linfo, sizeof(linfo));
@@ -4664,17 +4677,17 @@ PackLinuxElf64::unRela64(
// 1. new Elf headers: Ehdr, PT_LOAD (r-x), PT_LOAD (rw-, if any), non-PT_LOAD Phdrs // 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 // 2. Space for (original - 2) PT_LOAD Phdr
// 3. Remaining original contents of file below xct_off // 3. Remaining original contents of file below xct_off
// xct_off: (&lowest eXecutable Shdr section) // xct_off: (&lowest eXecutable Shdr section; in original PT_LOAD[0] or [1])
// 4. l_info (12 bytes) // 4. l_info (12 bytes)
// overlay_offset: // overlay_offset:
// 5. p_info (12 bytes) // 5. p_info (12 bytes)
// 6. compressed original Elf headers // 6. compressed original Elf headers (prefixed by b_info as usual)
// 7. compressed remainder of PT_LOAD above xct_off // 7. compressed remainder of PT_LOAD above xct_off
// 8. compressed read-only PT_LOAD above xct_off (if any) // 8. compressed read-only PT_LOAD above xct_off (if any)
// 9. uncompressed Read-Write PT_LOAD (slide down N pages) // 9. uncompressed Read-Write PT_LOAD (slide down N pages)
// 10. int[6] tables for de-compressor // 10. int[6] tables for UPX runtime de-compressor
// DT_INIT: // (new) DT_INIT:
// 11. de-compressing loader // 11. UPX runtime de-compressing loader
// 12. compressed gaps between PT_LOADs (and EOF) above xct_off // 12. compressed gaps between PT_LOADs (and EOF) above xct_off
// 13. 32-byte pack header // 13. 32-byte pack header
// 14. 4-byte overlay offset // 14. 4-byte overlay offset
@@ -5578,7 +5591,7 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp, upx_uint64_t headway)
unsigned bj = get_te32(&buckets[j]); unsigned bj = get_te32(&buckets[j]);
if (bj) { if (bj) {
if (bj < symbias) { if (bj < symbias) {
char msg[50]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH bucket[%d] < symbias{%#x}\n", "bad DT_GNU_HASH bucket[%d] < symbias{%#x}\n",
bj, symbias); bj, symbias);
throwCantPack(msg); throwCantPack(msg);
@@ -5589,7 +5602,7 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp, upx_uint64_t headway)
} }
} }
if ((1+ bmax) < symbias) { if ((1+ bmax) < symbias) {
char msg[80]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH (1+ max_bucket)=%#x < symbias=%#x", 1+ bmax, symbias); "bad DT_GNU_HASH (1+ max_bucket)=%#x < symbias=%#x", 1+ bmax, symbias);
throwCantPack(msg); throwCantPack(msg);
} }
@@ -5730,7 +5743,7 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
if (1& (w>>hbit1) & (w>>hbit2)) { if (1& (w>>hbit1) & (w>>hbit2)) {
unsigned bucket = get_te32(&buckets[h % n_bucket]); unsigned bucket = get_te32(&buckets[h % n_bucket]);
if (n_bucket <= bucket) { if (n_bucket <= bucket) {
char msg[80]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH n_bucket{%#x} <= buckets[%d]{%#x}\n", "bad DT_GNU_HASH n_bucket{%#x} <= buckets[%d]{%#x}\n",
n_bucket, h % n_bucket, bucket); n_bucket, h % n_bucket, bucket);
throwCantPack(msg); throwCantPack(msg);
@@ -5807,7 +5820,7 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const
if (1& (w>>hbit1) & (w>>hbit2)) { if (1& (w>>hbit1) & (w>>hbit2)) {
unsigned bucket = get_te32(&buckets[h % n_bucket]); unsigned bucket = get_te32(&buckets[h % n_bucket]);
if (n_bucket <= bucket) { if (n_bucket <= bucket) {
char msg[80]; snprintf(msg, sizeof(msg), char msg[90]; snprintf(msg, sizeof(msg),
"bad DT_GNU_HASH n_bucket{%#x} <= buckets[%d]{%#x}\n", "bad DT_GNU_HASH n_bucket{%#x} <= buckets[%d]{%#x}\n",
n_bucket, h % n_bucket, bucket); n_bucket, h % n_bucket, bucket);
throwCantPack(msg); throwCantPack(msg);