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:
parent
f383629282
commit
8a5d352733
25
src/file.cpp
25
src/file.cpp
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user