📄 p_vmlinx.cpp
字号:
} fo->write(&hdr_info, sizeof(hdr_info)); fo_off += sizeof(hdr_info); ppc32_extra += sizeof(hdr_info); if (ph.u_len!=f_len) { set_be32(&hdr_info.sz_unc, f_ptr - (upx_bytep) ibuf); set_be32(&hdr_info.sz_cpr, f_len); fo->write(&hdr_info, 2*sizeof(unsigned)); fo_off += 2*sizeof(unsigned); ppc32_extra += 2*sizeof(unsigned); }#if 0 /*{ Documentation: changes to arch/powerpc/boot/main.c */struct b_info { unsigned sz_unc; unsigned sz_cpr; unsigned char b_method; unsigned char b_ftid; unsigned char b_cto8; unsigned char b_unused;};typedef int (*upx_f_unc)( /* uncompress */ unsigned char const *src, unsigned src_len, unsigned char *dst, unsigned *dst_len, int method);typedef int (*upx_f_unf)( /* unfilter */ unsigned char *buf, unsigned len, unsigned cto8, unsigned ftid);unsigned char const *upx_expand( // return updated src [aligned, too] unsigned char const *src, unsigned char *dst, unsigned *const dst_len, upx_f_unc const f_unc){ if (0==*dst_len) { *dst_len = ((struct b_info const *)src)->sz_unc; } upx_f_unf const f_unf = (upx_f_unf)(sizeof(int) + (char *)f_unc); unsigned total_len = 0; unsigned need = *dst_len; while (0 < need) { struct b_info const *const b_hdr = (struct b_info const *)src; src = (unsigned char const *)(1+ b_hdr); unsigned blk_len = b_hdr->sz_unc; int const rv = (*f_unc)(src, b_hdr->sz_cpr, dst, &blk_len, b_hdr->b_method); if (0!=rv) { printf("decompress error %d\n\r", rv); exit(); } if (b_hdr->b_ftid) { (*f_unf)(dst, b_hdr->sz_unc, b_hdr->b_cto8, b_hdr->b_ftid); } src += b_hdr->sz_cpr; src += (3& -(int)src); // 4-byte align dst += b_hdr->sz_unc; total_len += b_hdr->sz_unc; need -= b_hdr->sz_unc; } *dst_len = total_len; return src;}void prep_kernel(unsigned long a1, unsigned long a2){ upx_f_unc f_unc = (upx_f_unc)0; vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); if (0x55505821 == *(unsigned *)vmlinuz.addr) { /* was compressed by upx */ /* Uncompress elfheader */ unsigned const *const fwa = (unsigned *)vmlinuz.addr; f_unc = (upx_f_unc)((char *)&fwa[2] + fwa[1]); unsigned dst_len = 0; unsigned char const *src = (unsigned char const *)&fwa[2]; src = upx_expand(src, (unsigned char *)elfheader, &dst_len, f_unc); unsigned const src_len = src - (unsigned char const *)&fwa[0]; vmlinuz.addr += src_len; vmlinuz.size -= src_len; } else { memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader)); }===== /* Eventually gunzip the kernel */ if (f_unc) { /* was compressed by upx */ printf("upx_expand (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); unsigned dst_len = vmlinux.size - elfoffset; upx_expand((unsigned char const *)vmlinuz.addr, (unsigned char *)vmlinux.addr, &dst_len, f_unc); printf("done 0x%lx bytes\n\r", len); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr, vmlinuz.size); /* Skip over the ELF header */#ifdef DEBUG printf("... skipping 0x%lx bytes of ELF header\n\r", elfoffset);#endif vmlinux.addr += elfoffset; }=====}#endif /*}*/ } else { compressWithFilters(&ft, 512, &cconf, getStrategy(ft)); } unsigned const txt_c_len = ph.c_len; const unsigned lsize = getLoaderSize(); defineDecompressorSymbols(); defineFilterSymbols(&ft); relocateLoader(); MemBuffer loader(lsize); memcpy(loader, getLoader(), lsize); patchPackHeader(loader, lsize);#define shstrtab local_shstrtab // avoid -Wshadow warning char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab"; char const *p = shstrtab; while (0!=*p++) ; shdro[1].sh_name = ptr_diff(p, shstrtab); shdro[1].sh_type = Shdr::SHT_PROGBITS; shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR; shdro[1].sh_offset = fo_off - ppc32_extra; shdro[1].sh_size = ppc32_extra + txt_c_len + lsize; // plus more ... shdro[1].sh_addralign = 1; // default fo_off += write_vmlinux_head(fo, &shdro[1]); fo->write(obuf, txt_c_len); fo_off += txt_c_len; unsigned const a = (shdro[1].sh_addralign -1) & (0u-(ppc32_extra + txt_c_len)); if (0!=a) { // align fo_off += a; shdro[1].sh_size += a; fo->seek(a, SEEK_CUR); } fo->write(loader, lsize); fo_off += lsize;#if 0 printf("%-13s: compressed : %8u bytes\n", getName(), txt_c_len); printf("%-13s: decompressor : %8u bytes\n", getName(), lsize);#endif verifyOverlappingDecompression(); // .note with 1st page -------------------------------- ph.u_len = phdri[0].p_offset; fi->seek(0, SEEK_SET); fi->readx(ibuf, ph.u_len); compress(ibuf, ph.u_len, obuf, &cconf); while (0!=*p++) ; shdro[2].sh_name = ptr_diff(p, shstrtab); shdro[2].sh_type = Shdr::SHT_NOTE; shdro[2].sh_offset = fo_off; shdro[2].sh_size = sizeof(ph.u_len) + ph.c_len; shdro[2].sh_addralign = 1; tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4); fo->write(obuf, ph.c_len); fo_off += shdro[2].sh_size; // .note with rest -------------------------------- ph.u_len = file_size - (sz_ptload + phdri[0].p_offset); fi->seek(sz_ptload + phdri[0].p_offset, SEEK_SET); fi->readx(ibuf, ph.u_len); // Temporarily decrease ph.level by about (1+ log2(sz_rest / sz_ptload)) // to avoid spending unreasonable effort compressing large symbol tables // that are discarded 99.9% of the time anyway. int const old_level = ph.level; for (unsigned v = ((ph.u_len>>3) + ph.u_len) / sz_ptload; 0 < v; v>>=1) { if (0== --ph.level) { ph.level = 1; } } compress(ibuf, ph.u_len, obuf, &cconf); ph.level = old_level; // while (0!=*p++) ; // name is the same shdro[3].sh_name = ptr_diff(p, shstrtab); shdro[3].sh_type = Shdr::SHT_NOTE; shdro[3].sh_offset = fo_off; shdro[3].sh_size = sizeof(ph.u_len) + ph.c_len; shdro[3].sh_addralign = 1; tmp_u32 = ph.u_len; fo->write(&tmp_u32, 4); fo->write(obuf, ph.c_len); fo_off += shdro[3].sh_size; while (0!=*p++) ; shdro[4].sh_name = ptr_diff(p, shstrtab); shdro[4].sh_type = Shdr::SHT_STRTAB; shdro[4].sh_offset = fo_off; shdro[4].sh_size = sizeof(shstrtab); // already includes terminating '\0' shdro[4].sh_addralign = 1; fo->write(shstrtab, shdro[4].sh_size); fo_off += shdro[4].sh_size; fo_off = ~3 & (3+ fo_off); fo->seek(fo_off, SEEK_SET); while (0!=*p++) ; shdro[5].sh_name = ptr_diff(p, shstrtab); shdro[5].sh_type = Shdr::SHT_SYMTAB; shdro[5].sh_offset = fo_off; shdro[5].sh_size = ((Ehdr::EM_PPC==my_e_machine) + 5)*sizeof(Sym); //shdro[5].sh_flags = Shdr::SHF_INFO_LINK; shdro[5].sh_link = 6; // to .strtab for symbols shdro[5].sh_info = 1+3; // number of non-global symbols [binutils/bfd/elf.c] shdro[5].sh_addralign = 4; shdro[5].sh_entsize = sizeof(Sym); Sym sec_sym; // Symbol 0; no references, but bfd demands it. memset(&sec_sym, 0, sizeof(sec_sym)); fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym); // Each section before .shstrtab needs a symbol. sec_sym.st_info = sec_sym.make_st_info(Sym::STB_LOCAL, Sym::STT_SECTION); sec_sym.st_other = Sym::STV_DEFAULT; sec_sym.st_shndx = 1; // .text fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym); sec_sym.st_shndx = 2; // .note fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym); sec_sym.st_shndx = 3; // .note fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym); // the symbol we care about Sym unc_ker; unc_ker.st_name = 1; // 1 byte into strtab unc_ker.st_value = 0; unc_ker.st_size = ppc32_extra + txt_c_len; unc_ker.st_info = unc_ker.make_st_info(Sym::STB_GLOBAL, Sym::STT_FUNC); unc_ker.st_other = Sym::STV_DEFAULT; unc_ker.st_shndx = 1; // .text fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker); unsigned const lablen = strlen(my_boot_label); if (Ehdr::EM_PPC==my_e_machine) { unc_ker.st_name += 1+ lablen; unc_ker.st_value = unc_ker.st_size; unc_ker.st_size = 0; fo->write(&unc_ker, sizeof(unc_ker)); fo_off += sizeof(unc_ker); } while (0!=*p++) ; shdro[6].sh_name = ptr_diff(p, shstrtab); shdro[6].sh_type = Shdr::SHT_STRTAB; shdro[6].sh_offset = fo_off; shdro[6].sh_size = 2+ lablen + (Ehdr::EM_PPC==my_e_machine)*(1+ 12); // '\0' before and after shdro[6].sh_addralign = 1; fo->seek(1, SEEK_CUR); // the '\0' before fo->write(my_boot_label, 1+ lablen); // include the '\0' terminator if (Ehdr::EM_PPC==my_e_machine) { fo->write("_vmlinux_end", 1+ 12); fo_off += 1+ 12; } fo_off += 2+ lablen; fo->seek(0, SEEK_SET); fo->write(&ehdro, sizeof(ehdro)); fo->write(&shdro, sizeof(shdro)); if (Ehdr::EM_PPC==my_e_machine) { fo->seek(sizeof(unsigned), SEEK_CUR); set_be32(&ppc32_extra, ppc32_extra - 2*sizeof(unsigned) + txt_c_len); fo->write(&ppc32_extra, sizeof(ppc32_extra)); } if (!checkFinalCompressionRatio(fo)) throwNotCompressible();#undef shstrtab}template <class T>int PackVmlinuxBase<T>::canUnpack(){ fi->seek(0, SEEK_SET); fi->readx(&ehdri, sizeof(ehdri)); // now check the ELF header if (memcmp(&ehdri, "\x7f\x45\x4c\x46", 4) || ehdri.e_ident[Ehdr::EI_CLASS] != my_elfclass || ehdri.e_ident[Ehdr::EI_DATA] != my_elfdata || ehdri.e_ident[Ehdr::EI_VERSION] != Ehdr::EV_CURRENT || !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded || ehdri.e_machine != my_e_machine || ehdri.e_version != 1 // version || ehdri.e_ehsize != sizeof(ehdri) // different <elf.h> ? ) return false; if (ehdri.e_type != Ehdr::ET_REL //i386 fails || ehdri.e_shoff != sizeof(ehdri) // Shdr not contiguous with Ehdr || ehdri.e_shentsize!=sizeof(Shdr) || ehdri.e_shnum < 4 || (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff) ) return false; // find the .shstrtab section Shdr const *const shstrsec = getElfSections(); if (0==shstrsec) { return false; } // check for .text .note .note and sane (.sh_size + .sh_offset) p_note0 = p_note1 = p_text = 0; int j; Shdr *p; for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) { if ((unsigned)file_size < (p->sh_size + p->sh_offset) || shstrsec->sh_size < (5+ p->sh_name) ) { continue; } if (0==strcmp(".text", shstrtab + p->sh_name)) { p_text = p; } if (0==strcmp(".note", shstrtab + p->sh_name)) { if (0==p_note0) { p_note0 = p; } else if (0==p_note1) { p_note1 = p; } } } if (0==p_text || 0==p_note0 || 0==p_note1) { return false; } char buf[1024]; fi->seek(p_text->sh_offset + p_text->sh_size - sizeof(buf), SEEK_SET); fi->readx(buf, sizeof(buf)); if (!getPackHeader(buf, sizeof(buf))) return -1; // format is known, but definitely is not packed return true;}template <class T>void PackVmlinuxBase<T>::unpack(OutputFile *fo){ U32 word; PackHeader const ph_tmp(ph); fi->seek(p_note0->sh_offset, SEEK_SET); fi->readx(&word, sizeof(word)); ph.u_len = word; ph.c_len = p_note0->sh_size - sizeof(word); ibuf.alloc(ph.c_len); fi->readx(ibuf, ph.c_len); obuf.allocForUncompression(ph.u_len); decompress(ibuf, obuf, false); fo->write(obuf, ph.u_len); obuf.dealloc(); ibuf.dealloc(); ph = ph_tmp; if (!has_valid_vmlinux_head()) { throwCantUnpack(".text corrupted"); } ibuf.alloc(ph.c_len); fi->readx(ibuf, ph.c_len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -