refactor PackVmlinuxBase ::canUnpack(), ::unpack()
This commit is contained in:
+144
-331
@@ -134,16 +134,16 @@ bool PackVmlinuxBase<T>::canPack()
|
|||||||
|| ehdri.e_ident[Ehdr::EI_DATA] != my_elfdata
|
|| ehdri.e_ident[Ehdr::EI_DATA] != my_elfdata
|
||||||
|| ehdri.e_ident[Ehdr::EI_VERSION] != Ehdr::EV_CURRENT
|
|| ehdri.e_ident[Ehdr::EI_VERSION] != Ehdr::EV_CURRENT
|
||||||
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|
|| !memcmp(&ehdri.e_ident[8], "FreeBSD", 7) // branded
|
||||||
|
|| ehdri.e_machine != my_e_machine
|
||||||
|| ehdri.e_version != 1 // version
|
|| ehdri.e_version != 1 // version
|
||||||
|| ehdri.e_ehsize != sizeof(ehdri) // different <elf.h> ?
|
|| ehdri.e_ehsize != sizeof(ehdri) // different <elf.h> ?
|
||||||
|| ehdri.e_phoff != sizeof(ehdri) // Phdrs not contiguous with Ehdr
|
|
||||||
|| ehdri.e_phentsize!=sizeof(Phdr)
|
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// additional requirements for vmlinux
|
// additional requirements for vmlinux
|
||||||
if (ehdri.e_machine != my_e_machine
|
if (ehdri.e_type != Ehdr::ET_EXEC
|
||||||
|| ehdri.e_type != Ehdr::ET_EXEC
|
|| ehdri.e_phoff != sizeof(ehdri) // Phdr not contiguous with Ehdr
|
||||||
|
|| ehdri.e_phentsize!=sizeof(Phdr)
|
||||||
|| !is_valid_e_entry(ehdri.e_entry)
|
|| !is_valid_e_entry(ehdri.e_entry)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
@@ -194,6 +194,122 @@ bool PackVmlinuxBase<T>::canPack()
|
|||||||
return 0 < n_ptload;
|
return 0 < n_ptload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|| 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 = BeLePolicy::get32(&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);
|
||||||
|
obuf.allocForUncompression(ph.u_len);
|
||||||
|
decompress(ibuf, obuf);
|
||||||
|
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.init(ph.filter, 0);
|
||||||
|
ft.cto = (unsigned char) ph.filter_cto;
|
||||||
|
ft.unfilter(obuf, ph.u_len);
|
||||||
|
fo->write(obuf, ph.u_len);
|
||||||
|
obuf.dealloc();
|
||||||
|
ibuf.dealloc();
|
||||||
|
|
||||||
|
fi->seek(p_note1->sh_offset, SEEK_SET);
|
||||||
|
fi->readx(&word, sizeof(word));
|
||||||
|
ph.u_len = BeLePolicy::get32(&word);
|
||||||
|
ph.c_len = p_note1->sh_size - sizeof(word);
|
||||||
|
ibuf.alloc(ph.c_len);
|
||||||
|
fi->readx(ibuf, p_note1->sh_size - sizeof(ph.u_len));
|
||||||
|
obuf.allocForUncompression(ph.u_len);
|
||||||
|
decompress(ibuf, obuf, false);
|
||||||
|
fo->write(obuf, ph.u_len);
|
||||||
|
obuf.dealloc();
|
||||||
|
ibuf.dealloc();
|
||||||
|
|
||||||
|
ph = ph_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
@@ -519,120 +635,6 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
|||||||
#undef shstrtab
|
#undef shstrtab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// unpack
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int PackVmlinuxI386::canUnpack()
|
|
||||||
{
|
|
||||||
fi->seek(0, SEEK_SET);
|
|
||||||
fi->readx(&ehdri, sizeof(ehdri));
|
|
||||||
|
|
||||||
// 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 != Ehdr::EM_386
|
|
||||||
|| ehdri.e_version != 1 // version
|
|
||||||
|| ehdri.e_type != Ehdr::ET_REL
|
|
||||||
|| 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 false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackVmlinuxI386::unpack(OutputFile *fo)
|
|
||||||
{
|
|
||||||
unsigned char buf[5];
|
|
||||||
PackHeader const ph_tmp(ph);
|
|
||||||
|
|
||||||
fi->seek(p_note0->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 4);
|
|
||||||
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);
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
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] || BeLePolicy::get32(&buf[1]) != ph.c_len)
|
|
||||||
{
|
|
||||||
throwCantUnpack(".text corrupted");
|
|
||||||
}
|
|
||||||
ibuf.alloc(ph.c_len);
|
|
||||||
fi->readx(ibuf, ph.c_len);
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf);
|
|
||||||
|
|
||||||
Filter ft(ph.level);
|
|
||||||
ft.init(ph.filter, 0);
|
|
||||||
ft.cto = (unsigned char) ph.filter_cto;
|
|
||||||
ft.unfilter(obuf, ph.u_len);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
fi->seek(p_note1->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 4);
|
|
||||||
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));
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
ph = ph_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackVmlinuxARM::pack(OutputFile *fo)
|
void PackVmlinuxARM::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
unsigned fo_off = 0;
|
unsigned fo_off = 0;
|
||||||
@@ -836,117 +838,42 @@ void PackVmlinuxARM::pack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
bool PackVmlinuxARM::has_valid_vmlinux_head()
|
||||||
// unpack
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int PackVmlinuxARM::canUnpack()
|
|
||||||
{
|
{
|
||||||
fi->seek(0, SEEK_SET);
|
U32 buf[2];
|
||||||
fi->readx(&ehdri, sizeof(ehdri));
|
fi->seek(p_text->sh_offset + sizeof(stub_arm_linux_kernel_vmlinux_head) -8, SEEK_SET);
|
||||||
|
|
||||||
// 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 != Ehdr::EM_ARM
|
|
||||||
|| ehdri.e_version != 1 // version
|
|
||||||
|| ehdri.e_type != Ehdr::ET_REL
|
|
||||||
|| 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));
|
fi->readx(buf, sizeof(buf));
|
||||||
if (!getPackHeader(buf, sizeof(buf)))
|
//unsigned const word0 = BeLePolicy::get32(&buf[0]);
|
||||||
return false;
|
unsigned const word1 = BeLePolicy::get32(&buf[1]);
|
||||||
|
if (0xeb==(word1>>24)
|
||||||
|
&& (0x00ffffff& word1)==(-1+ ((3+ ph.c_len)>>2))) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PackVmlinuxI386::has_valid_vmlinux_head()
|
||||||
void PackVmlinuxARM::unpack(OutputFile *fo)
|
|
||||||
{
|
{
|
||||||
unsigned char buf[5];
|
unsigned char buf[5];
|
||||||
PackHeader const ph_tmp(ph);
|
fi->seek(p_text->sh_offset + sizeof(stub_i386_linux_kernel_vmlinux_head) -5, SEEK_SET);
|
||||||
|
|
||||||
fi->seek(p_note0->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 4);
|
|
||||||
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);
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
ph = ph_tmp;
|
|
||||||
fi->seek(p_text->sh_offset + sizeof(stub_arm_linux_kernel_vmlinux_head) -5, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 5);
|
fi->readx(&buf[0], 5);
|
||||||
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
|
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
|
||||||
{
|
{
|
||||||
throwCantUnpack(".text corrupted");
|
return false;
|
||||||
}
|
}
|
||||||
ibuf.alloc(ph.c_len);
|
return true;
|
||||||
fi->readx(ibuf, ph.c_len);
|
}
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf);
|
|
||||||
|
|
||||||
Filter ft(ph.level);
|
bool PackVmlinuxAMD64::has_valid_vmlinux_head()
|
||||||
ft.init(ph.filter, 0);
|
{
|
||||||
ft.cto = (unsigned char) ph.filter_cto;
|
unsigned char buf[5];
|
||||||
ft.unfilter(obuf, ph.u_len);
|
fi->seek(p_text->sh_offset + sizeof(stub_amd64_linux_kernel_vmlinux_head) -5, SEEK_SET);
|
||||||
fo->write(obuf, ph.u_len);
|
fi->readx(&buf[0], 5);
|
||||||
obuf.dealloc();
|
if (0xE8!=buf[0] || BeLePolicy::get32(&buf[1]) != ph.c_len)
|
||||||
ibuf.dealloc();
|
{
|
||||||
|
return false;
|
||||||
fi->seek(p_note1->sh_offset, SEEK_SET);
|
}
|
||||||
fi->readx(&buf[0], 4);
|
return true;
|
||||||
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));
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
ph = ph_tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1378,120 +1305,6 @@ void PackVmlinuxAMD64::pack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// unpack
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int PackVmlinuxAMD64::canUnpack()
|
|
||||||
{
|
|
||||||
fi->seek(0, SEEK_SET);
|
|
||||||
fi->readx(&ehdri, sizeof(ehdri));
|
|
||||||
|
|
||||||
// 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 != Ehdr::EM_X86_64
|
|
||||||
|| ehdri.e_version != 1 // version
|
|
||||||
|| ehdri.e_type != Ehdr::ET_REL
|
|
||||||
|| 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 false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackVmlinuxAMD64::unpack(OutputFile *fo)
|
|
||||||
{
|
|
||||||
unsigned char buf[5];
|
|
||||||
PackHeader const ph_tmp(ph);
|
|
||||||
|
|
||||||
fi->seek(p_note0->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 4);
|
|
||||||
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);
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
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] || BeLePolicy::get32(&buf[1]) != ph.c_len)
|
|
||||||
{
|
|
||||||
throwCantUnpack(".text corrupted");
|
|
||||||
}
|
|
||||||
ibuf.alloc(ph.c_len);
|
|
||||||
fi->readx(ibuf, ph.c_len);
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf);
|
|
||||||
|
|
||||||
Filter ft(ph.level);
|
|
||||||
ft.init(ph.filter, 0);
|
|
||||||
ft.cto = (unsigned char) ph.filter_cto;
|
|
||||||
ft.unfilter(obuf, ph.u_len);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
fi->seek(p_note1->sh_offset, SEEK_SET);
|
|
||||||
fi->readx(&buf[0], 4);
|
|
||||||
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));
|
|
||||||
obuf.allocForUncompression(ph.u_len);
|
|
||||||
decompress(ibuf, obuf, false);
|
|
||||||
fo->write(obuf, ph.u_len);
|
|
||||||
obuf.dealloc();
|
|
||||||
ibuf.dealloc();
|
|
||||||
|
|
||||||
ph = ph_tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// instantiate instances
|
// instantiate instances
|
||||||
template class PackVmlinuxBase<ElfClass_LE32>;
|
template class PackVmlinuxBase<ElfClass_LE32>;
|
||||||
template class PackVmlinuxBase<ElfClass_LE64>;
|
template class PackVmlinuxBase<ElfClass_LE64>;
|
||||||
|
|||||||
+6
-9
@@ -79,7 +79,10 @@ protected:
|
|||||||
virtual Shdr const *getElfSections();
|
virtual Shdr const *getElfSections();
|
||||||
virtual int getStrategy(Filter &/*ft*/);
|
virtual int getStrategy(Filter &/*ft*/);
|
||||||
virtual bool is_valid_e_entry(Addr) = 0;
|
virtual bool is_valid_e_entry(Addr) = 0;
|
||||||
|
virtual bool has_valid_vmlinux_head() = 0;
|
||||||
virtual bool canPack();
|
virtual bool canPack();
|
||||||
|
virtual int canUnpack(); // bool, except -1: format known, but not packed
|
||||||
|
virtual void unpack(OutputFile *fo);
|
||||||
static int __acc_cdecl_qsort compare_Phdr(void const *aa, void const *bb);
|
static int __acc_cdecl_qsort compare_Phdr(void const *aa, void const *bb);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,14 +100,12 @@ public:
|
|||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
virtual void unpack(OutputFile *fo);
|
|
||||||
|
|
||||||
virtual int canUnpack();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const;
|
||||||
virtual bool is_valid_e_entry(Addr);
|
virtual bool is_valid_e_entry(Addr);
|
||||||
|
virtual bool has_valid_vmlinux_head();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -121,14 +122,12 @@ public:
|
|||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
virtual void unpack(OutputFile *fo);
|
|
||||||
|
|
||||||
virtual int canUnpack();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const;
|
||||||
virtual bool is_valid_e_entry(Addr);
|
virtual bool is_valid_e_entry(Addr);
|
||||||
|
virtual bool has_valid_vmlinux_head();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -145,14 +144,12 @@ public:
|
|||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
virtual void unpack(OutputFile *fo);
|
|
||||||
|
|
||||||
virtual int canUnpack();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const;
|
||||||
virtual bool is_valid_e_entry(Addr);
|
virtual bool is_valid_e_entry(Addr);
|
||||||
|
virtual bool has_valid_vmlinux_head();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user