1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

vmlinux: use template types throughout.

This commit is contained in:
Markus F.X.J. Oberhumer 2006-12-19 11:06:58 +01:00
parent f00c0a9436
commit 8795f60bf1
2 changed files with 92 additions and 88 deletions

View File

@ -91,7 +91,7 @@ PackVmlinuxBase<T>::compare_Phdr(void const *aa, void const *bb)
}
template <class T>
class T::Shdr const *PackVmlinuxBase<T>::getElfSections()
typename T::Shdr const *PackVmlinuxBase<T>::getElfSections()
{
Shdr const *p, *shstrsec=0;
shdri = new Shdr[(unsigned) ehdri.e_shnum];
@ -125,9 +125,9 @@ bool PackVmlinuxBase<T>::canPack()
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46", 4)
|| ehdri.e_ident[/*EI_CLASS*/ 4]!=my_elfclass
|| ehdri.e_ident[/*EI_DATA*/ 5]!=my_elfdata
|| ehdri.e_ident[/*EI_VERSION*/ 6]!=1 // EV_CURRENT
|| 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_version != 1 // version
|| ehdri.e_ehsize != sizeof(ehdri) // different <elf.h> ?
@ -138,7 +138,7 @@ bool PackVmlinuxBase<T>::canPack()
// additional requirements for vmlinux
if (ehdri.e_machine != my_e_machine
|| ehdri.e_type!=Ehdr::ET_EXEC
|| ehdri.e_type != Ehdr::ET_EXEC
|| !is_valid_e_entry(ehdri.e_entry)
) {
return false;
@ -189,6 +189,7 @@ bool PackVmlinuxBase<T>::canPack()
return 0 < n_ptload;
}
/*************************************************************************
//
**************************************************************************/
@ -346,13 +347,13 @@ static const
void PackVmlinuxI386::pack(OutputFile *fo)
{
unsigned fo_off = 0;
Elf32_Ehdr ehdro;
LE32 tmp_le32;
Ehdr ehdro;
U32 tmp_u32; // for external representation
// NULL
// .text(PT_LOADs) .note(1st page) .note(rest)
// .shstrtab /* .symtab .strtab */
Elf32_Shdr shdro[1+3+1/*+2*/];
Shdr shdro[1+3+1/*+2*/];
memset(shdro, 0, sizeof(shdro));
ibuf.alloc(file_size);
@ -360,7 +361,7 @@ void PackVmlinuxI386::pack(OutputFile *fo)
// .e_ident, .e_machine, .e_version, .e_flags
memcpy(&ehdro, &ehdri, sizeof(ehdro));
ehdro.e_type = Elf32_Ehdr::ET_REL;
ehdro.e_type = Ehdr::ET_REL;
ehdro.e_entry = 0;
ehdro.e_phoff = 0;
ehdro.e_shoff = 0; // later
@ -404,19 +405,19 @@ void PackVmlinuxI386::pack(OutputFile *fo)
char const *p = shstrtab;
while (0!=*p++) ;
shdro[1].sh_name = ptr_diff(p, shstrtab);
shdro[1].sh_type = Elf32_Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Elf32_Shdr::SHF_ALLOC | Elf32_Shdr::SHF_EXECINSTR;
shdro[1].sh_type = Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
shdro[1].sh_offset = fo_off;
shdro[1].sh_size = sizeof(stub_i386_linux_kernel_vmlinux_head) + ph.c_len + lsize;
shdro[1].sh_addralign = 1;
// ENTRY_POINT
fo->write(&stub_i386_linux_kernel_vmlinux_head[0], sizeof(stub_i386_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
tmp_u32 = ehdri.e_entry; fo->write(&tmp_u32, 4);
// COMPRESSED_LENGTH
fo->write(&stub_i386_linux_kernel_vmlinux_head[sizeof(stub_i386_linux_kernel_vmlinux_head)-(1+ 4)], 1);
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4);
tmp_u32 = ph.c_len; fo->write(&tmp_u32, 4);
fo_off += sizeof(stub_i386_linux_kernel_vmlinux_head);
@ -437,11 +438,11 @@ void PackVmlinuxI386::pack(OutputFile *fo)
while (0!=*p++) ;
shdro[2].sh_name = ptr_diff(p, shstrtab);
shdro[2].sh_type = Elf32_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 --------------------------------
@ -463,16 +464,16 @@ void PackVmlinuxI386::pack(OutputFile *fo)
// while (0!=*p++) ; // name is the same
shdro[3].sh_name = ptr_diff(p, shstrtab);
shdro[3].sh_type = Elf32_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 = Elf32_Shdr::SHT_STRTAB;
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;
@ -482,18 +483,18 @@ void PackVmlinuxI386::pack(OutputFile *fo)
while (0!=*p++) ;
fo_off = ~3 & (3+ fo_off);
shdro[5].sh_name = ptr_diff(p, shstrtab);
shdro[5].sh_type = Elf32_Shdr::SHT_SYMTAB;
shdro[5].sh_type = Shdr::SHT_SYMTAB;
shdro[5].sh_offset = fo_off;
shdro[5].sh_size = 16; // XXX ?
shdro[5].sh_link = 6; // to .strtab for symbols
shdro[5].sh_addralign = 4;
shdro[5].sh_entsize = 16; // XXX Elf32_Sym
shdro[5].sh_entsize = 16; // XXX Sym
fo->seek(fo_off, SEEK_SET);
fo->write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); fo_off += 16;
while (0!=*p++) ;
shdro[6].sh_name = ptr_diff(p, shstrtab);
shdro[6].sh_type = Elf32_Shdr::SHT_STRTAB;
shdro[6].sh_type = Shdr::SHT_STRTAB;
shdro[6].sh_offset = fo_off;
shdro[6].sh_size = 1; // XXX ?
shdro[6].sh_addralign = 1;
@ -526,16 +527,16 @@ int PackVmlinuxI386::canUnpack()
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46\x01\x01\x01", 7) // ELF 32-bit LSB
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|| ehdri.e_machine != Elf32_Ehdr::EM_386
|| ehdri.e_machine != Ehdr::EM_386
|| ehdri.e_version != 1 // version
|| ehdri.e_type != Elf32_Ehdr::ET_REL
|| ehdri.e_type != Ehdr::ET_REL
|| ehdri.e_shnum < 4
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Elf32_Shdr) + ehdri.e_shoff)
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff)
)
return false;
// find the .shstrtab section
Elf_LE32_Shdr const *const shstrsec = getElfSections();
Shdr const *const shstrsec = getElfSections();
if (0==shstrsec) {
return false;
}
@ -543,7 +544,7 @@ int PackVmlinuxI386::canUnpack()
// check for .text .note .note and sane (.sh_size + .sh_offset)
p_note0 = p_note1 = p_text = 0;
int j;
Elf_LE32_Shdr *p;
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) ) {
@ -582,7 +583,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
fi->seek(p_note0->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note0->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, ph.c_len);
@ -595,7 +596,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
ph = ph_tmp;
fi->seek(p_text->sh_offset + sizeof(stub_i386_linux_kernel_vmlinux_head) -5, SEEK_SET);
fi->readx(&buf[0], 5);
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
{
throwCantUnpack(".text corrupted");
}
@ -614,7 +615,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
fi->seek(p_note1->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note1->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, p_note1->sh_size - sizeof(ph.u_len));
@ -630,13 +631,13 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
void PackVmlinuxARM::pack(OutputFile *fo)
{
unsigned fo_off = 0;
Elf32_Ehdr ehdro;
LE32 tmp_le32;
Ehdr ehdro;
U32 tmp_u32;
// NULL
// .text(PT_LOADs) .note(1st page) .note(rest)
// .shstrtab .symtab .strtab
Elf32_Shdr shdro[1+3+3];
Shdr shdro[1+3+3];
memset(shdro, 0, sizeof(shdro));
ibuf.alloc(file_size);
@ -644,7 +645,7 @@ void PackVmlinuxARM::pack(OutputFile *fo)
// .e_ident, .e_machine, .e_version, .e_flags
memcpy(&ehdro, &ehdri, sizeof(ehdro));
ehdro.e_type = Elf32_Ehdr::ET_REL;
ehdro.e_type = Ehdr::ET_REL;
ehdro.e_entry = 0;
ehdro.e_phoff = 0;
ehdro.e_shoff = sizeof(ehdro); // later
@ -695,8 +696,8 @@ void PackVmlinuxARM::pack(OutputFile *fo)
char const *p = shstrtab;
while (0!=*p++) ;
shdro[1].sh_name = ptr_diff(p, shstrtab);
shdro[1].sh_type = Elf32_Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Elf32_Shdr::SHF_ALLOC | Elf32_Shdr::SHF_EXECINSTR;
shdro[1].sh_type = Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
shdro[1].sh_offset = fo_off;
shdro[1].sh_size = sizeof(stub_arm_linux_kernel_vmlinux_head) +
txt_c_len + (3& -txt_c_len) + lsize;
@ -706,14 +707,14 @@ void PackVmlinuxARM::pack(OutputFile *fo)
fo->write(&stub_arm_linux_kernel_vmlinux_head[0], 4);
// Second word
tmp_le32 = (0xff000000 & get_le32(&stub_arm_linux_kernel_vmlinux_head[4]))
tmp_u32 = (0xff000000 & BeLePolicy::get32(&stub_arm_linux_kernel_vmlinux_head[4]))
| (0x00ffffff & (-1+ ((3+ txt_c_len)>>2)));
fo->write(&tmp_le32, 4);
fo->write(&tmp_u32, 4);
fo_off += sizeof(stub_arm_linux_kernel_vmlinux_head);
fo->write(obuf, txt_c_len); fo_off += txt_c_len;
tmp_le32 = 0; fo->write(&tmp_le32, 3& -txt_c_len); fo_off += 3& -txt_c_len;
tmp_u32 = 0; fo->write(&tmp_u32, 3& -txt_c_len); fo_off += 3& -txt_c_len;
fo->write(loader, lsize); fo_off += lsize;
#if 0
@ -730,11 +731,11 @@ void PackVmlinuxARM::pack(OutputFile *fo)
while (0!=*p++) ;
shdro[2].sh_name = ptr_diff(p, shstrtab);
shdro[2].sh_type = Elf32_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 --------------------------------
@ -756,16 +757,16 @@ void PackVmlinuxARM::pack(OutputFile *fo)
// while (0!=*p++) ; // name is the same
shdro[3].sh_name = ptr_diff(p, shstrtab);
shdro[3].sh_type = Elf32_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 = Elf32_Shdr::SHT_STRTAB;
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;
@ -774,24 +775,24 @@ void PackVmlinuxARM::pack(OutputFile *fo)
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 = Elf32_Shdr::SHT_SYMTAB;
shdro[5].sh_type = Shdr::SHT_SYMTAB;
shdro[5].sh_offset = fo_off;
shdro[5].sh_size = 5*sizeof(Elf_LE32_Sym);
//shdro[5].sh_flags = Elf32_Shdr::SHF_INFO_LINK;
shdro[5].sh_size = 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(Elf_LE32_Sym);
shdro[5].sh_entsize = sizeof(Sym);
Elf_LE32_Sym sec_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.St_info(Elf32_Sym::STB_LOCAL, Elf32_Sym::STT_SECTION);
sec_sym.st_other = Elf32_Sym::STV_DEFAULT;
sec_sym.st_info = sec_sym.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
@ -800,12 +801,12 @@ void PackVmlinuxARM::pack(OutputFile *fo)
fo->write(&sec_sym, sizeof(sec_sym)); fo_off += sizeof(sec_sym);
// the symbol we care about
Elf_LE32_Sym unc_ker;
Sym unc_ker;
unc_ker.st_name = 1; // 1 byte into strtab
unc_ker.st_value = 0;
unc_ker.st_size = txt_c_len;
unc_ker.st_info = unc_ker.St_info(Elf32_Sym::STB_GLOBAL, Elf32_Sym::STT_FUNC);
unc_ker.st_other = Elf32_Sym::STV_DEFAULT;
unc_ker.st_info = unc_ker.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);
@ -814,7 +815,7 @@ void PackVmlinuxARM::pack(OutputFile *fo)
while (0!=*p++) ;
shdro[6].sh_name = ptr_diff(p, shstrtab);
shdro[6].sh_type = Elf32_Shdr::SHT_STRTAB;
shdro[6].sh_type = Shdr::SHT_STRTAB;
shdro[6].sh_offset = fo_off;
shdro[6].sh_size = sizeof(strtab); // includes both '\0'
shdro[6].sh_addralign = 1;
@ -842,16 +843,16 @@ int PackVmlinuxARM::canUnpack()
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46\x01\x01\x01", 7) // ELF 32-bit LSB
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|| ehdri.e_machine != Elf32_Ehdr::EM_ARM
|| ehdri.e_machine != Ehdr::EM_ARM
|| ehdri.e_version != 1 // version
|| ehdri.e_type != Elf32_Ehdr::ET_REL
|| ehdri.e_type != Ehdr::ET_REL
|| ehdri.e_shnum < 4
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Elf32_Shdr) + ehdri.e_shoff)
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff)
)
return false;
// find the .shstrtab section
Elf_LE32_Shdr const *const shstrsec = getElfSections();
Shdr const *const shstrsec = getElfSections();
if (0==shstrsec) {
return false;
}
@ -859,7 +860,7 @@ int PackVmlinuxARM::canUnpack()
// check for .text .note .note and sane (.sh_size + .sh_offset)
p_note0 = p_note1 = p_text = 0;
int j;
Elf_LE32_Shdr *p;
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) ) {
@ -898,7 +899,7 @@ void PackVmlinuxARM::unpack(OutputFile *fo)
fi->seek(p_note0->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note0->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, ph.c_len);
@ -911,7 +912,7 @@ void PackVmlinuxARM::unpack(OutputFile *fo)
ph = ph_tmp;
fi->seek(p_text->sh_offset + sizeof(stub_arm_linux_kernel_vmlinux_head) -5, SEEK_SET);
fi->readx(&buf[0], 5);
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
{
throwCantUnpack(".text corrupted");
}
@ -930,7 +931,7 @@ void PackVmlinuxARM::unpack(OutputFile *fo)
fi->seek(p_note1->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note1->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, p_note1->sh_size - sizeof(ph.u_len));
@ -1149,6 +1150,7 @@ void PackVmlinuxARM::unpack(OutputFile *fo)
///* Fall into .text of upx-compressed vmlinux. */
//-----
/*************************************************************************
//
**************************************************************************/
@ -1205,13 +1207,13 @@ void PackVmlinuxAMD64::buildLoader(const Filter *ft)
void PackVmlinuxAMD64::pack(OutputFile *fo)
{
unsigned fo_off = 0;
Elf64_Ehdr ehdro;
LE64 tmp_le32;
Ehdr ehdro;
U32 tmp_u32; // for external representation
// NULL
// .text(PT_LOADs) .note(1st page) .note(rest)
// .shstrtab /* .symtab .strtab */
Elf64_Shdr shdro[1+3+1/*+2*/];
Shdr shdro[1+3+1/*+2*/];
memset(shdro, 0, sizeof(shdro));
char const shstrtab[]= "\0.text\0.note\0.shstrtab\0.symtab\0.strtab";
char const *p = shstrtab;
@ -1221,7 +1223,7 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
// .e_ident, .e_machine, .e_version, .e_flags
memcpy(&ehdro, &ehdri, sizeof(ehdro));
ehdro.e_type = Elf64_Ehdr::ET_REL;
ehdro.e_type = Ehdr::ET_REL;
ehdro.e_entry = 0;
ehdro.e_phoff = 0;
ehdro.e_shoff = 0; // later
@ -1262,19 +1264,19 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
while (0!=*p++) ;
shdro[1].sh_name = ptr_diff(p, shstrtab);
shdro[1].sh_type = Elf64_Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Elf64_Shdr::SHF_ALLOC | Elf64_Shdr::SHF_EXECINSTR;
shdro[1].sh_type = Shdr::SHT_PROGBITS;
shdro[1].sh_flags = Shdr::SHF_ALLOC | Shdr::SHF_EXECINSTR;
shdro[1].sh_offset = fo_off;
shdro[1].sh_size = sizeof(stub_amd64_linux_kernel_vmlinux_head) + ph.c_len + lsize;
shdro[1].sh_addralign = 1;
// ENTRY_POINT
fo->write(&stub_amd64_linux_kernel_vmlinux_head[0], sizeof(stub_amd64_linux_kernel_vmlinux_head)-2*(1+ 4) +1);
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
tmp_u32 = ehdri.e_entry; fo->write(&tmp_u32, 4);
// COMPRESSED_LENGTH
fo->write(&stub_amd64_linux_kernel_vmlinux_head[sizeof(stub_amd64_linux_kernel_vmlinux_head)-(1+ 4)], 1);
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4);
tmp_u32 = ph.c_len; fo->write(&tmp_u32, 4);
fo_off += sizeof(stub_amd64_linux_kernel_vmlinux_head);
@ -1295,11 +1297,11 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
while (0!=*p++) ;
shdro[2].sh_name = ptr_diff(p, shstrtab);
shdro[2].sh_type = Elf64_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 --------------------------------
@ -1321,16 +1323,16 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
// while (0!=*p++) ; // name is the same
shdro[3].sh_name = ptr_diff(p, shstrtab);
shdro[3].sh_type = Elf64_Shdr::SHT_NOTE;
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_le32 = ph.u_len; fo->write(&tmp_le32, 4);
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 = Elf64_Shdr::SHT_STRTAB;
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;
@ -1340,18 +1342,18 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
while (0!=*p++) ;
fo_off = ~3 & (3+ fo_off);
shdro[5].sh_name = ptr_diff(p, shstrtab);
shdro[5].sh_type = Elf64_Shdr::SHT_SYMTAB;
shdro[5].sh_type = Shdr::SHT_SYMTAB;
shdro[5].sh_offset = fo_off;
shdro[5].sh_size = 16; // XXX ?
shdro[5].sh_link = 6; // to .strtab for symbols
shdro[5].sh_addralign = 4;
shdro[5].sh_entsize = 16; // XXX Elf64_Sym
shdro[5].sh_entsize = 16; // XXX Sym
fo->seek(fo_off, SEEK_SET);
fo->write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); fo_off += 16;
while (0!=*p++) ;
shdro[6].sh_name = ptr_diff(p, shstrtab);
shdro[6].sh_type = Elf64_Shdr::SHT_STRTAB;
shdro[6].sh_type = Shdr::SHT_STRTAB;
shdro[6].sh_offset = fo_off;
shdro[6].sh_size = 1; // XXX ?
shdro[6].sh_addralign = 1;
@ -1383,16 +1385,16 @@ int PackVmlinuxAMD64::canUnpack()
// now check the ELF header
if (memcmp(&ehdri, "\x7f\x45\x4c\x46\x01\x01\x01", 7) // ELF 32-bit LSB
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|| ehdri.e_machine != Elf64_Ehdr::EM_X86_64
|| ehdri.e_machine != Ehdr::EM_X86_64
|| ehdri.e_version != 1 // version
|| ehdri.e_type != Elf64_Ehdr::ET_REL
|| ehdri.e_type != Ehdr::ET_REL
|| ehdri.e_shnum < 4
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Elf64_Shdr) + ehdri.e_shoff)
|| (unsigned)file_size < (ehdri.e_shnum * sizeof(Shdr) + ehdri.e_shoff)
)
return false;
// find the .shstrtab section
Elf_LE64_Shdr const *const shstrsec = getElfSections();
Shdr const *const shstrsec = getElfSections();
if (0==shstrsec) {
return false;
}
@ -1400,7 +1402,7 @@ int PackVmlinuxAMD64::canUnpack()
// check for .text .note .note and sane (.sh_size + .sh_offset)
p_note0 = p_note1 = p_text = 0;
int j;
Elf_LE64_Shdr *p;
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) ) {
@ -1439,7 +1441,7 @@ void PackVmlinuxAMD64::unpack(OutputFile *fo)
fi->seek(p_note0->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note0->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, ph.c_len);
@ -1452,7 +1454,7 @@ void PackVmlinuxAMD64::unpack(OutputFile *fo)
ph = ph_tmp;
fi->seek(p_text->sh_offset + sizeof(stub_amd64_linux_kernel_vmlinux_head) -5, SEEK_SET);
fi->readx(&buf[0], 5);
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
{
throwCantUnpack(".text corrupted");
}
@ -1471,7 +1473,7 @@ void PackVmlinuxAMD64::unpack(OutputFile *fo)
fi->seek(p_note1->sh_offset, SEEK_SET);
fi->readx(&buf[0], 4);
ph.u_len = get_le32(buf);
ph.u_len = BeLePolicy::get32(buf);
ph.c_len = p_note1->sh_size - 4;
ibuf.alloc(ph.c_len);
fi->readx(ibuf, p_note1->sh_size - sizeof(ph.u_len));
@ -1483,8 +1485,9 @@ void PackVmlinuxAMD64::unpack(OutputFile *fo)
ph = ph_tmp;
}
/*
vi:ts=4:et
*/

View File

@ -41,6 +41,7 @@ class PackVmlinuxBase : public Packer
{
typedef Packer super;
protected:
typedef typename TElfClass::BeLePolicy BeLePolicy;
// integral types
typedef typename TElfClass::U16 U16;
typedef typename TElfClass::U32 U32;
@ -115,7 +116,7 @@ class PackVmlinuxARM : public PackVmlinuxBase<ElfClass_LE32>
{
typedef PackVmlinuxBase<ElfClass_LE32> super;
public:
PackVmlinuxARM(InputFile *f) : super(f, Elf32_Ehdr::EM_ARM,
PackVmlinuxARM(InputFile *f) : super(f, Elf32_Ehdr::EM_ARM,
Elf32_Ehdr::ELFCLASS32, Elf32_Ehdr::ELFDATA2LSB) { }
virtual int getFormat() const { return UPX_F_VMLINUX_ARM; }
virtual const char *getName() const { return "vmlinux/ARM"; }