vmlinux/386 check for __ksymtab; fix unpack
This commit is contained in:
parent
2b122562ad
commit
452a953234
103
src/p_vmlinx.cpp
103
src/p_vmlinx.cpp
@ -46,12 +46,13 @@ static const
|
||||
**************************************************************************/
|
||||
|
||||
PackVmlinuxI386::PackVmlinuxI386(InputFile *f) :
|
||||
super(f), n_ptload(0), phdri(NULL), shdri(NULL)
|
||||
super(f), n_ptload(0), phdri(NULL), shdri(NULL), shstrtab(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PackVmlinuxI386::~PackVmlinuxI386()
|
||||
{
|
||||
delete [] shstrtab;
|
||||
delete [] phdri;
|
||||
delete [] shdri;
|
||||
}
|
||||
@ -81,6 +82,34 @@ int PackVmlinuxI386::getStrategy(Filter &/*ft*/)
|
||||
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
||||
}
|
||||
|
||||
|
||||
Elf_LE32_Shdr const *
|
||||
PackVmlinuxI386::getElfSections()
|
||||
{
|
||||
Elf_LE32_Shdr const *p, *shstrsec=0;
|
||||
shdri = new Elf_LE32_Shdr[(unsigned) ehdri.e_shnum];
|
||||
fi->seek(ehdri.e_shoff, SEEK_SET);
|
||||
fi->readx(shdri, ehdri.e_shnum * sizeof(*shdri));
|
||||
int j;
|
||||
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||
if (Elf32_Shdr::SHT_STRTAB==p->sh_type
|
||||
&& (p->sh_size + p->sh_offset) <= (unsigned) file_size
|
||||
&& (10+ p->sh_name) <= p->sh_size // 1+ strlen(".shstrtab")
|
||||
) {
|
||||
delete [] shstrtab;
|
||||
shstrtab = new char[1+ p->sh_size];
|
||||
fi->seek(p->sh_offset, SEEK_SET);
|
||||
fi->readx(shstrtab, p->sh_size);
|
||||
shstrtab[p->sh_size] = '\0';
|
||||
if (0==strcmp(".shstrtab", shstrtab + p->sh_name)) {
|
||||
shstrsec = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return shstrsec;
|
||||
}
|
||||
|
||||
static int __acc_cdecl_qsort
|
||||
compare_Phdr(void const *aa, void const *bb)
|
||||
{
|
||||
@ -143,6 +172,22 @@ bool PackVmlinuxI386::canPack()
|
||||
return false;
|
||||
}
|
||||
|
||||
// A Linux kernel must have a __ksymtab section. [??]
|
||||
Elf_LE32_Shdr const *p, *const shstrsec = getElfSections();
|
||||
if (0==shstrsec) {
|
||||
return false;
|
||||
}
|
||||
int j;
|
||||
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||
if (Elf32_Shdr::SHT_PROGBITS==p->sh_type
|
||||
&& 0==strcmp("__ksymtab", p->sh_name + shstrtab)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
phdri = new Elf_LE32_Phdr[(unsigned) ehdri.e_phnum];
|
||||
fi->seek(ehdri.e_phoff, SEEK_SET);
|
||||
fi->readx(phdri, ehdri.e_phnum * sizeof(*phdri));
|
||||
@ -220,6 +265,8 @@ static bool defineFilterSymbols(Linker *linker, const Filter *ft)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const
|
||||
#include "stub/i386-linux.kernel.head-vmlinux.h"
|
||||
|
||||
void PackVmlinuxI386::pack(OutputFile *fo)
|
||||
{
|
||||
@ -284,26 +331,21 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
||||
shdro[1].sh_type = Elf32_Shdr::SHT_PROGBITS;
|
||||
shdro[1].sh_flags = Elf32_Shdr::SHF_ALLOC | Elf32_Shdr::SHF_EXECINSTR;
|
||||
shdro[1].sh_offset = fo_off;
|
||||
shdro[1].sh_size = 1+ 4+ ph.c_len + lsize;
|
||||
shdro[1].sh_size = sizeof(head_stack) + ph.c_len + lsize;
|
||||
shdro[1].sh_addralign = 1;
|
||||
|
||||
{
|
||||
static const
|
||||
#include "stub/i386-linux.kernel.head-vmlinux.h"
|
||||
// ENTRY_POINT
|
||||
fo->write(&head_stack[0], sizeof(head_stack)-2*(1+ 4) +1);
|
||||
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
|
||||
|
||||
// ENTRY_POINT
|
||||
fo->write(&head_stack[0], sizeof(head_stack)-2*(1+ 4) +1);
|
||||
tmp_le32 = ehdri.e_entry; fo->write(&tmp_le32, 4);
|
||||
// COMPRESSED_LENGTH
|
||||
fo->write(&head_stack[sizeof(head_stack)-(1+ 4)], 1);
|
||||
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4);
|
||||
|
||||
// COMPRESSED_LENGTH
|
||||
fo->write(&head_stack[sizeof(head_stack)-(1+ 4)], 1);
|
||||
tmp_le32 = ph.c_len; fo->write(&tmp_le32, 4);
|
||||
fo_off += sizeof(head_stack);
|
||||
|
||||
fo_off += sizeof(head_stack);
|
||||
|
||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
}
|
||||
fo->write(obuf, ph.c_len); fo_off += ph.c_len;
|
||||
fo->write(loader, lsize); fo_off += lsize;
|
||||
|
||||
#if 0
|
||||
printf("%-13s: compressed : %8u bytes\n", getName(), ph.c_len);
|
||||
@ -416,35 +458,18 @@ int PackVmlinuxI386::canUnpack()
|
||||
return false;
|
||||
|
||||
// find the .shstrtab section
|
||||
char shstrtab[40];
|
||||
Elf_LE32_Shdr *p, *p_shstrtab=0;
|
||||
shdri = new Elf_LE32_Shdr[(unsigned) ehdri.e_shnum];
|
||||
fi->seek(ehdri.e_shoff, SEEK_SET);
|
||||
fi->readx(shdri, ehdri.e_shnum * sizeof(*shdri));
|
||||
int j;
|
||||
for (p = shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||
if (Elf32_Shdr::SHT_STRTAB==p->sh_type
|
||||
&& p->sh_size <= sizeof(shstrtab)
|
||||
&& (p->sh_size + p->sh_offset) <= (unsigned) file_size
|
||||
&& (10+ p->sh_name) <= p->sh_size // 1+ strlen(".shstrtab")
|
||||
) {
|
||||
fi->seek(p->sh_offset, SEEK_SET);
|
||||
fi->readx(shstrtab, p->sh_size);
|
||||
if (0==strcmp(".shstrtab", shstrtab + p->sh_name)) {
|
||||
p_shstrtab = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0==p_shstrtab) {
|
||||
Elf_LE32_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;
|
||||
Elf_LE32_Shdr *p;
|
||||
for (p= shdri, j= ehdri.e_shnum; --j>=0; ++p) {
|
||||
if ((unsigned)file_size < (p->sh_size + p->sh_offset)
|
||||
|| p_shstrtab->sh_size < (5+ p->sh_name) ) {
|
||||
|| shstrsec->sh_size < (5+ p->sh_name) ) {
|
||||
continue;
|
||||
}
|
||||
if (0==strcmp(".text", shstrtab + p->sh_name)) {
|
||||
@ -491,7 +516,7 @@ void PackVmlinuxI386::unpack(OutputFile *fo)
|
||||
ibuf.dealloc();
|
||||
|
||||
ph = ph_tmp;
|
||||
fi->seek(p_text->sh_offset, SEEK_SET);
|
||||
fi->seek(p_text->sh_offset + sizeof(head_stack) -5, SEEK_SET);
|
||||
fi->readx(&buf[0], 5);
|
||||
if (0xE8!=buf[0] || get_le32(&buf[1]) != ph.c_len)
|
||||
{
|
||||
|
||||
@ -55,6 +55,7 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual Elf_LE32_Shdr const *getElfSections();
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual Linker* newLinker() const;
|
||||
// virtual const upx_byte *getLoader() const;
|
||||
@ -62,8 +63,9 @@ protected:
|
||||
|
||||
int n_ptload;
|
||||
unsigned sz_ptload;
|
||||
Elf_LE32_Phdr *phdri; // from input file
|
||||
Elf_LE32_Phdr *phdri; // from input file
|
||||
Elf_LE32_Shdr *shdri; // from input file
|
||||
char *shstrtab; // from input file
|
||||
Elf_LE32_Shdr *p_text;
|
||||
Elf_LE32_Shdr *p_note0;
|
||||
Elf_LE32_Shdr *p_note1;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user