mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Try to appease Android runtime loader; _Shdr vs _Phdr offsets
JNI FalalError called: Unable to load library: [dlopen failed: "/lib/arm/libunity.so" .dynamic section has invalid offset: 0x6d3e58, expected to match PT_DYNAMIC offset: 0x441e58] https://github.com/upx/upx/issues/609 modified: p_elf_enum.h modified: p_lx_elf.cpp
This commit is contained in:
parent
b5d1eba4c1
commit
b361b91ec7
|
@ -127,9 +127,12 @@
|
||||||
SHT_FINI_ARRAY = 15, /* Array of destructors */
|
SHT_FINI_ARRAY = 15, /* Array of destructors */
|
||||||
SHT_PREINIT_ARRAY = 16, /* Array of pre-constructors */
|
SHT_PREINIT_ARRAY = 16, /* Array of pre-constructors */
|
||||||
SHT_GROUP = 17, /* Section group */
|
SHT_GROUP = 17, /* Section group */
|
||||||
SHT_SYMTAB_SHNDX = 18, /* Extended section indeces */
|
SHT_SYMTAB_SHNDX = 18, /* Extended section indices */
|
||||||
SHT_GNU_LIBLIST = 0x6ffffff7, /* Prelink library list */
|
|
||||||
SHT_GNU_HASH = 0x6ffffff6, /* GNU-style hash table. */
|
SHT_GNU_HASH = 0x6ffffff6, /* GNU-style hash table. */
|
||||||
|
SHT_GNU_LIBLIST = 0x6ffffff7, /* Prelink library list */
|
||||||
|
SHT_GNU_verdef = 0x6ffffffd, /* Version definition section. */
|
||||||
|
SHT_GNU_verneed = 0x6ffffffe, /* Version needs section. */
|
||||||
|
SHT_GNU_versym = 0x6fffffff, /* Version symbol table. */
|
||||||
|
|
||||||
SHT_LOOS = 0x60000000, /* LOcal OS; SHT_ANDROID_REL{,A} is +1, +2 */
|
SHT_LOOS = 0x60000000, /* LOcal OS; SHT_ANDROID_REL{,A} is +1, +2 */
|
||||||
SHT_LOPROC = 0x70000000, /* Start of processor-specific */
|
SHT_LOPROC = 0x70000000, /* Start of processor-specific */
|
||||||
|
|
|
@ -1660,6 +1660,7 @@ static const
|
||||||
|
|
||||||
#define WANT_NHDR_ENUM
|
#define WANT_NHDR_ENUM
|
||||||
#include "p_elf_enum.h"
|
#include "p_elf_enum.h"
|
||||||
|
#undef WANT_NHDR_ENUM
|
||||||
|
|
||||||
void
|
void
|
||||||
PackNetBSDElf32x86::buildLoader(const Filter *ft)
|
PackNetBSDElf32x86::buildLoader(const Filter *ft)
|
||||||
|
@ -5477,6 +5478,10 @@ void PackLinuxElf32mipsel::defineSymbols(Filter const *ft)
|
||||||
PackLinuxElf32::defineSymbols(ft);
|
PackLinuxElf32::defineSymbols(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WANT_SHDR_ENUM
|
||||||
|
#include "p_elf_enum.h"
|
||||||
|
#undef WANT_SHDR_ENUM
|
||||||
|
|
||||||
void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
||||||
{
|
{
|
||||||
if (saved_opt_android_shlib) { // Forward select _Shdr
|
if (saved_opt_android_shlib) { // Forward select _Shdr
|
||||||
|
@ -5485,6 +5490,21 @@ void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
||||||
// Keep _Shdr for SHF_WRITE.
|
// Keep _Shdr for SHF_WRITE.
|
||||||
// Discard _Shdr with (0==sh_addr), except _Shdr[0]
|
// Discard _Shdr with (0==sh_addr), except _Shdr[0]
|
||||||
// Keep ARM_ATTRIBUTES
|
// Keep ARM_ATTRIBUTES
|
||||||
|
unsigned const want_types_mask =
|
||||||
|
1<<SHT_SYMTAB
|
||||||
|
| 1<<SHT_RELA
|
||||||
|
| 1<<SHT_HASH
|
||||||
|
| 1<<SHT_DYNAMIC
|
||||||
|
| 1<<SHT_NOTE
|
||||||
|
| 1<<SHT_REL
|
||||||
|
| 1<<SHT_DYNSYM
|
||||||
|
| 1<<SHT_INIT_ARRAY
|
||||||
|
| 1<<SHT_FINI_ARRAY
|
||||||
|
| 1<<SHT_PREINIT_ARRAY
|
||||||
|
| 1<<(0x1f & SHT_GNU_versym)
|
||||||
|
| 1<<(0x1f & SHT_GNU_verneed)
|
||||||
|
| 1<<(0x1f & SHT_GNU_verdef)
|
||||||
|
| 1<<(0x1f & SHT_GNU_HASH);
|
||||||
Elf32_Ehdr *eho = (Elf32_Ehdr *)lowmem.getVoidPtr();
|
Elf32_Ehdr *eho = (Elf32_Ehdr *)lowmem.getVoidPtr();
|
||||||
MemBuffer mb_ask_for(e_shnum * sizeof(eho->e_shnum));
|
MemBuffer mb_ask_for(e_shnum * sizeof(eho->e_shnum));
|
||||||
memset(mb_ask_for, 0, mb_ask_for.getSize());
|
memset(mb_ask_for, 0, mb_ask_for.getSize());
|
||||||
|
@ -5501,7 +5521,8 @@ void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
||||||
for (unsigned j = 1; j < e_shnum; ++j, ++sh_in) {
|
for (unsigned j = 1; j < e_shnum; ++j, ++sh_in) {
|
||||||
unsigned sh_offset = get_te32(&sh_in->sh_offset);
|
unsigned sh_offset = get_te32(&sh_in->sh_offset);
|
||||||
unsigned sh_flags = get_te32(&sh_in->sh_flags);
|
unsigned sh_flags = get_te32(&sh_in->sh_flags);
|
||||||
unsigned sh_info = get_te16(&sh_in->sh_info);
|
unsigned sh_info = get_te32(&sh_in->sh_info);
|
||||||
|
unsigned sh_type = get_te32(&sh_in->sh_type);
|
||||||
if (ask_for[j]) { // Some previous _Shdr requested me
|
if (ask_for[j]) { // Some previous _Shdr requested me
|
||||||
// Tell them my new index
|
// Tell them my new index
|
||||||
set_te16(&sh_out0[ask_for[j]].sh_info, n_sh_out);
|
set_te16(&sh_out0[ask_for[j]].sh_info, n_sh_out);
|
||||||
|
@ -5511,6 +5532,7 @@ void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
||||||
|| (Elf32_Shdr::SHF_WRITE & sh_flags)
|
|| (Elf32_Shdr::SHF_WRITE & sh_flags)
|
||||||
|| (j == e_shstrndx)
|
|| (j == e_shstrndx)
|
||||||
|| (sec_arm_attr == sh_in)
|
|| (sec_arm_attr == sh_in)
|
||||||
|
|| (want_types_mask & (1<<(0x1f & sh_type)))
|
||||||
) {
|
) {
|
||||||
*sh_out = *sh_in;
|
*sh_out = *sh_in;
|
||||||
if (sec_arm_attr == sh_in) {
|
if (sec_arm_attr == sh_in) {
|
||||||
|
@ -5530,8 +5552,10 @@ void PackLinuxElf32::forward_Shdrs(OutputFile *fo)
|
||||||
fo->write(ibuf, len);
|
fo->write(ibuf, len);
|
||||||
total_out += len;
|
total_out += len;
|
||||||
}
|
}
|
||||||
if (Elf32_Shdr::SHF_WRITE & sh_flags) {
|
if (Elf32_Shdr::SHF_WRITE & sh_flags || SHT_NOTE == sh_type) {
|
||||||
set_te32(&sh_out->sh_offset, so_slide + get_te32(&sh_out->sh_offset));
|
if (sh_offset > xct_off) {
|
||||||
|
set_te32(&sh_out->sh_offset, so_slide + sh_offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++sh_out; ++n_sh_out;
|
++sh_out; ++n_sh_out;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user