Many changes for ELF shared libraries on Linux and Android

Handling more than 2 PT_LOAD (and thus more than 1 executable PT_LOAD)
required extensive changes.  But the bonus is the infrastructure
to support a different (de-)compression algorithm for each PT_LOAD.

https://github.com/upx/upx/issues/341   i386 .so decompression
https://github.com/upx/upx/issues/609   armv7 .so on Android
https://github.com/upx/upx/issues/625   amd64 .so execution
https://github.com/upx/upx/issues/654   armv7 .exe
Not yet: .so on MIPS, PowerPC, PowerPC64
This commit is contained in:
John Reiser
2023-03-04 17:37:25 -08:00
committed by Markus F.X.J. Oberhumer
parent fa56a1d9cd
commit adb0ca8250
121 changed files with 15796 additions and 6036 deletions
+30 -9
View File
@@ -76,6 +76,8 @@ protected:
unsigned e_phnum; /* Program header table entry count */
unsigned e_shnum;
MemBuffer file_image; // if ET_DYN investigation
MemBuffer lowmem; // at least including PT_LOAD[0]
MemBuffer mb_shdr; // Shdr might not be near Phdr
char const *dynstr; // from DT_STRTAB
unsigned sz_phdrs; // sizeof Phdr[]
@@ -89,6 +91,7 @@ protected:
unsigned xct_off; // shared library: file offset of SHT_EXECINSTR
unsigned hatch_off; // file offset of escape hatch
unsigned o_binfo; // offset to first b_info
upx_off_t so_slide;
upx_uint64_t load_va; // PT_LOAD[0].p_vaddr
upx_uint64_t xct_va; // minimum SHT_EXECINSTR virtual address
upx_uint64_t jni_onload_va; // runtime &JNI_OnLoad
@@ -137,10 +140,26 @@ protected:
virtual int ARM_is_QNX(void);
virtual void pack1(OutputFile *, Filter &) override; // generate executable header
virtual void asl_pack2_Shdrs(OutputFile *, unsigned pre_xct_top); // AndroidSharedLibrary processes Shdrs
virtual void asl_slide_Shdrs(); // by so_slide if above xct_off
virtual int pack2(OutputFile *, Filter &) override; // append compressed data
virtual off_t pack3(OutputFile *, Filter &) override; // append loader
virtual void pack4(OutputFile *, Filter &) override; // append pack header
virtual void unpack(OutputFile *fo) override;
virtual void un_asl_dynsym(unsigned orig_file_size, OutputFile *);
virtual void un_shlib_1(
OutputFile *const fo,
MemBuffer &o_elfhdrs,
unsigned &c_adler,
unsigned &u_adler,
unsigned const orig_file_size
);
virtual void un_DT_INIT(
unsigned old_dtinit,
Elf32_Phdr const *phdro,
Elf32_Phdr const *dynhdr, // in phdri
OutputFile *fo
);
virtual void unRel32(unsigned dt_rel, Elf32_Rel *rel0, unsigned relsz,
MemBuffer &membuf, unsigned const load_off, OutputFile *fo);
@@ -167,9 +186,12 @@ protected:
virtual Elf32_Sym const *elf_lookup(char const *) const;
virtual unsigned elf_get_offset_from_address(unsigned) const;
virtual unsigned elf_get_offset_from_Phdrs(unsigned, Elf32_Phdr const *phdr0) const;
virtual Elf32_Phdr *elf_find_Phdr_for_va(unsigned addr, Elf32_Phdr *phdr, unsigned phnum);
Elf32_Phdr const *elf_find_ptype(unsigned type, Elf32_Phdr const *phdr0, unsigned phnum);
Elf32_Shdr const *elf_find_section_name(char const *) const;
Elf32_Shdr const *elf_find_section_type(unsigned) const;
Elf32_Shdr *elf_find_section_type(unsigned) const;
int is_LOAD32(Elf32_Phdr const *phdr) const; // beware confusion with (1+ LO_PROC)
unsigned check_pt_load(Elf32_Phdr const *);
unsigned check_pt_dynamic(Elf32_Phdr const *);
@@ -183,14 +205,14 @@ protected:
char const *get_dynsym_name(unsigned symnum, unsigned relnum) const;
protected:
Elf32_Ehdr ehdri; // from input file
MemBuffer lowmem; // especially for shlib
Elf32_Phdr *phdri; // for input file
Elf32_Shdr *shdri; // from input file
Elf32_Shdr *shdro; // for output file
Elf32_Phdr const *gnu_stack; // propagate NX
unsigned e_phoff;
unsigned e_shoff;
unsigned e_shstrndx;
unsigned sz_dynseg; // PT_DYNAMIC.p_memsz
unsigned so_slide;
unsigned n_jmp_slot;
unsigned plt_off;
unsigned page_mask; // AND clears the offset-within-page
@@ -204,6 +226,7 @@ protected:
Elf32_Shdr *sec_strndx;
Elf32_Shdr const *sec_dynsym;
Elf32_Shdr const *sec_dynstr;
Elf32_Shdr *sec_arm_attr; // SHT_ARM_ATTRIBUTES;
unsigned symnum_end;
unsigned strtab_end;
@@ -285,9 +308,7 @@ protected:
MemBuffer &o_elfhdrs,
unsigned &c_adler,
unsigned &u_adler,
Elf64_Phdr const *const dynhdr,
unsigned const orig_file_size,
unsigned const szb_info
unsigned const orig_file_size
);
virtual void un_DT_INIT(
unsigned old_dtinit,
@@ -320,9 +341,10 @@ protected:
virtual Elf64_Sym const *elf_lookup(char const *) const;
virtual upx_uint64_t elf_get_offset_from_address(upx_uint64_t) const;
virtual Elf64_Phdr *elf_find_Phdr_for_va(upx_uint64_t addr, Elf64_Phdr *phdr, unsigned phnum);
Elf64_Phdr const *elf_find_ptype(unsigned type, Elf64_Phdr const *phdr0, unsigned phnum);
Elf64_Shdr const *elf_find_section_name(char const *) const;
Elf64_Shdr const *elf_find_section_type(unsigned) const;
Elf64_Shdr *elf_find_section_type(unsigned) const;
int is_LOAD64(Elf64_Phdr const *phdr) const; // beware confusion with (1+ LO_PROC)
upx_uint64_t check_pt_load(Elf64_Phdr const *);
upx_uint64_t check_pt_dynamic(Elf64_Phdr const *);
@@ -336,14 +358,13 @@ protected:
char const *get_dynsym_name(unsigned symnum, unsigned relnum) const;
protected:
Elf64_Ehdr ehdri; // from input file
MemBuffer lowmem; // especially for shlib
Elf64_Phdr *phdri; // for input file
Elf64_Shdr *shdri; // from input file
Elf64_Shdr *shdro; // for output file
Elf64_Phdr const *gnu_stack; // propagate NX
upx_uint64_t e_phoff;
upx_uint64_t e_shoff;
upx_uint64_t sz_dynseg; // PT_DYNAMIC.p_memsz
upx_uint64_t so_slide;
unsigned n_jmp_slot;
upx_uint64_t page_mask; // AND clears the offset-within-page