diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 093e3ae9..7bee5828 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -195,6 +195,7 @@ PackLinuxElf::PackLinuxElf(InputFile *f) : super(f), e_phnum(0), file_image(NULL), dynstr(NULL), sz_phdrs(0), sz_elf_hdrs(0), sz_pack2(0), sz_pack2a(0), lg2_page(12), page_size(1u<seek(0, SEEK_SET); + f->readx(file_image, len); + phdri= (Elf32_Phdr *)(e_phoff + file_image); // do not free() !! + } + if (f && Elf32_Ehdr::ET_DYN==e_type) { + // The DT_STRTAB has no designated length. Read the whole file. + file_image = new char[file_size]; + f->seek(0, SEEK_SET); + f->readx(file_image, file_size); + phdri= (Elf32_Phdr *)(e_phoff + file_image); // do not free() !! + shdri= (Elf32_Shdr const *)(e_shoff + file_image); // do not free() !! + sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM); + if (sec_dynsym) + sec_dynstr = get_te32(&sec_dynsym->sh_link) + shdri; + + Elf32_Phdr const *phdr= phdri; + for (int j = e_phnum; --j>=0; ++phdr) + if (Elf32_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) { + dynseg= (Elf32_Dyn const *)(get_te32(&phdr->p_offset) + file_image); + break; + } + // elf_find_dynamic() returns 0 if 0==dynseg. + dynstr = (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB); + dynsym = (Elf32_Sym const *)elf_find_dynamic(Elf32_Dyn::DT_SYMTAB); + gashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_GNU_HASH); + hashtab = (unsigned const *)elf_find_dynamic(Elf32_Dyn::DT_HASH); + jni_onload_sym = elf_lookup("JNI_OnLoad"); + if (jni_onload_sym) + jni_onload_va = get_te32(&jni_onload_sym->st_value); + } +} + void PackLinuxElf::pack3(OutputFile *fo, Filter &ft) { unsigned disp; @@ -223,7 +269,10 @@ void PackLinuxElf::pack3(OutputFile *fo, Filter &ft) len += sizeof(disp); if (xct_off) { // is_shlib - set_te32(&disp, elf_unsigned_dynamic(Elf32_Dyn::DT_INIT) - load_va); + upx_uint64_t const firstpc_va = (jni_onload_va + ? jni_onload_va + : elf_unsigned_dynamic(Elf32_Dyn::DT_INIT) ); + set_te32(&disp, firstpc_va - load_va); fo->write(&disp, sizeof(disp)); len += sizeof(disp); @@ -305,7 +354,7 @@ void PackLinuxElf32::pack3(OutputFile *fo, Filter &ft) continue; // all done with this PT_LOAD } // Compute new offset of &DT_INIT.d_val. - if (phdr->PT_DYNAMIC==type) { + if (0==jni_onload_sym && phdr->PT_DYNAMIC==type) { off_init = rel + ioff; fi->seek(ioff, SEEK_SET); fi->read(ibuf, len); @@ -475,7 +524,8 @@ PackLinuxElf32::PackLinuxElf32(InputFile *f) : super(f), phdri(NULL), note_body(NULL), shdri(NULL), page_mask(~0u<seek(0, SEEK_SET); + f->readx(file_image, len); + phdri= (Elf64_Phdr *)(e_phoff + file_image); // do not free() !! + } + if (f && Elf64_Ehdr::ET_DYN==e_type) { + // The DT_STRTAB has no designated length. Read the whole file. + file_image = new char[file_size]; + f->seek(0, SEEK_SET); + f->readx(file_image, file_size); + phdri= (Elf64_Phdr *)(e_phoff + file_image); // do not free() !! + shdri= (Elf64_Shdr const *)(e_shoff + file_image); // do not free() !! + sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM); + if (sec_dynsym) + sec_dynstr = get_te64(&sec_dynsym->sh_link) + shdri; + + Elf64_Phdr const *phdr= phdri; + for (int j = e_phnum; --j>=0; ++phdr) + if (Elf64_Phdr::PT_DYNAMIC==get_te64(&phdr->p_type)) { + dynseg= (Elf64_Dyn const *)(get_te64(&phdr->p_offset) + file_image); + break; + } + // elf_find_dynamic() returns 0 if 0==dynseg. + dynstr = (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB); + dynsym = (Elf64_Sym const *)elf_find_dynamic(Elf64_Dyn::DT_SYMTAB); + gashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_GNU_HASH); + hashtab = (unsigned const *)elf_find_dynamic(Elf64_Dyn::DT_HASH); + jni_onload_sym = elf_lookup("JNI_OnLoad"); + if (jni_onload_sym) + jni_onload_va = get_te64(&jni_onload_sym->st_value); + } } Linker* PackLinuxElf64amd::newLinker() const @@ -1168,7 +1263,7 @@ Elf32_Shdr const *PackLinuxElf32::elf_find_section_name( ) const { Elf32_Shdr const *shdr = shdri; - int j = n_elf_shnum; + int j = e_shnum; for (; 0 <=--j; ++shdr) { if (0==strcmp(name, &shstrtab[get_te32(&shdr->sh_name)])) { return shdr; @@ -1182,7 +1277,7 @@ Elf64_Shdr const *PackLinuxElf64::elf_find_section_name( ) const { Elf64_Shdr const *shdr = shdri; - int j = n_elf_shnum; + int j = e_shnum; for (; 0 <=--j; ++shdr) { unsigned ndx = get_te64(&shdr->sh_name); if (0==strcmp(name, &shstrtab[ndx])) { @@ -1197,7 +1292,7 @@ Elf32_Shdr const *PackLinuxElf32::elf_find_section_type( ) const { Elf32_Shdr const *shdr = shdri; - int j = n_elf_shnum; + int j = e_shnum; for (; 0 <=--j; ++shdr) { if (type==get_te32(&shdr->sh_type)) { return shdr; @@ -1211,7 +1306,7 @@ Elf64_Shdr const *PackLinuxElf64::elf_find_section_type( ) const { Elf64_Shdr const *shdr = shdri; - int j = n_elf_shnum; + int j = e_shnum; for (; 0 <=--j; ++shdr) { if (type==get_te32(&shdr->sh_type)) { return shdr; @@ -1242,8 +1337,6 @@ bool PackLinuxElf32::canPack() throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'"); return false; } - unsigned const e_shoff = get_te32(&ehdr->e_shoff); - unsigned const e_phoff = get_te32(&ehdr->e_phoff); if (e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr throwCantPack("non-contiguous Ehdr/Phdr; try '--force-execve'"); return false; @@ -1328,31 +1421,7 @@ bool PackLinuxElf32::canPack() // Also allow __uClibc_main and __uClibc_start_main . if (Elf32_Ehdr::ET_DYN==get_te16(&ehdr->e_type)) { - // The DT_STRTAB has no designated length. Read the whole file. - file_image = new char[file_size]; - fi->seek(0, SEEK_SET); - fi->readx(file_image, file_size); memcpy(&ehdri, ehdr, sizeof(Elf32_Ehdr)); - phdri= (Elf32_Phdr *)(e_phoff + file_image); // do not free() !! - shdri= (Elf32_Shdr const *)(e_shoff + file_image); // do not free() !! - - n_elf_shnum = get_te16(&ehdr->e_shnum); - //sec_strndx = &shdri[ehdr->e_shstrndx]; - //shstrtab = (char const *)(sec_strndx->sh_offset + file_image); - sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM); - if (sec_dynsym) - sec_dynstr = get_te32(&sec_dynsym->sh_link) + shdri; - - int j= e_phnum; - phdr= phdri; - for (; --j>=0; ++phdr) - if (Elf32_Phdr::PT_DYNAMIC==get_te32(&phdr->p_type)) { - dynseg= (Elf32_Dyn const *)(get_te32(&phdr->p_offset) + file_image); - break; - } - // elf_find_dynamic() returns 0 if 0==dynseg. - dynstr= (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB); - dynsym= (Elf32_Sym const *)elf_find_dynamic(Elf32_Dyn::DT_SYMTAB); // Modified 2009-10-10 to detect a ProgramLinkageTable relocation // which references the symbol, because DT_GNU_HASH contains only @@ -1389,19 +1458,17 @@ bool PackLinuxElf32::canPack() // 2011-06-01: stub.shlib-init.S works around by installing hatch // at end of .text. - if (elf_find_dynamic(Elf32_Dyn::DT_INIT)) { + if (jni_onload_sym || elf_find_dynamic(Elf32_Dyn::DT_INIT)) { if (this->e_machine!=Elf32_Ehdr::EM_386 && this->e_machine!=Elf32_Ehdr::EM_ARM) goto abandon; // need stub: EM_MIPS EM_PPC if (elf_has_dynamic(Elf32_Dyn::DT_TEXTREL)) { - shdri = NULL; - phdri = NULL; throwCantPack("DT_TEXTREL found; re-compile with -fPIC"); goto abandon; } Elf32_Shdr const *shdr = shdri; xct_va = ~0u; - for (j= n_elf_shnum; --j>=0; ++shdr) { + for (int j= e_shnum; --j>=0; ++shdr) { if (Elf32_Shdr::SHF_EXECINSTR & get_te32(&shdr->sh_flags)) { xct_va = umin(xct_va, get_te32(&shdr->sh_addr)); } @@ -1418,12 +1485,11 @@ bool PackLinuxElf32::canPack() || xct_va < elf_unsigned_dynamic(Elf32_Dyn::DT_VERDEF) || xct_va < elf_unsigned_dynamic(Elf32_Dyn::DT_VERSYM) || xct_va < elf_unsigned_dynamic(Elf32_Dyn::DT_VERNEEDED) ) { - phdri = NULL; - shdri = NULL; throwCantPack("DT_ tag above stub"); goto abandon; } - for ((shdr= shdri), (j= n_elf_shnum); --j>=0; ++shdr) { + shdr= shdri; + for (int j= e_shnum; --j>=0; ++shdr) { unsigned const sh_addr = get_te32(&shdr->sh_addr); if ( sh_addr==va_gash || (sh_addr==va_hash && 0==va_gash) ) { @@ -1436,14 +1502,10 @@ bool PackLinuxElf32::canPack() goto proceed; // But proper packing depends on checking xct_va. } else - infoWarning("no DT_INIT: %s", fi->getName()); + infoWarning("no DT_INIT or JNI_OnLoad: %s", fi->getName()); abandon: - phdri = NULL; // Done with this - shdri = NULL; return false; -proceed: - phdri = NULL; - shdri = NULL; +proceed: ; } // XXX Theoretically the following test should be first, // but PackUnix::canPack() wants 0!=exetype ? @@ -1479,8 +1541,6 @@ PackLinuxElf64amd::canPack() throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'"); return false; } - upx_uint64_t const e_shoff = get_te64(&ehdr->e_shoff); - upx_uint64_t const e_phoff = get_te64(&ehdr->e_phoff); if (e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr throwCantPack("non-contiguous Ehdr/Phdr; try '--force-execve'"); return false; @@ -1525,7 +1585,6 @@ PackLinuxElf64amd::canPack() phdri= (Elf64_Phdr *)((size_t)e_phoff + file_image); // do not free() !! shdri= (Elf64_Shdr const *)((size_t)e_shoff + file_image); // do not free() !! - n_elf_shnum = get_te16(&ehdr->e_shnum); //sec_strndx = &shdri[ehdr->e_shstrndx]; //shstrtab = (char const *)(sec_strndx->sh_offset + file_image); sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM); @@ -1575,14 +1634,12 @@ PackLinuxElf64amd::canPack() if (elf_find_dynamic(Elf64_Dyn::DT_INIT)) { if (elf_has_dynamic(Elf64_Dyn::DT_TEXTREL)) { - shdri = NULL; - phdri = NULL; throwCantPack("DT_TEXTREL found; re-compile with -fPIC"); goto abandon; } Elf64_Shdr const *shdr = shdri; xct_va = ~0ull; - for (j= n_elf_shnum; --j>=0; ++shdr) { + for (j= e_shnum; --j>=0; ++shdr) { if (Elf64_Shdr::SHF_EXECINSTR & get_te32(&shdr->sh_flags)) { xct_va = umin64(xct_va, get_te64(&shdr->sh_addr)); } @@ -1599,12 +1656,10 @@ PackLinuxElf64amd::canPack() || xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERDEF) || xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERSYM) || xct_va < elf_unsigned_dynamic(Elf64_Dyn::DT_VERNEEDED) ) { - phdri = NULL; - shdri = NULL; throwCantPack("DT_ tag above stub"); goto abandon; } - for ((shdr= shdri), (j= n_elf_shnum); --j>=0; ++shdr) { + for ((shdr= shdri), (j= e_shnum); --j>=0; ++shdr) { upx_uint64_t const sh_addr = get_te64(&shdr->sh_addr); if ( sh_addr==va_gash || (sh_addr==va_hash && 0==va_gash) ) { @@ -1617,10 +1672,8 @@ PackLinuxElf64amd::canPack() goto proceed; // But proper packing depends on checking xct_va. } abandon: - phdri = 0; // Done with this return false; -proceed: - phdri = 0; +proceed: ; } // XXX Theoretically the following test should be first, // but PackUnix::canPack() wants 0!=exetype ? @@ -1978,14 +2031,9 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/) { fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); - unsigned const e_phoff = get_te32(&ehdri.e_phoff); assert(e_phoff == sizeof(Elf32_Ehdr)); // checked by canPack() sz_phdrs = e_phnum * get_te16(&ehdri.e_phentsize); - phdri = new Elf32_Phdr[e_phnum]; - fi->seek(e_phoff, SEEK_SET); - fi->readx(phdri, sz_phdrs); - // Remember all PT_NOTE, and find lg2_page from PT_LOAD. Elf32_Phdr const *phdr = phdri; note_size = 0; @@ -2030,13 +2078,12 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/) // if the preserve build-id option was specified if (opt->o_unix.preserve_build_id) { - n_elf_shnum = ehdri.e_shnum; Elf32_Shdr *shdr = NULL; Elf32_Shdr const *tmp = shdri; if (! shdri) { - shdr = new Elf32_Shdr[n_elf_shnum]; + shdr = new Elf32_Shdr[e_shnum]; fi->seek(0,SEEK_SET); fi->seek(ehdri.e_shoff,SEEK_SET); @@ -2170,14 +2217,9 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/) { fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); - unsigned const e_phoff = get_te32(&ehdri.e_phoff); assert(e_phoff == sizeof(Elf64_Ehdr)); // checked by canPack() sz_phdrs = e_phnum * get_te16(&ehdri.e_phentsize); - phdri = new Elf64_Phdr[e_phnum]; - fi->seek(e_phoff, SEEK_SET); - fi->readx(phdri, sz_phdrs); - Elf64_Phdr const *phdr = phdri; note_size = 0; for (unsigned j=0; j < e_phnum; ++phdr, ++j) { @@ -2222,7 +2264,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/) // only execute if option present if (opt->o_unix.preserve_build_id) { // set this so we can use elf_find_section_name - n_elf_shnum = ehdri.e_shnum; + e_shnum = ehdri.e_shnum; // there is a class member similar to this, but I did not // want to assume it would be available @@ -2231,7 +2273,7 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/) Elf64_Shdr *shdr = NULL; if (! shdri) { - shdr = new Elf64_Shdr[n_elf_shnum]; + shdr = new Elf64_Shdr[e_shnum]; fi->seek(0,SEEK_SET); fi->seek(ehdri.e_shoff,SEEK_SET); @@ -2821,6 +2863,15 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft) fo->rewrite(phdri, e_phnum * sizeof(*phdri)); fo->seek(sz_elf_hdrs, SEEK_SET); fo->rewrite(&linfo, sizeof(linfo)); + + if (jni_onload_va) { + unsigned tmp = sz_pack2 + get_te32(&elfout.phdr[0].p_vaddr); + tmp |= (Elf32_Ehdr::EM_ARM==e_machine); // THUMB mode + set_te32(&tmp, tmp); + fo->seek((char const *)&jni_onload_sym->st_value - file_image, SEEK_SET); + fo->rewrite(&tmp, sizeof(tmp)); + fo->seek(0, SEEK_SET); + } } else { unsigned const reloc = get_te32(&elfout.phdr[0].p_vaddr); @@ -3283,7 +3334,7 @@ PackLinuxElf64::elf_unsigned_dynamic(unsigned int const key) const return 0; } -unsigned PackLinuxElf32::gnu_hash(char const *q) +unsigned PackLinuxElf::gnu_hash(char const *q) { unsigned char const *p = (unsigned char const *)q; unsigned h; @@ -3294,7 +3345,7 @@ unsigned PackLinuxElf32::gnu_hash(char const *q) return h; } -unsigned PackLinuxElf32::elf_hash(char const *p) +unsigned PackLinuxElf::elf_hash(char const *p) { unsigned h; for (h= 0; 0!=*p; ++p) { @@ -3357,6 +3408,55 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const } +Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const +{ + if (hashtab && dynsym && dynstr) { + unsigned const nbucket = get_te32(&hashtab[0]); + unsigned const *const buckets = &hashtab[2]; + unsigned const *const chains = &buckets[nbucket]; + unsigned const m = elf_hash(name) % nbucket; + unsigned si; + for (si= get_te32(&buckets[m]); 0!=si; si= get_te32(&chains[si])) { + char const *const p= get_te64(&dynsym[si].st_name) + dynstr; + if (0==strcmp(name, p)) { + return &dynsym[si]; + } + } + } + if (gashtab && dynsym && dynstr) { + unsigned const n_bucket = get_te32(&gashtab[0]); + unsigned const symbias = get_te32(&gashtab[1]); + unsigned const n_bitmask = get_te32(&gashtab[2]); + unsigned const gnu_shift = get_te32(&gashtab[3]); + unsigned long const *const bitmask = (unsigned long const *)&gashtab[4]; + unsigned const *const buckets = (unsigned const *)&bitmask[n_bitmask]; + + unsigned const h = gnu_hash(name); + unsigned const hbit1 = 077& h; + unsigned const hbit2 = 077& (h>>gnu_shift); + unsigned long const w = get_te64(&bitmask[(n_bitmask -1) & (h>>6)]); + + if (1& (w>>hbit1) & (w>>hbit2)) { + unsigned bucket = get_te32(&buckets[h % n_bucket]); + if (0!=bucket) { + Elf64_Sym const *dsp = dynsym; + unsigned const *const hasharr = &buckets[n_bucket]; + unsigned const *hp = &hasharr[bucket - symbias]; + + dsp += bucket; + do if (0==((h ^ get_te32(hp))>>1)) { + char const *const p = get_te64(&dsp->st_name) + dynstr; + if (0==strcmp(name, p)) { + return dsp; + } + } while (++dsp, 0==(1u& get_te32(hp++))); + } + } + } + return 0; + +} + void PackLinuxElf32::unpack(OutputFile *fo) { #define MAX_ELF_HDR 512 diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index 9ae032a2..03bc575a 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -65,9 +65,15 @@ protected: //virtual void const *elf_find_dynamic(unsigned) const = 0; virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const = 0; + static unsigned elf_hash(char const *) /*const*/; + static unsigned gnu_hash(char const *) /*const*/; protected: + unsigned e_type; unsigned e_phnum; /* Program header table entry count */ + unsigned e_shnum; + unsigned e_phoff; + unsigned e_shoff; char *file_image; // if ET_DYN investigation char const *dynstr; // from DT_STRTAB @@ -81,6 +87,7 @@ protected: unsigned hatch_off; // file offset of escape hatch 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 unsigned short e_machine; unsigned char ei_class; @@ -100,6 +107,7 @@ public: PackLinuxElf32(InputFile *f); virtual ~PackLinuxElf32(); protected: + virtual void PackLinuxElf32help1(InputFile *f); virtual int checkEhdr(Elf32_Ehdr const *ehdr) const; virtual bool canPack(); @@ -134,8 +142,6 @@ protected: unsigned const e_phnum); virtual off_t getbase(const Elf32_Phdr *phdr, int e_phnum) const; - static unsigned elf_hash(char const *) /*const*/; - static unsigned gnu_hash(char const *) /*const*/; virtual Elf32_Sym const *elf_lookup(char const *) const; virtual unsigned elf_get_offset_from_address(unsigned) const; Elf32_Shdr const *elf_find_section_name(char const *) const; @@ -156,8 +162,8 @@ protected: unsigned int const *hashtab; // from DT_HASH unsigned int const *gashtab; // from DT_GNU_HASH Elf32_Sym const *dynsym; // from DT_SYMTAB + Elf32_Sym const *jni_onload_sym; char const *shstrtab; // via Elf32_Shdr - int n_elf_shnum; // via e_shnum Elf32_Shdr const *sec_strndx; Elf32_Shdr const *sec_dynsym; @@ -224,6 +230,7 @@ public: /*virtual void buildLoader(const Filter *);*/ protected: + virtual void PackLinuxElf64help1(InputFile *f); virtual int checkEhdr(Elf64_Ehdr const *ehdr) const; virtual void pack1(OutputFile *, Filter &); // generate executable header @@ -250,6 +257,7 @@ protected: virtual unsigned find_LOAD_gap(Elf64_Phdr const *const phdri, unsigned const k, unsigned const e_phnum); + virtual Elf64_Sym const *elf_lookup(char const *) const; virtual upx_uint64_t elf_get_offset_from_address(upx_uint64_t) const; Elf64_Shdr const *elf_find_section_name(char const *) const; Elf64_Shdr const *elf_find_section_type(unsigned) const; @@ -269,8 +277,8 @@ protected: unsigned int const *hashtab; // from DT_HASH unsigned int const *gashtab; // from DT_GNU_HASH Elf64_Sym const *dynsym; // from DT_SYMTAB + Elf64_Sym const *jni_onload_sym; char const *shstrtab; // via Elf64_Shdr - int n_elf_shnum; // via e_shnum Elf64_Shdr const *sec_strndx; Elf64_Shdr const *sec_dynsym; @@ -326,7 +334,7 @@ class PackLinuxElf32Be : public PackLinuxElf32 protected: PackLinuxElf32Be(InputFile *f) : super(f) { bele = &N_BELE_RTP::be_policy; - e_phnum = get_te16(&ehdri.e_phnum); + PackLinuxElf32help1(f); } }; @@ -336,7 +344,7 @@ class PackLinuxElf32Le : public PackLinuxElf32 protected: PackLinuxElf32Le(InputFile *f) : super(f) { bele = &N_BELE_RTP::le_policy; - e_phnum = get_te16(&ehdri.e_phnum); + PackLinuxElf32help1(f); } }; @@ -346,7 +354,7 @@ class PackLinuxElf64Le : public PackLinuxElf64 protected: PackLinuxElf64Le(InputFile *f) : super(f) { bele = &N_BELE_RTP::le_policy; - e_phnum = get_te16(&ehdri.e_phnum); + PackLinuxElf64help1(f); } };