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);
|
super::seek(off,whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
int OutputFile::read(void *buf, int len)
|
// WARNING: fsync() does not exist in some Windows environments.
|
||||||
{
|
// This trick works only on UNIX-like systems.
|
||||||
InputFile infile;
|
//int OutputFile::read(void *buf, int len)
|
||||||
infile.open(this->getName(), O_RDONLY);
|
//{
|
||||||
infile.seek(this->tell(), SEEK_SET);
|
// fsync(_fd);
|
||||||
return infile.read(buf, len);
|
// InputFile infile;
|
||||||
}
|
// infile.open(this->getName(), O_RDONLY);
|
||||||
|
// infile.seek(this->tell(), SEEK_SET);
|
||||||
int OutputFile::readx(void *buf, int len)
|
// return infile.read(buf, len);
|
||||||
{
|
//}
|
||||||
InputFile infile;
|
|
||||||
infile.open(this->getName(), O_RDONLY);
|
|
||||||
infile.seek(this->tell(), SEEK_SET);
|
|
||||||
return infile.readx(buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutputFile::set_extent(off_t offset, off_t length)
|
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
|
// FIXME - these won't work when using the '--stdout' option
|
||||||
virtual void seek(off_t off, int whence);
|
virtual void seek(off_t off, int whence);
|
||||||
virtual void rewrite(const void *buf, int len);
|
virtual void rewrite(const void *buf, int len);
|
||||||
virtual int read(void *buf, int len);
|
|
||||||
virtual int readx(void *buf, int len);
|
|
||||||
|
|
||||||
// util
|
// util
|
||||||
static void dump(const char *name, const void *buf, int len, int flags=-1);
|
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;
|
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)
|
void PackLinuxElf::pack3(OutputFile *fo, Filter &ft)
|
||||||
{
|
{
|
||||||
sz_pack2b = fpad4(fo); // after headers, all PT_LOAD, gaps
|
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));
|
get_te16(&linfo.l_lsize) + len - sz_pack2a));
|
||||||
|
|
||||||
len = fpad4(fo);
|
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)
|
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_filesz, sz_pack2 + lsize);
|
||||||
set_te32(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
|
set_te32(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
|
||||||
if (0!=xct_off) { // shared library
|
if (0!=xct_off) { // shared library
|
||||||
@ -331,7 +332,24 @@ void PackLinuxElf32::pack3(OutputFile *fo, Filter &ft)
|
|||||||
|
|
||||||
void PackLinuxElf64::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_filesz, sz_pack2 + lsize);
|
||||||
set_te64(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
|
set_te64(&elfout.phdr[0].p_memsz, sz_pack2 + lsize);
|
||||||
if (0!=xct_off) { // shared library
|
if (0!=xct_off) { // shared library
|
||||||
@ -2298,7 +2316,7 @@ unsigned PackLinuxElf32::find_LOAD_gap(
|
|||||||
return lo - hi;
|
return lo - hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
||||||
{
|
{
|
||||||
Extent x;
|
Extent x;
|
||||||
unsigned k;
|
unsigned k;
|
||||||
@ -2356,17 +2374,15 @@ void PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
|||||||
}
|
}
|
||||||
sz_pack2a = fpad4(fo);
|
sz_pack2a = fpad4(fo);
|
||||||
|
|
||||||
|
// Accounting only; ::pack3 will do the compression and output
|
||||||
for (k = 0; k < e_phnum; ++k) {
|
for (k = 0; k < e_phnum; ++k) {
|
||||||
x.size = find_LOAD_gap(phdri, k, e_phnum);
|
total_in += 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((off_t)total_in != file_size)
|
if ((off_t)total_in != file_size)
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
|
|
||||||
|
return 0; // omit end-of-compression bhdr for now
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD
|
// 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;
|
return lo - hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
||||||
{
|
{
|
||||||
Extent x;
|
Extent x;
|
||||||
unsigned k;
|
unsigned k;
|
||||||
@ -2467,17 +2483,15 @@ void PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
|||||||
}
|
}
|
||||||
sz_pack2a = fpad4(fo);
|
sz_pack2a = fpad4(fo);
|
||||||
|
|
||||||
for (k = 0; k < e_phnum; ++k) {
|
// Accounting only; ::pack3 will do the compression and output
|
||||||
x.size = find_LOAD_gap(phdri, k, e_phnum);
|
for (k = 0; k < e_phnum; ++k) { //
|
||||||
if (x.size) {
|
total_in += find_LOAD_gap(phdri, k, e_phnum);
|
||||||
x.offset = get_te64(&phdri[k].p_offset) +
|
|
||||||
get_te64(&phdri[k].p_filesz);
|
|
||||||
packExtent(x, total_in, total_out, 0, fo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((off_t)total_in != file_size)
|
if ((off_t)total_in != file_size)
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
|
|
||||||
|
return 0; // omit end-of-compression bhdr for now
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter 0x50, 0x51 assume HostPolicy::isLE
|
// Filter 0x50, 0x51 assume HostPolicy::isLE
|
||||||
|
|||||||
@ -50,7 +50,7 @@ protected:
|
|||||||
// because they depend on Elf32 or Elf64 data structures, which differ.
|
// because they depend on Elf32 or Elf64 data structures, which differ.
|
||||||
|
|
||||||
virtual void pack1(OutputFile *, Filter &) = 0; // generate executable header
|
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 pack3(OutputFile *, Filter &) = 0; // append loader
|
||||||
//virtual void pack4(OutputFile *, Filter &) = 0; // append pack header
|
//virtual void pack4(OutputFile *, Filter &) = 0; // append pack header
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ protected:
|
|||||||
virtual int ARM_is_QNX(void);
|
virtual int ARM_is_QNX(void);
|
||||||
|
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
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 pack3(OutputFile *, Filter &); // append loader
|
||||||
virtual void pack4(OutputFile *, Filter &); // append pack header
|
virtual void pack4(OutputFile *, Filter &); // append pack header
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo);
|
||||||
@ -228,7 +228,7 @@ protected:
|
|||||||
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
|
virtual int checkEhdr(Elf64_Ehdr const *ehdr) const;
|
||||||
|
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
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 pack3(OutputFile *, Filter &); // append loader
|
||||||
virtual void pack4(OutputFile *, Filter &); // append pack header
|
virtual void pack4(OutputFile *, Filter &); // append pack header
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|||||||
@ -124,12 +124,12 @@ void PackLinuxElf32x86interp::pack1(OutputFile *fo, Filter &)
|
|||||||
#undef E
|
#undef E
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackLinuxElf32x86interp::pack2(OutputFile *fo, Filter &ft)
|
int PackLinuxElf32x86interp::pack2(OutputFile *fo, Filter &ft)
|
||||||
{
|
{
|
||||||
if (opt->o_unix.make_ptinterp) {
|
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
|
#undef PAGE_MASK
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
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
|
virtual void pack3(OutputFile *, Filter &); // build loader
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -899,7 +899,7 @@ void PackMachBase<T>::pack3(OutputFile *fo, Filter &ft)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
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];
|
unsigned const lc_seg = lc_segment[sizeof(Addr)>>3];
|
||||||
Extent x;
|
Extent x;
|
||||||
@ -977,6 +977,8 @@ void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed bo
|
|||||||
if ((off_t)total_in != file_size)
|
if ((off_t)total_in != file_size)
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
segcmdo.filesize = fo->getBytesWritten();
|
segcmdo.filesize = fo->getBytesWritten();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackMachPPC32::pack1_setup_threado(OutputFile *const fo)
|
void PackMachPPC32::pack1_setup_threado(OutputFile *const fo)
|
||||||
|
|||||||
@ -532,7 +532,7 @@ public:
|
|||||||
|
|
||||||
// called by the generic pack()
|
// called by the generic pack()
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
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 pack3(OutputFile *, Filter &) = 0; // append loader
|
||||||
virtual void pack4(OutputFile *, Filter &) = 0; // append PackHeader
|
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));
|
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
|
// compress blocks
|
||||||
unsigned total_in = 0;
|
unsigned total_in = 0;
|
||||||
@ -224,6 +224,8 @@ void PackUnix::pack2(OutputFile *fo, Filter &ft)
|
|||||||
if ((off_t)total_in != file_size) {
|
if ((off_t)total_in != file_size) {
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1; // default: write end-of-compression bhdr next
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -285,12 +287,13 @@ void PackUnix::pack(OutputFile *fo)
|
|||||||
set_te32(&hbuf.p_blocksize, blocksize);
|
set_te32(&hbuf.p_blocksize, blocksize);
|
||||||
fo->write(&hbuf, sizeof(hbuf));
|
fo->write(&hbuf, sizeof(hbuf));
|
||||||
|
|
||||||
pack2(fo, ft); // append the compressed body
|
// append the compressed body
|
||||||
|
if (pack2(fo, ft)) {
|
||||||
// write block end marker (uncompressed size 0)
|
// write block end marker (uncompressed size 0)
|
||||||
b_info hdr; memset(&hdr, 0, sizeof(hdr));
|
b_info hdr; memset(&hdr, 0, sizeof(hdr));
|
||||||
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
|
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
|
||||||
fo->write(&hdr, sizeof(hdr));
|
fo->write(&hdr, sizeof(hdr));
|
||||||
|
}
|
||||||
|
|
||||||
pack3(fo, ft); // append loader
|
pack3(fo, ft); // append loader
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// called by the generic pack()
|
// called by the generic pack()
|
||||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
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 pack3(OutputFile *, Filter &); // append loader
|
||||||
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user