📄 p_lx_elf.cpp
字号:
voidPackLinuxElf64amd::buildLoader(const Filter *ft){ buildLinuxLoader( stub_amd64_linux_elf_entry, sizeof(stub_amd64_linux_elf_entry), stub_amd64_linux_elf_fold, sizeof(stub_amd64_linux_elf_fold), ft);}Elf32_Shdr const *PackLinuxElf32::elf_find_section_name( char const *const name) const{ Elf32_Shdr const *shdr = shdri; int j = n_elf_shnum; for (; 0 <=--j; ++shdr) { if (0==strcmp(name, &shstrtab[shdr->sh_name])) { return shdr; } } return 0;}Elf32_Shdr const *PackLinuxElf32::elf_find_section_type( unsigned const type) const{ Elf32_Shdr const *shdr = shdri; int j = n_elf_shnum; for (; 0 <=--j; ++shdr) { if (type==shdr->sh_type) { return shdr; } } return 0;}bool PackLinuxElf32::canPack(){ unsigned char buf[sizeof(Elf32_Ehdr) + 14*sizeof(Elf32_Phdr)]; COMPILE_TIME_ASSERT(sizeof(buf) <= 512); fi->seek(0, SEEK_SET); fi->readx(buf, sizeof(buf)); fi->seek(0, SEEK_SET); Elf32_Ehdr const *const ehdr = (Elf32_Ehdr const *)buf; // now check the ELF header if (checkEhdr(ehdr) != 0) return false; // additional requirements for linux/elf386 if (get_native16(&ehdr->e_ehsize) != sizeof(*ehdr)) { throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'"); return false; } unsigned const e_shoff = get_native32(&ehdr->e_shoff); unsigned const e_phoff = get_native32(&ehdr->e_phoff); if (e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr throwCantPack("non-contiguous Ehdr/Phdr; try '--force-execve'"); return false; } unsigned osabi0 = buf[Elf32_Ehdr::EI_OSABI]; // The first PT_LOAD32 must cover the beginning of the file (0==p_offset). unsigned const e_phnum = get_native16(&ehdr->e_phnum); Elf32_Phdr const *phdr = (Elf32_Phdr const *)(buf + e_phoff); for (unsigned j=0; j < e_phnum; ++phdr, ++j) { if (j >= 14) return false; unsigned const p_type = get_native32(&phdr->p_type); unsigned const p_offset = get_native32(&phdr->p_offset); if (1!=exetype && phdr->PT_LOAD32 == p_type) { if (p_offset != 0) { throwCantPack("invalid Phdr p_offset; try '--force-execve'"); return false; } exetype = 1; } if (Elf32_Ehdr::ELFOSABI_NONE==osabi0 // Still seems to be generic. && NULL!=osabi_note && phdr->PT_NOTE == p_type) { struct Elf32_Note note; memset(¬e, 0, sizeof(note)); fi->seek(p_offset, SEEK_SET); fi->readx(¬e, sizeof(note)); fi->seek(0, SEEK_SET); if (4==get_native32(¬e.descsz) && 1==get_native32(¬e.type) && 0==note.end && (1+ strlen(osabi_note))==get_native32(¬e.namesz) && 0==strcmp(osabi_note, (char const *)¬e.text) ) { osabi0 = ei_osabi; // Specified by PT_NOTE. } } } if (Elf32_Ehdr::ELFOSABI_NONE==osabi0) { // No EI_OSBAI, no PT_NOTE. osabi0 = opt->o_unix.osabi0; // Possibly specified by command-line. } if (osabi0!=ei_osabi) { return false; } // We want to compress position-independent executable (gcc -pie) // main programs, but compressing a shared library must be avoided // because the result is no longer usable. In theory, there is no way // to tell them apart: both are just ET_DYN. Also in theory, // neither the presence nor the absence of any particular symbol name // can be used to tell them apart; there are counterexamples. // However, we will use the following heuristic suggested by // Peter S. Mazinger <ps.m@gmx.net> September 2005: // If a ET_DYN has __libc_start_main as a global undefined symbol, // then the file is a position-independent executable main program // (that depends on libc.so.6) and is eligible to be compressed. // Otherwise (no __libc_start_main as global undefined): skip it. // Also allow __uClibc_main and __uClibc_start_main . if (Elf32_Ehdr::ET_DYN==get_native16(&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); ehdri= *ehdr; phdri= (Elf32_Phdr *)(e_phoff + file_image); // do not free() !! shdri= (Elf32_Shdr *)(e_shoff + file_image); // do not free() !! n_elf_shnum = get_native16(&ehdr->e_shnum); shdri = (Elf32_Shdr const *)(e_shoff + file_image); //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); sec_dynstr = get_native32(&sec_dynsym->sh_link) + shdri; int j= e_phnum; phdr= phdri; for (; --j>=0; ++phdr) if (Elf32_Phdr::PT_DYNAMIC==get_native32(&phdr->p_type)) { dynseg= (Elf32_Dyn const *)(get_native32(&phdr->p_offset) + file_image); break; } // elf_find_dynamic() returns 0 if 0==dynseg. gashtab= (unsigned int const *)elf_find_dynamic(Elf32_Dyn::DT_GNU_HASH); hashtab= (unsigned int const *)elf_find_dynamic(Elf32_Dyn::DT_HASH); dynstr= (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB); dynsym= (Elf32_Sym const *)elf_find_dynamic(Elf32_Dyn::DT_SYMTAB); // FIXME 2007-09-10 It seems that DT_GNU_HASH does not have undefined // symbols. So if no DT_HASH, then we would have to look in .dynsym. char const *const run_start[]= { "__libc_start_main", "__uClibc_main", "__uClibc_start_main", }; for (j=0; j<3; ++j) { // elf_lookup() returns 0 if any required table is missing. Elf32_Sym const *const lsm = elf_lookup(run_start[j]); if (lsm && get_native16(&lsm->st_shndx)==Elf32_Sym::SHN_UNDEF && get_native16(&lsm->st_info)==lsm->Elf32_Sym::make_st_info(Elf32_Sym::STB_GLOBAL, Elf32_Sym::STT_FUNC) && get_native16(&lsm->st_other)==Elf32_Sym::STV_DEFAULT ) { break; } if (sec_dynsym) { Elf32_Sym const *symp = (Elf32_Sym const *)(get_native32(&sec_dynsym->sh_offset) + file_image); Elf32_Sym const *const symlwa = (Elf32_Sym const *)( get_native32(&sec_dynsym->sh_size) + get_native32(&sec_dynsym->sh_offset) + file_image); for (; symp < symlwa; ++symp) if (0==strcmp(run_start[j], get_native32(&symp->st_name) + dynstr)) { goto found; } } }found: phdri = 0; // done "borrowing" this member if (3<=j) { return false; } } // XXX Theoretically the following test should be first, // but PackUnix::canPack() wants 0!=exetype ? if (!super::canPack()) return false; assert(exetype == 1); exetype = 0; // set options opt->o_unix.blocksize = blocksize = file_size; return true;}boolPackLinuxElf64amd::canPack(){ unsigned char buf[sizeof(Elf64_Ehdr) + 14*sizeof(Elf64_Phdr)]; COMPILE_TIME_ASSERT(sizeof(buf) <= 1024); fi->readx(buf, sizeof(buf)); fi->seek(0, SEEK_SET); Elf64_Ehdr const *const ehdr = (Elf64_Ehdr const *)buf; // now check the ELF header if (checkEhdr(ehdr) != 0) return false; // additional requirements for linux/elf386 if (get_native16(&ehdr->e_ehsize) != sizeof(*ehdr)) { throwCantPack("invalid Ehdr e_ehsize; try '--force-execve'"); return false; } acc_uint64l_t const e_phoff = get_native64(&ehdr->e_phoff); if (e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr throwCantPack("non-contiguous Ehdr/Phdr; try '--force-execve'"); return false; } // The first PT_LOAD64 must cover the beginning of the file (0==p_offset). unsigned const e_phnum = get_native16(&ehdr->e_phnum); Elf64_Phdr const *phdr = (Elf64_Phdr const *)(buf + (unsigned) e_phoff); for (unsigned j=0; j < e_phnum; ++phdr, ++j) { if (j >= 14) return false; if (phdr->PT_LOAD64 == get_native32(&phdr->p_type)) { // Just avoid the "rewind" when unpacking? //if (phdr->p_offset != 0) { // throwCantPack("invalid Phdr p_offset; try '--force-execve'"); // return false; //} exetype = 1; break; } } if (!super::canPack()) return false; assert(exetype == 1); exetype = 0; // set options opt->o_unix.blocksize = blocksize = file_size; return true;}off_tPackLinuxElf32::getbrk(const Elf32_Phdr *phdr, int e_phnum) const{ off_t brka = 0; for (int j = 0; j < e_phnum; ++phdr, ++j) { if (PT_LOAD32 == get_native32(&phdr->p_type)) { off_t b = get_native32(&phdr->p_vaddr) + get_native32(&phdr->p_memsz); if (b > brka) brka = b; } } return brka;}off_tPackLinuxElf32::getbase(const Elf32_Phdr *phdr, int e_phnum) const{ off_t base = ~0u; for (int j = 0; j < e_phnum; ++phdr, ++j) { if (phdr->PT_LOAD == phdr->p_type) { if (phdr->p_vaddr < (unsigned) base) base = phdr->p_vaddr; } } if (0!=base) { return base; } return 0x12000;}off_tPackLinuxElf64::getbrk(const Elf64_Phdr *phdr, int e_phnum) const{ off_t brka = 0; for (int j = 0; j < e_phnum; ++phdr, ++j) { if (PT_LOAD64 == get_native32(&phdr->p_type)) { off_t b = get_native64(&phdr->p_vaddr) + get_native64(&phdr->p_memsz); if (b > brka) brka = b; } } return brka;}voidPackLinuxElf32::generateElfHdr( OutputFile *fo, void const *proto, unsigned const brka){ cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout; cprElfHdr3 *const h3 = (cprElfHdr3 *)&elfout; memcpy(h3, proto, sizeof(*h3)); // reads beyond, but OK h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = ei_osabi; if (Elf32_Ehdr::EM_MIPS==e_machine) { // MIPS R3000 FIXME h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = Elf32_Ehdr::ELFOSABI_NONE; h3->ehdr.e_flags = ehdri.e_flags; } assert(get_native32(&h2->ehdr.e_phoff) == sizeof(Elf32_Ehdr)); h2->ehdr.e_shoff = 0; assert(get_native16(&h2->ehdr.e_ehsize) == sizeof(Elf32_Ehdr)); assert(get_native16(&h2->ehdr.e_phentsize) == sizeof(Elf32_Phdr)); set_native16(&h2->ehdr.e_shentsize, sizeof(Elf32_Shdr)); h2->ehdr.e_shnum = 0; h2->ehdr.e_shstrndx = 0; sz_elf_hdrs = sizeof(*h2) - sizeof(linfo); // default set_native32(&h2->phdr[0].p_filesz, sizeof(*h2)); // + identsize; h2->phdr[0].p_memsz = h2->phdr[0].p_filesz; unsigned const e_phnum = get_native16(&ehdri.e_phnum); Elf32_Phdr const *phdr = phdri; for (unsigned j=0; j < e_phnum; ++phdr, ++j) { if (phdr->PT_LOAD32 == get_native32(&phdr->p_type)) { unsigned x = get_native32(&phdr->p_align) >> lg2_page; while (x>>=1) { ++lg2_page; } } } page_size = 1u<<lg2_page; page_mask = ~0u<<lg2_page; for (unsigned j=0; j < 3; ++j) { set_native32(&h3->phdr[j].p_align, page_size); } // Info for OS kernel to set the brk() if (brka) { // linux-2.6.14 binfmt_elf.c: SIGKILL if (0==.p_memsz) on a page boundary unsigned const brkb = brka | ((0==(~page_mask & brka)) ? 0x20 : 0); set_native32(&h2->phdr[1].p_type, PT_LOAD32); // be sure set_native32(&h2->phdr[1].p_offset, ~page_mask & brkb); set_native32(&h2->phdr[1].p_vaddr, brkb); set_native32(&h2->phdr[1].p_paddr, brkb); h2->phdr[1].p_filesz = 0; h2->phdr[1].p_memsz = 0; set_native32(&h2->phdr[1].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W); } if (ph.format==getFormat()) { assert(2==get_native16(&h2->ehdr.e_phnum)); set_native32(&h2->phdr[0].p_flags, ~Elf32_Phdr::PF_W & get_native32(&h2->phdr[0].p_flags)); memset(&h2->linfo, 0, sizeof(h2->linfo)); fo->write(h2, sizeof(*h2)); } else { assert(false); // unknown ph.format, PackLinuxElf32 }}voidPackOpenBSDElf32x86::generateElfHdr( OutputFile *fo, void const *proto, unsigned const brka){ cprElfHdr3 *const h3 = (cprElfHdr3 *)&elfout; memcpy(h3, proto, sizeof(*h3)); // reads beyond, but OK h3->ehdr.e_ident[Elf32_Ehdr::EI_OSABI] = ei_osabi; assert(2==get_native16(&h3->ehdr.e_phnum)); set_native16(&h3->ehdr.e_phnum, 3); assert(get_native32(&h3->ehdr.e_phoff) == sizeof(Elf32_Ehdr)); h3->ehdr.e_shoff = 0; assert(get_native16(&h3->ehdr.e_ehsize) == sizeof(Elf32_Ehdr)); assert(get_native16(&h3->ehdr.e_phentsize) == sizeof(Elf32_Phdr)); set_native16(&h3->ehdr.e_shentsize, sizeof(Elf32_Shdr)); h3->ehdr.e_shnum = 0; h3->ehdr.e_shstrndx = 0; sz_elf_hdrs = sizeof(*h3) - sizeof(linfo); unsigned const note_offset = sz_elf_hdrs; set_native32(&h3->phdr[0].p_filesz, sizeof(*h3)+sizeof(elfnote)); // + identsize; h3->phdr[0].p_memsz = h3->phdr[0].p_filesz; unsigned const brkb = brka | ((0==(~page_mask & brka)) ? 0x20 : 0); set_native32(&h3->phdr[1].p_type, PT_LOAD32); // be sure set_native32(&h3->phdr[1].p_offset, ~page_mask & brkb); set_native32(&h3->phdr[1].p_vaddr, brkb); set_native32(&h3->phdr[1].p_paddr, brkb); h3->phdr[1].p_filesz = 0; h3->phdr[1].p_memsz = 0; set_native32(&h3->phdr[1].p_flags, Elf32_Phdr::PF_R | Elf32_Phdr::PF_W); set_native32(&h3->phdr[2].p_type, Elf32_Phdr::PT_NOTE); set_native32(&h3->phdr[2].p_offset, note_offset); set_native32(&h3->phdr[2].p_vaddr, note_offset); set_native32(&h3->phdr[2].p_paddr, note_offset); set_native32(&h3->phdr[2].p_filesz, sizeof(elfnote)); set_native32(&h3->phdr[2].p_memsz, sizeof(elfnote)); set_native32(&h3->phdr[2].p_flags, Elf32_Phdr::PF_R); set_native32(&h3->phdr[2].p_align, 4); set_native32(&elfnote.namesz, 8); set_native32(&elfnote.descsz, 4); set_native32(&elfnote.type, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -