📄 p_lx_elf.cpp
字号:
strcpy(elfnote.text, "OpenBSD"); elfnote.end = 0; if (ph.format==getFormat()) { memset(&h3->linfo, 0, sizeof(h3->linfo)); fo->write(h3, sizeof(*h3) - sizeof(h3->linfo)); fo->write(&elfnote, sizeof(elfnote)); fo->write(&h3->linfo, sizeof(h3->linfo)); } else { assert(false); // unknown ph.format, PackLinuxElf32 }}voidPackLinuxElf64::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; assert(get_native32(&h2->ehdr.e_phoff) == sizeof(Elf64_Ehdr)); h2->ehdr.e_shoff = 0; assert(get_native16(&h2->ehdr.e_ehsize) == sizeof(Elf64_Ehdr)); assert(get_native16(&h2->ehdr.e_phentsize) == sizeof(Elf64_Phdr)); set_native16(&h2->ehdr.e_shentsize, sizeof(Elf64_Shdr)); h2->ehdr.e_shnum = 0; h2->ehdr.e_shstrndx = 0; sz_elf_hdrs = sizeof(*h2) - sizeof(linfo); // default set_native64(&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); Elf64_Phdr const *phdr = phdri; for (unsigned j=0; j < e_phnum; ++phdr, ++j) { if (phdr->PT_LOAD64 == get_native64(&phdr->p_type)) { unsigned x = get_native64(&phdr->p_align) >> lg2_page; while (x>>=1) { ++lg2_page; } } } page_size = 1u <<lg2_page; page_mask = ~0ull<<lg2_page; for (unsigned j=0; j < 3; ++j) { set_native64(&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_LOAD64); // be sure set_native64(&h2->phdr[1].p_offset, ~page_mask & brkb); set_native64(&h2->phdr[1].p_vaddr, brkb); set_native64(&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, Elf64_Phdr::PF_R | Elf64_Phdr::PF_W); } if (ph.format==getFormat()) { assert(2==get_native16(&h2->ehdr.e_phnum)); set_native32(&h2->phdr[0].p_flags, ~Elf64_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, PackLinuxElf64 }}void PackLinuxElf32::pack1(OutputFile */*fo*/, Filter &/*ft*/){ fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); unsigned const e_phoff = get_native32(&ehdri.e_phoff); unsigned const e_phnum = get_native16(&ehdri.e_phnum); assert(e_phoff == sizeof(Elf32_Ehdr)); // checked by canPack() sz_phdrs = e_phnum * get_native16(&ehdri.e_phentsize); phdri = new Elf32_Phdr[e_phnum]; fi->seek(e_phoff, SEEK_SET); fi->readx(phdri, sz_phdrs); progid = 0; // getRandomId(); not useful, so do not clutter}void PackLinuxElf32x86::pack1(OutputFile *fo, Filter &ft){ PackLinuxElf32::pack1(fo, ft); generateElfHdr(fo, stub_i386_linux_elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackBSDElf32x86::pack1(OutputFile *fo, Filter &ft){ PackLinuxElf32::pack1(fo, ft); generateElfHdr(fo, stub_i386_bsd_elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf32armLe::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); cprElfHdr3 h3; memcpy(&h3, stub_arm_linux_elf_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr)); generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf32armBe::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); cprElfHdr3 h3; memcpy(&h3, stub_armeb_linux_elf_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr)); generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf32mipsel::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); cprElfHdr3 h3; memcpy(&h3, stub_mipsel_r3000_linux_elf_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr)); generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf32mipseb::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); cprElfHdr3 h3; memcpy(&h3, stub_mips_r3000_linux_elf_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr)); generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf32ppc::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); generateElfHdr(fo, stub_powerpc_linux_elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}void PackLinuxElf64::pack1(OutputFile */*fo*/, Filter &/*ft*/){ fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); unsigned const e_phoff = get_native32(&ehdri.e_phoff); unsigned const e_phnum = get_native16(&ehdri.e_phnum); assert(e_phoff == sizeof(Elf64_Ehdr)); // checked by canPack() sz_phdrs = e_phnum * get_native16(&ehdri.e_phentsize); phdri = new Elf64_Phdr[e_phnum]; fi->seek(e_phoff, SEEK_SET); fi->readx(phdri, sz_phdrs); progid = 0; // getRandomId(); not useful, so do not clutter}void PackLinuxElf64amd::pack1(OutputFile *fo, Filter &ft){ super::pack1(fo, ft); generateElfHdr(fo, stub_amd64_linux_elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );}// Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD// which follows in the file (or end-of-file). Optimize for common case// where the PT_LOAD are adjacent ascending by .p_offset. Assume no overlap.unsigned PackLinuxElf32::find_LOAD_gap( Elf32_Phdr const *const phdr, unsigned const k, unsigned const e_phnum){ if (PT_LOAD32!=get_native32(&phdr[k].p_type)) { return 0; } unsigned const hi = get_native32(&phdr[k].p_offset) + get_native32(&phdr[k].p_filesz); unsigned lo = ph.u_file_size; unsigned j = k; for (;;) { // circular search, optimize for adjacent ascending ++j; if (e_phnum==j) { j = 0; } if (k==j) { break; } if (PT_LOAD32==get_native32(&phdr[j].p_type)) { unsigned const t = get_native32(&phdr[j].p_offset); if ((t - hi) < (lo - hi)) { lo = t; if (hi==lo) { break; } } } } return lo - hi;}void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft){ Extent x; unsigned k; // count passes, set ptload vars uip->ui_total_passes = 0; unsigned const e_phnum = get_native16(&ehdri.e_phnum); for (k = 0; k < e_phnum; ++k) { if (PT_LOAD32 == get_native32(&phdri[k].p_type)) { uip->ui_total_passes++; if (find_LOAD_gap(phdri, k, e_phnum)) { uip->ui_total_passes++; } } } // compress extents unsigned total_in = 0; unsigned total_out = 0; unsigned hdr_u_len = sizeof(Elf32_Ehdr) + sz_phdrs; uip->ui_pass = 0; ft.addvalue = 0; int nx = 0; for (k = 0; k < e_phnum; ++k) if (PT_LOAD32==get_native32(&phdri[k].p_type)) { if (ft.id < 0x40) { // FIXME: ?? ft.addvalue = phdri[k].p_vaddr; } x.offset = get_native32(&phdri[k].p_offset); x.size = get_native32(&phdri[k].p_filesz); if (0 == nx) { // 1st PT_LOAD32 must cover Ehdr at 0==p_offset unsigned const delta = sizeof(Elf32_Ehdr) + sz_phdrs; if (ft.id < 0x40) { // FIXME: ?? ft.addvalue += delta; } x.offset += delta; x.size -= delta; } // compressWithFilters() always assumes a "loader", so would // throw NotCompressible for small .data Extents, which PowerPC // sometimes marks as PF_X anyway. So filter only first segment. packExtent(x, total_in, total_out, ((0==nx && (Elf32_Phdr::PF_X & get_native32(&phdri[k].p_flags))) ? &ft : 0 ), fo, hdr_u_len); hdr_u_len = 0; ++nx; } for (k = 0; k < e_phnum; ++k) { x.size = find_LOAD_gap(phdri, k, e_phnum); if (x.size) { x.offset = get_native32(&phdri[k].p_offset) + get_native32(&phdri[k].p_filesz); packExtent(x, total_in, total_out, 0, fo); } } if ((off_t)total_in != file_size) throwEOFException();}// Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD// which follows in the file (or end-of-file). Optimize for common case// where the PT_LOAD are adjacent ascending by .p_offset. Assume no overlap.unsigned PackLinuxElf64::find_LOAD_gap( Elf64_Phdr const *const phdr, unsigned const k, unsigned const e_phnum){ if (PT_LOAD64!=get_native32(&phdr[k].p_type)) { return 0; } unsigned const hi = get_native64(&phdr[k].p_offset) + get_native64(&phdr[k].p_filesz); unsigned lo = ph.u_file_size; unsigned j = k; for (;;) { // circular search, optimize for adjacent ascending ++j; if (e_phnum==j) { j = 0; } if (k==j) { break; } if (PT_LOAD64==get_native32(&phdr[j].p_type)) { unsigned const t = get_native64(&phdr[j].p_offset); if ((t - hi) < (lo - hi)) { lo = t; if (hi==lo) { break; } } } } return lo - hi;}void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft){ Extent x; unsigned k; // count passes, set ptload vars uip->ui_total_passes = 0; unsigned const e_phnum = get_native16(&ehdri.e_phnum); for (k = 0; k < e_phnum; ++k) { if (PT_LOAD64==get_native32(&phdri[k].p_type)) { uip->ui_total_passes++; if (find_LOAD_gap(phdri, k, e_phnum)) { uip->ui_total_passes++; } } } // compress extents unsigned total_in = 0; unsigned total_out = 0; unsigned hdr_u_len = sizeof(Elf64_Ehdr) + sz_phdrs; uip->ui_pass = 0; ft.addvalue = 0; int nx = 0; for (k = 0; k < e_phnum; ++k) if (PT_LOAD64==get_native32(&phdri[k].p_type)) { if (ft.id < 0x40) { // FIXME: ?? ft.addvalue = phdri[k].p_vaddr; } x.offset = get_native64(&phdri[k].p_offset); x.size = get_native64(&phdri[k].p_filesz); if (0 == nx) { // 1st PT_LOAD64 must cover Ehdr at 0==p_offset unsigned const delta = sizeof(Elf64_Ehdr) + sz_phdrs; if (ft.id < 0x40) { // FIXME: ?? ft.addvalue += delta; } x.offset += delta; x.size -= delta; } // compressWithFilters() always assumes a "loader", so would // throw NotCompressible for small .data Extents, which PowerPC // sometimes marks as PF_X anyway. So filter only first segment. packExtent(x, total_in, total_out, ((0==nx && (Elf64_Phdr::PF_X & get_native64(&phdri[k].p_flags))) ? &ft : 0 ), fo, hdr_u_len); hdr_u_len = 0; ++nx; } for (k = 0; k < e_phnum; ++k) { x.size = find_LOAD_gap(phdri, k, e_phnum); if (x.size) { x.offset = get_native64(&phdri[k].p_offset) + get_native64(&phdri[k].p_filesz); packExtent(x, total_in, total_out, 0, fo); } } if ((off_t)total_in != file_size) throwEOFException();}#include "bele.h"using namespace N_BELE_CTP;// Filter 0x50, 0x51 assume HostPolicy::isLEstatic const int *ARM_getFilters(bool const isBE){ static const int f50[] = { 0x50, FT_END }; static const int f51[] = { 0x51, FT_END }; if (isBE) return f51; return f50;}const int *PackLinuxElf32armBe::getFilters() const{ return ARM_getFilters(true);}const int *PackLinuxElf32armLe::getFilters() const{ return ARM_getFilters(false);}const int *PackLinuxElf32mipseb::getFilters() const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -