Files
upx/src/packmast.cpp
T
Markus F.X.J. Oberhumer 46e2e40736 Disable PackLinuxI386sep for now. Compressed binaries really should
be completely self contained. Also, I'm afraid that an external
decompressor will require too much work for maintaining unlimited
backward compatibility.

If we really want to enable this again at some future point more
work must go into it - at least I think that there should be a
*single* external program that handles all algorithms and versions.

committer: mfx <mfx> 973827819 +0000
2000-11-10 03:43:39 +00:00

270 lines
5.8 KiB
C++

/* packmast.cpp --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2000 Laszlo Molnar
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
*/
#include "conf.h"
#include "file.h"
#include "packmast.h"
#include "packer.h"
#include "lefile.h"
#include "p_com.h"
#include "p_djgpp2.h"
#include "p_exe.h"
#include "p_elf.h"
#include "p_unix.h"
#include "p_lx_elf.h"
#include "p_lx_sep.h"
#include "p_lx_sh.h"
#include "p_sys.h"
#include "p_tos.h"
#include "p_wcle.h"
#include "p_tmt.h"
#include "p_vxd.h"
#include "p_w32pe.h"
/*************************************************************************
//
**************************************************************************/
PackMaster::PackMaster(InputFile *f, struct options_t *o) :
fi(f), p(NULL)
{
// replace options with local options
saved_opt = o;
if (o)
{
this->local_options = *o; // struct copy
opt = &this->local_options;
}
}
PackMaster::~PackMaster()
{
fi = NULL;
delete p; p = NULL;
// restore options
if (saved_opt)
opt = saved_opt;
saved_opt = NULL;
}
/*************************************************************************
//
**************************************************************************/
typedef Packer* (*try_function)(Packer *p, InputFile *f);
static Packer* try_pack(Packer *p, InputFile *f)
{
if (p == NULL)
return NULL;
#if !defined(UNUPX)
try {
p->initPackHeader();
f->seek(0,SEEK_SET);
if (p->canPack())
{
p->updatePackHeader();
f->seek(0,SEEK_SET);
return p;
}
} catch (IOException&) {
} catch (...) {
delete p;
throw;
}
#endif /* UNUPX */
delete p;
return NULL;
}
static Packer* try_unpack(Packer *p, InputFile *f)
{
if (p == NULL)
return NULL;
try {
p->initPackHeader();
f->seek(0,SEEK_SET);
int r = p->canUnpack();
if (r > 0)
{
f->seek(0,SEEK_SET);
return p;
}
if (r < 0)
{
// FIXME - could stop testing all other unpackers at this time
// see canUnpack() in packer.h
}
} catch (IOException&) {
} catch (...) {
delete p;
throw;
}
delete p;
return NULL;
}
/*************************************************************************
//
**************************************************************************/
static Packer* try_packers(InputFile *f, try_function func)
{
Packer *p = NULL;
// note: order of tries is important !
if (!opt->dos.force_stub)
{
if ((p = func(new PackDjgpp2(f),f)) != NULL)
return p;
if ((p = func(new PackTmt(f),f)) != NULL)
return p;
if ((p = func(new PackWcle(f),f)) != NULL)
return p;
#if 0
if ((p = func(new PackVxd(f),f)) != NULL)
return p;
#endif
if ((p = func(new PackW32Pe(f),f)) != NULL)
return p;
}
if ((p = func(new PackExe(f),f)) != NULL)
return p;
if ((p = func(new PackTos(f),f)) != NULL)
return p;
#if 0
if (opt->unix.script_name)
{
if ((p = func(new PackLinuxI386sep(f),f)) != NULL)
return p;
}
#endif
if ((p = func(new PackLinuxI386elf(f),f)) != NULL)
return p;
if ((p = func(new PackLinuxI386sh(f),f)) != NULL)
return p;
#if 0
if ((p = func(new PackBvmlinuxI386(f),f)) != NULL)
return p;
#endif
if ((p = func(new PackLinuxI386(f),f)) != NULL)
return p;
if ((p = func(new PackSys(f),f)) != NULL)
return p;
if ((p = func(new PackCom(f),f)) != NULL)
return p;
return NULL;
}
static Packer *getPacker(InputFile *f)
{
Packer *p = try_packers(f, try_pack);
if (!p)
throwUnknownExecutableFormat();
return p;
}
static Packer *getUnpacker(InputFile *f)
{
Packer *p = try_packers(f, try_unpack);
if (!p)
throwNotPacked();
return p;
}
static void assertPacker(const Packer *p)
{
assert(strlen(p->getName()) <= 13);
}
/*************************************************************************
// delegation
**************************************************************************/
void PackMaster::pack(OutputFile *fo)
{
p = getPacker(fi);
assertPacker(p);
fi = NULL;
p->doPack(fo);
}
void PackMaster::unpack(OutputFile *fo)
{
p = getUnpacker(fi);
assertPacker(p);
fi = NULL;
p->doUnpack(fo);
}
void PackMaster::test()
{
p = getUnpacker(fi);
assertPacker(p);
fi = NULL;
p->doTest();
}
void PackMaster::list()
{
p = getUnpacker(fi);
assertPacker(p);
fi = NULL;
p->doList();
}
void PackMaster::fileInfo()
{
p = try_packers(fi, try_unpack);
if (!p)
p = try_packers(fi, try_pack);
if (!p)
throwUnknownExecutableFormat(NULL, 1); // make a warning here
assertPacker(p);
fi = NULL;
p->doFileInfo();
}
/*
vi:ts=4:et:nowrap
*/