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

Portability: fix "EOFException: premature end of file" doing ELF on Windows.

OutputFile::read() was bad news; fsync() should work, but was missing.
This commit is contained in:
John Reiser 2012-07-12 14:25:28 -07:00
parent f383629282
commit 8a5d352733
10 changed files with 79 additions and 67 deletions

View File

@ -410,21 +410,16 @@ void OutputFile::seek(off_t off, int whence)
super::seek(off,whence);
}
int OutputFile::read(void *buf, int len)
{
InputFile infile;
infile.open(this->getName(), O_RDONLY);
infile.seek(this->tell(), SEEK_SET);
return infile.read(buf, len);
}
int OutputFile::readx(void *buf, int len)
{
InputFile infile;
infile.open(this->getName(), O_RDONLY);
infile.seek(this->tell(), SEEK_SET);
return infile.readx(buf, len);
}
// WARNING: fsync() does not exist in some Windows environments.
// This trick works only on UNIX-like systems.
//int OutputFile::read(void *buf, int len)
//{
// fsync(_fd);
// InputFile infile;
// infile.open(this->getName(), O_RDONLY);
// infile.seek(this->tell(), SEEK_SET);
// return infile.read(buf, len);
//}
void OutputFile::set_extent(off_t offset, off_t length)
{

View File

@ -141,8 +141,6 @@ public:
// FIXME - these won't work when using the '--stdout' option
virtual void seek(off_t off, int whence);
virtual void rewrite(const void *buf, int len);
virtual int read(void *buf, int len);
virtual int readx(void *buf, int len);
// util
static void dump(const char *name, const void *buf, int len, int flags=-1);

View File

@ -196,17 +196,6 @@ PackLinuxElf::~PackLinuxElf()
delete[] file_image; file_image = NULL;
}
// Swap the byte ranges fo[a to b] and fo[b to c].
static void swap_byte_ranges(OutputFile *fo, unsigned a, unsigned b, unsigned c)
{
MemBuffer buf(c - a);
fo->seek(a, SEEK_SET);
fo->readx(buf, c - a);
fo->seek(a, SEEK_SET);
fo->rewrite(&buf[b - a], c - b);
fo->rewrite(&buf[0], b - a);
}
void PackLinuxElf::pack3(OutputFile *fo, Filter &ft)
{
sz_pack2b = fpad4(fo); // after headers, all PT_LOAD, gaps
@ -245,16 +234,28 @@ void PackLinuxElf::pack3(OutputFile *fo, Filter &ft)
get_te16(&linfo.l_lsize) + len - sz_pack2a));
len = fpad4(fo);
// Put the loader in the middle, after the compressed PT_LOADs
// and before the compressed gaps (and debuginfo!)
// As first written, loader is fo[sz_pack2b to len],
// and gaps and debuginfo are fo[sz_pack2a to sz_pack2b].
swap_byte_ranges(fo, sz_pack2a, sz_pack2b, len);
}
void PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
{
super::pack3(fo, ft);
super::pack3(fo, ft); // loader follows compressed PT_LOADs
// Then compressed gaps (including debuginfo.)
unsigned total_in = 0, total_out = 0;
for (unsigned k = 0; k < e_phnum; ++k) {
Extent x;
x.size = find_LOAD_gap(phdri, k, e_phnum);
if (x.size) {
x.offset = get_te32(&phdri[k].p_offset) +
get_te32(&phdri[k].p_filesz);
packExtent(x, total_in, total_out, 0, fo);
}
}
// write block end marker (uncompressed size 0)
b_info hdr; memset(&hdr, 0, sizeof(hdr));
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
fo->write(&hdr, sizeof(hdr));
fpad4(fo);
set_te32(&elfout.phdr[0].p_filesz, sz_pack2 + lsize);
set_te32(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
if (0!=xct_off) { // shared library
@ -331,7 +332,24 @@ void PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
void PackLinuxElf64::pack3(OutputFile *fo, Filter &ft)
{
super::pack3(fo, ft);
super::pack3(fo, ft); // loader follows compressed PT_LOADs
// Then compressed gaps (including debuginfo.)
unsigned total_in = 0, total_out = 0;
for (unsigned k = 0; k < e_phnum; ++k) {
Extent x;
x.size = find_LOAD_gap(phdri, k, e_phnum);
if (x.size) {
x.offset = get_te64(&phdri[k].p_offset) +
get_te64(&phdri[k].p_filesz);
packExtent(x, total_in, total_out, 0, fo);
}
}
// write block end marker (uncompressed size 0)
b_info hdr; memset(&hdr, 0, sizeof(hdr));
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
fo->write(&hdr, sizeof(hdr));
fpad4(fo);
set_te64(&elfout.phdr[0].p_filesz, sz_pack2 + lsize);
set_te64(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
if (0!=xct_off) { // shared library
@ -2298,7 +2316,7 @@ unsigned PackLinuxElf32::find_LOAD_gap(
return lo - hi;
}
void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
{
Extent x;
unsigned k;
@ -2356,17 +2374,15 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
}
sz_pack2a = fpad4(fo);
// Accounting only; ::pack3 will do the compression and output
for (k = 0; k < e_phnum; ++k) {
x.size = find_LOAD_gap(phdri, k, e_phnum);
if (x.size) {
x.offset = get_te32(&phdri[k].p_offset) +
get_te32(&phdri[k].p_filesz);
packExtent(x, total_in, total_out, 0, fo);
}
total_in += find_LOAD_gap(phdri, k, e_phnum);
}
if ((off_t)total_in != file_size)
throwEOFException();
return 0; // omit end-of-compression bhdr for now
}
// Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD
@ -2409,7 +2425,7 @@ unsigned PackLinuxElf64::find_LOAD_gap(
return lo - hi;
}
void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
{
Extent x;
unsigned k;
@ -2467,17 +2483,15 @@ void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
}
sz_pack2a = fpad4(fo);
for (k = 0; k < e_phnum; ++k) {
x.size = find_LOAD_gap(phdri, k, e_phnum);
if (x.size) {
x.offset = get_te64(&phdri[k].p_offset) +
get_te64(&phdri[k].p_filesz);
packExtent(x, total_in, total_out, 0, fo);
}
// Accounting only; ::pack3 will do the compression and output
for (k = 0; k < e_phnum; ++k) { //
total_in += find_LOAD_gap(phdri, k, e_phnum);
}
if ((off_t)total_in != file_size)
throwEOFException();
return 0; // omit end-of-compression bhdr for now
}
// Filter 0x50, 0x51 assume HostPolicy::isLE

View File

@ -50,7 +50,7 @@ protected:
// because they depend on Elf32 or Elf64 data structures, which differ.
virtual void pack1(OutputFile *, Filter &) = 0; // generate executable header
virtual void pack2(OutputFile *, Filter &) = 0; // append compressed data
virtual int pack2(OutputFile *, Filter &) = 0; // append compressed data
virtual void pack3(OutputFile *, Filter &) = 0; // append loader
//virtual void pack4(OutputFile *, Filter &) = 0; // append pack header
@ -111,7 +111,7 @@ protected:
virtual int ARM_is_QNX(void);
virtual void pack1(OutputFile *, Filter &); // generate executable header
virtual void pack2(OutputFile *, Filter &); // append compressed data
virtual int pack2(OutputFile *, Filter &); // append compressed data
virtual void pack3(OutputFile *, Filter &); // append loader
virtual void pack4(OutputFile *, Filter &); // append pack header
virtual void unpack(OutputFile *fo);
@ -228,7 +228,7 @@ protected:
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
virtual void pack1(OutputFile *, Filter &); // generate executable header
virtual void pack2(OutputFile *, Filter &); // append compressed data
virtual int pack2(OutputFile *, Filter &); // append compressed data
virtual void pack3(OutputFile *, Filter &); // append loader
virtual void pack4(OutputFile *, Filter &); // append pack header
virtual void unpack(OutputFile *fo);

View File

@ -124,12 +124,12 @@ void PackLinuxElf32x86interp::pack1(OutputFile *fo, Filter &)
#undef E
}
void PackLinuxElf32x86interp::pack2(OutputFile *fo, Filter &ft)
int PackLinuxElf32x86interp::pack2(OutputFile *fo, Filter &ft)
{
if (opt->o_unix.make_ptinterp) {
return; // ignore current input file!
return 1; // ignore current input file!
}
super::pack2(fo, ft);
return super::pack2(fo, ft);
}
#undef PAGE_MASK

View File

@ -54,7 +54,7 @@ public:
protected:
virtual void pack1(OutputFile *, Filter &); // generate executable header
virtual void pack2(OutputFile *, Filter &); // append compressed data
virtual int pack2(OutputFile *, Filter &); // append compressed data
virtual void pack3(OutputFile *, Filter &); // build loader
};

View File

@ -899,7 +899,7 @@ void PackMachBase<T>::pack3(OutputFile *fo, Filter &ft)
}
template <class T>
void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed body
int PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed body
{
unsigned const lc_seg = lc_segment[sizeof(Addr)>>3];
Extent x;
@ -977,6 +977,8 @@ void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed bo
if ((off_t)total_in != file_size)
throwEOFException();
segcmdo.filesize = fo->getBytesWritten();
return 1;
}
void PackMachPPC32::pack1_setup_threado(OutputFile *const fo)

View File

@ -532,7 +532,7 @@ public:
// called by the generic pack()
virtual void pack1(OutputFile *, Filter &); // generate executable header
virtual void pack2(OutputFile *, Filter &); // append compressed data
virtual int pack2(OutputFile *, Filter &); // append compressed data
virtual void pack3(OutputFile *, Filter &) = 0; // append loader
virtual void pack4(OutputFile *, Filter &) = 0; // append PackHeader

View File

@ -130,7 +130,7 @@ int PackUnix::getStrategy(Filter &/*ft*/)
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
}
void PackUnix::pack2(OutputFile *fo, Filter &ft)
int PackUnix::pack2(OutputFile *fo, Filter &ft)
{
// compress blocks
unsigned total_in = 0;
@ -224,6 +224,8 @@ void PackUnix::pack2(OutputFile *fo, Filter &ft)
if ((off_t)total_in != file_size) {
throwEOFException();
}
return 1; // default: write end-of-compression bhdr next
}
void
@ -285,12 +287,13 @@ void PackUnix::pack(OutputFile *fo)
set_te32(&hbuf.p_blocksize, blocksize);
fo->write(&hbuf, sizeof(hbuf));
pack2(fo, ft); // append the compressed body
// write block end marker (uncompressed size 0)
b_info hdr; memset(&hdr, 0, sizeof(hdr));
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
fo->write(&hdr, sizeof(hdr));
// append the compressed body
if (pack2(fo, ft)) {
// write block end marker (uncompressed size 0)
b_info hdr; memset(&hdr, 0, sizeof(hdr));
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
fo->write(&hdr, sizeof(hdr));
}
pack3(fo, ft); // append loader

View File

@ -54,7 +54,7 @@ public:
protected:
// called by the generic pack()
virtual void pack1(OutputFile *, Filter &); // generate executable header
virtual void pack2(OutputFile *, Filter &); // append compressed data
virtual int pack2(OutputFile *, Filter &); // append compressed data
virtual void pack3(OutputFile *, Filter &); // append loader
virtual void pack4(OutputFile *, Filter &); // append PackHeader