Hack Android shared libraries on arm64.
https://github.com/upx/upx/issues/318 modified: p_lx_elf.cpp
This commit is contained in:
+40
-16
@@ -312,7 +312,7 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f)
|
|||||||
jni_onload_sym = elf_lookup("JNI_OnLoad");
|
jni_onload_sym = elf_lookup("JNI_OnLoad");
|
||||||
if (jni_onload_sym) {
|
if (jni_onload_sym) {
|
||||||
jni_onload_va = get_te32(&jni_onload_sym->st_value);
|
jni_onload_va = get_te32(&jni_onload_sym->st_value);
|
||||||
jni_onload_va = 0;
|
jni_onload_va = 0; // FIXME not understood; need example
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -790,7 +790,7 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f)
|
|||||||
jni_onload_sym = elf_lookup("JNI_OnLoad");
|
jni_onload_sym = elf_lookup("JNI_OnLoad");
|
||||||
if (jni_onload_sym) {
|
if (jni_onload_sym) {
|
||||||
jni_onload_va = get_te64(&jni_onload_sym->st_value);
|
jni_onload_va = get_te64(&jni_onload_sym->st_value);
|
||||||
jni_onload_va = 0;
|
jni_onload_va = 0; // FIXME not understood; need example
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3262,13 +3262,19 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
if (xct_off <= r_offset) {
|
if (xct_off <= r_offset) {
|
||||||
set_te32(&rel->r_offset, asl_delta + r_offset);
|
set_te32(&rel->r_offset, asl_delta + r_offset);
|
||||||
}
|
}
|
||||||
if (Elf32_Ehdr::EM_ARM == e_machine) {
|
if (Elf32_Ehdr::EM_ARM == e_machine) switch (r_type) {
|
||||||
if (R_ARM_RELATIVE == r_type) {
|
default: {
|
||||||
|
char msg[90]; snprintf(msg, sizeof(msg),
|
||||||
|
"unexpected relocation %#x [%#x]",
|
||||||
|
r_type, -1 + (sh_size / sh_entsize) - k);
|
||||||
|
throwCantPack(msg);
|
||||||
|
} break;
|
||||||
|
case R_ARM_RELATIVE: {
|
||||||
if (xct_off <= w) {
|
if (xct_off <= w) {
|
||||||
set_te32(&file_image[d], asl_delta + w);
|
set_te32(&file_image[d], asl_delta + w);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
if (R_ARM_JUMP_SLOT == r_type) {
|
case R_ARM_JUMP_SLOT: {
|
||||||
if (plt_off > r_offset) {
|
if (plt_off > r_offset) {
|
||||||
plt_off = r_offset;
|
plt_off = r_offset;
|
||||||
}
|
}
|
||||||
@@ -3276,7 +3282,7 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
set_te32(&file_image[d], asl_delta + w);
|
set_te32(&file_image[d], asl_delta + w);
|
||||||
}
|
}
|
||||||
++n_jmp_slot;
|
++n_jmp_slot;
|
||||||
}
|
}; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fo->seek(sh_offset, SEEK_SET);
|
fo->seek(sh_offset, SEEK_SET);
|
||||||
@@ -3293,7 +3299,15 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
memcpy(&buf_notes[len_notes], &file_image[sh_offset], sh_size);
|
memcpy(&buf_notes[len_notes], &file_image[sh_offset], sh_size);
|
||||||
len_notes += sh_size;
|
len_notes += sh_size;
|
||||||
}
|
}
|
||||||
// else: SHF_ALLOC, thus already in PT_LOAD
|
else { // SHF_ALLOC, thus already in PT_LOAD
|
||||||
|
// Not sure why we need this conditional.
|
||||||
|
// Anyway, some Android have multiple SHT_NOTE sections.
|
||||||
|
if (xct_off <= sh_offset) {
|
||||||
|
upx_uint32_t pos = xct_off + e_shnum * sizeof(Elf32_Shdr);
|
||||||
|
set_te32(&shdr->sh_addr, pos);
|
||||||
|
set_te32(&shdr->sh_offset, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// shstrndx will move
|
// shstrndx will move
|
||||||
@@ -3621,13 +3635,19 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
if (xct_off <= r_offset) {
|
if (xct_off <= r_offset) {
|
||||||
set_te64(&rela->r_offset, asl_delta + r_offset);
|
set_te64(&rela->r_offset, asl_delta + r_offset);
|
||||||
}
|
}
|
||||||
if (Elf64_Ehdr::EM_AARCH64 == e_machine) {
|
if (Elf64_Ehdr::EM_AARCH64 == e_machine) switch (r_type) {
|
||||||
if (R_AARCH64_RELATIVE == r_type) {
|
default: {
|
||||||
|
char msg[90]; snprintf(msg, sizeof(msg),
|
||||||
|
"unexpected relocation %#x [%#x]",
|
||||||
|
r_type, -1 + (unsigned)(sh_size / sh_entsize) - k);
|
||||||
|
throwCantPack(msg);
|
||||||
|
} break;
|
||||||
|
case R_AARCH64_RELATIVE: {
|
||||||
if (xct_off <= r_addend) {
|
if (xct_off <= r_addend) {
|
||||||
set_te64(&rela->r_addend, asl_delta + r_addend);
|
set_te64(&rela->r_addend, asl_delta + r_addend);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
if (R_AARCH64_JUMP_SLOT == r_type) {
|
case R_AARCH64_JUMP_SLOT: {
|
||||||
// .rela.plt contains offset of the "first time" target
|
// .rela.plt contains offset of the "first time" target
|
||||||
if (plt_off > r_offset) {
|
if (plt_off > r_offset) {
|
||||||
plt_off = r_offset;
|
plt_off = r_offset;
|
||||||
@@ -3638,7 +3658,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
set_te64(&file_image[d], asl_delta + w);
|
set_te64(&file_image[d], asl_delta + w);
|
||||||
}
|
}
|
||||||
++n_jmp_slot;
|
++n_jmp_slot;
|
||||||
}
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fo->seek(sh_offset, SEEK_SET);
|
fo->seek(sh_offset, SEEK_SET);
|
||||||
@@ -3682,9 +3702,13 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/)
|
|||||||
len_notes += sh_size;
|
len_notes += sh_size;
|
||||||
}
|
}
|
||||||
else { // SHF_ALLOC: in PT_LOAD; but move sh_addr and sh_offset
|
else { // SHF_ALLOC: in PT_LOAD; but move sh_addr and sh_offset
|
||||||
upx_uint64_t pos = xct_off + e_shnum * sizeof(Elf64_Shdr);
|
// Not sure why we need this conditional.
|
||||||
set_te64(&shdr->sh_addr, pos);
|
// Anyway, some Android have multiple SHT_NOTE sections.
|
||||||
set_te64(&shdr->sh_offset, pos);
|
if (xct_off <= sh_offset) {
|
||||||
|
upx_uint64_t pos = xct_off + e_shnum * sizeof(Elf64_Shdr);
|
||||||
|
set_te64(&shdr->sh_addr, pos);
|
||||||
|
set_te64(&shdr->sh_offset, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user