1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00
This commit is contained in:
John Reiser 2010-02-20 20:36:34 -08:00
commit 36de249066
2 changed files with 10 additions and 127 deletions

View File

@ -2078,125 +2078,6 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
fo->rewrite(&linfo, sizeof(linfo));
}
void PackLinuxElf32::unpack(OutputFile *fo)
{
#define MAX_ELF_HDR 512
union {
unsigned char buf[MAX_ELF_HDR];
//struct { Elf32_Ehdr ehdr; Elf32_Phdr phdr; } e;
} u;
Elf32_Ehdr *const ehdr = (Elf32_Ehdr *) u.buf;
Elf32_Phdr const *phdr = (Elf32_Phdr *) (u.buf + sizeof(*ehdr));
unsigned szb_info = sizeof(b_info);
{
fi->seek(0, SEEK_SET);
fi->readx(u.buf, MAX_ELF_HDR);
unsigned const e_entry = get_te32(&ehdr->e_entry);
if (e_entry < 0x401180
&& ehdr->e_machine==Elf32_Ehdr::EM_386) { /* old style, 8-byte b_info */
szb_info = 2*sizeof(unsigned);
}
}
fi->seek(overlay_offset, SEEK_SET);
p_info hbuf;
fi->readx(&hbuf, sizeof(hbuf));
unsigned orig_file_size = get_te32(&hbuf.p_filesize);
blocksize = get_te32(&hbuf.p_blocksize);
if (file_size > (off_t)orig_file_size || blocksize > orig_file_size)
throwCantUnpack("file header corrupted");
ibuf.alloc(blocksize + OVERHEAD);
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
fi->readx(&bhdr, szb_info);
ph.u_len = get_te32(&bhdr.sz_unc);
ph.c_len = get_te32(&bhdr.sz_cpr);
ph.filter_cto = bhdr.b_cto8;
// Uncompress Ehdr and Phdrs.
bool is_shlib = (sizeof(u) < ph.u_len);
if (is_shlib) {
fi->seek(0, SEEK_SET);
fi->readx(ibuf, file_size); // the whole compressed file
// FIXME: re-construct original Ehdr and Phdrs in ibuf
fo->write(ibuf, overlay_offset);
// FIXME: not finished
return;
}
fi->readx(ibuf, ph.c_len);
if (!is_shlib) {
decompress(ibuf, (upx_byte *)ehdr, false);
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
}
unsigned total_in = 0;
unsigned total_out = 0;
unsigned c_adler = upx_adler32(NULL, 0);
unsigned u_adler = upx_adler32(NULL, 0);
// decompress PT_LOAD32
bool first_PF_X = true;
unsigned const u_phnum = get_te16(&ehdr->e_phnum);
for (unsigned j=0; j < u_phnum; ++phdr, ++j) {
if (PT_LOAD32==get_te32(&phdr->p_type)) {
unsigned const filesz = get_te32(&phdr->p_filesz);
unsigned const offset = get_te32(&phdr->p_offset);
if (fo)
fo->seek(offset, SEEK_SET);
if (Elf32_Phdr::PF_X & get_te32(&phdr->p_flags)) {
unpackExtent(filesz, fo, total_in, total_out,
c_adler, u_adler, first_PF_X, szb_info);
first_PF_X = false;
}
else {
unpackExtent(filesz, fo, total_in, total_out,
c_adler, u_adler, false, szb_info);
}
}
}
phdr = (Elf32_Phdr *) (u.buf + sizeof(*ehdr));
for (unsigned j = 0; j < u_phnum; ++j) {
unsigned const size = find_LOAD_gap(phdr, j, u_phnum);
if (size) {
unsigned const where = get_te32(&phdr[j].p_offset) +
get_te32(&phdr[j].p_filesz);
if (fo)
fo->seek(where, SEEK_SET);
unpackExtent(size, fo, total_in, total_out,
c_adler, u_adler, false, szb_info);
}
}
// check for end-of-file
fi->readx(&bhdr, szb_info);
unsigned const sz_unc = ph.u_len = get_te32(&bhdr.sz_unc);
if (sz_unc == 0) { // uncompressed size 0 -> EOF
// note: magic is always stored le32
unsigned const sz_cpr = get_le32(&bhdr.sz_cpr);
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
throwCompressedDataViolation();
}
else { // extra bytes after end?
throwCompressedDataViolation();
}
// update header with totals
ph.c_len = total_in;
ph.u_len = total_out;
// all bytes must be written
if (total_out != orig_file_size)
throwEOFException();
// finally test the checksums
if (ph.c_adler != c_adler || ph.u_adler != u_adler)
throwChecksumError();
#undef MAX_ELF_HDR
}
void PackLinuxElf64::unpack(OutputFile *fo)
{
#define MAX_ELF_HDR 1024
@ -2612,7 +2493,7 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
}
void PackLinuxElf32x86::unpack(OutputFile *fo)
void PackLinuxElf32::unpack(OutputFile *fo)
{
#define MAX_ELF_HDR 512
union {
@ -2629,10 +2510,10 @@ void PackLinuxElf32x86::unpack(OutputFile *fo)
{
fi->seek(0, SEEK_SET);
fi->readx(u.buf, MAX_ELF_HDR);
unsigned const e_entry = get_te32(&ehdr->e_entry);
unsigned const e_type = get_te16(&ehdr->e_type);
if (e_entry < 0x401180 && Elf32_Ehdr::ET_EXEC==e_type) {
// beware ET_DYN.e_entry==0x10f0 or so
if (get_te32(&ehdr->e_entry) < 0x401180
&& Elf32_Ehdr::EM_386 ==get_te16(&ehdr->e_machine)
&& Elf32_Ehdr::ET_EXEC==get_te16(&ehdr->e_type)) {
// Beware ET_DYN.e_entry==0x10f0 (or so) does NOT qualify here.
/* old style, 8-byte b_info */
szb_info = 2*sizeof(unsigned);
}
@ -2811,6 +2692,10 @@ void PackLinuxElf32x86::unpack(OutputFile *fo)
#undef MAX_ELF_HDR
}
void PackLinuxElf::unpack(OutputFile */*fo*/)
{
throwCantUnpack("internal error");
}
/*
vi:ts=4:et

View File

@ -61,7 +61,7 @@ protected:
) = 0;
virtual void defineSymbols(Filter const *);
virtual void addStubEntrySections(Filter const *);
virtual void unpack(OutputFile *fo) = 0;
virtual void unpack(OutputFile *fo);
virtual unsigned elf_get_offset_from_address(unsigned) const = 0;
virtual void const *elf_find_dynamic(unsigned) const = 0;
@ -361,8 +361,6 @@ public:
virtual const char *getFullName(const options_t *) const { return "i386-linux.elf"; }
virtual const int *getFilters() const;
virtual void unpack(OutputFile *fo);
protected:
virtual void pack1(OutputFile *, Filter &); // generate executable header