src: clang-format various packers

This commit is contained in:
Markus F.X.J. Oberhumer
2022-11-26 17:45:25 +01:00
parent 93c6496ba8
commit 9f5d67e27c
13 changed files with 863 additions and 1275 deletions
+2 -1
View File
@@ -79,7 +79,8 @@ CLANG_FORMAT_FILES += except.cpp except.h
CLANG_FORMAT_FILES += file.cpp file.h CLANG_FORMAT_FILES += file.cpp file.h
CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp packmast.cpp packmast.h CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp packmast.cpp packmast.h
CLANG_FORMAT_FILES += main.cpp options.cpp options.h packer.cpp packer.h CLANG_FORMAT_FILES += main.cpp options.cpp options.h packer.cpp packer.h
CLANG_FORMAT_FILES += p_tmt.cpp p_tmt.h p_tos.cpp p_tos.h CLANG_FORMAT_FILES += p_com.cpp p_com.h p_djgpp2.cpp p_djgpp2.h p_exe.cpp p_exe.h p_ps1.cpp p_ps1.h
CLANG_FORMAT_FILES += p_sys.cpp p_sys.h p_tmt.cpp p_tmt.h p_tos.cpp p_tos.h p_wcle.cpp p_wcle.h
CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h
CLANG_FORMAT_FILES += ui.cpp ui.h work.cpp CLANG_FORMAT_FILES += ui.cpp ui.h work.cpp
CLANG_FORMAT_FILES += $(wildcard util/[a-ln-z]*.[ch]* util/mem*.[ch]*) CLANG_FORMAT_FILES += $(wildcard util/[a-ln-z]*.[ch]* util/mem*.[ch]*)
+44 -84
View File
@@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@@ -33,49 +32,42 @@
#include "p_com.h" #include "p_com.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i086-dos16.com.h" #include "stub/i086-dos16.com.h"
//#define TESTING 1 //#define TESTING 1
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
const int *PackCom::getCompressionMethods(int method, int level) const const int *PackCom::getCompressionMethods(int method, int level) const {
{ static const int m_nrv2b[] = {M_NRV2B_LE16, M_END};
static const int m_nrv2b[] = { M_NRV2B_LE16, M_END };
#if 0 #if 0
static const int m_nrv2d[] = { M_NRV2D_LE16, M_END }; static const int m_nrv2d[] = { M_NRV2D_LE16, M_END };
#endif #endif
UNUSED(method); UNUSED(level); UNUSED(method);
UNUSED(level);
return m_nrv2b; return m_nrv2b;
} }
const int *PackCom::getFilters() const {
const int *PackCom::getFilters() const static const int filters[] = {0x06, 0x03, 0x04, 0x01, 0x05, 0x02, FT_END};
{
static const int filters[] = {
0x06, 0x03, 0x04, 0x01, 0x05, 0x02,
FT_END };
return filters; return filters;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
bool PackCom::canPack() bool PackCom::canPack() {
{
unsigned char buf[128]; unsigned char buf[128];
fi->readx(buf, sizeof(buf)); fi->readx(buf, sizeof(buf));
if (memcmp(buf,"MZ",2) == 0 || memcmp(buf,"ZM",2) == 0 // .exe if (memcmp(buf, "MZ", 2) == 0 || memcmp(buf, "ZM", 2) == 0 // .exe
|| memcmp (buf,"\xff\xff\xff\xff",4) == 0) // .sys || memcmp(buf, "\xff\xff\xff\xff", 4) == 0) // .sys
return false; return false;
if (!fn_has_ext(fi->getName(),"com")) if (!fn_has_ext(fi->getName(), "com"))
return false; return false;
checkAlreadyPacked(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024) if (file_size < 1024)
@@ -85,15 +77,11 @@ bool PackCom::canPack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackCom::patchLoader(OutputFile *fo, void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
upx_byte *loader, int lsize,
unsigned calls)
{
const int e_len = getLoaderSectionStart("COMCUTPO"); const int e_len = getLoaderSectionStart("COMCUTPO");
const int d_len = lsize - e_len; const int d_len = lsize - e_len;
assert(e_len > 0 && e_len < 128); assert(e_len > 0 && e_len < 128);
@@ -118,11 +106,11 @@ void PackCom::patchLoader(OutputFile *fo,
loader = getLoader(); loader = getLoader();
// some day we could use the relocation stuff for patchPackHeader too // some day we could use the relocation stuff for patchPackHeader too
patchPackHeader(loader,e_len); patchPackHeader(loader, e_len);
// write loader + compressed file // write loader + compressed file
fo->write(loader,e_len); // entry fo->write(loader, e_len); // entry
fo->write(obuf,ph.c_len); fo->write(obuf, ph.c_len);
fo->write(loader+e_len,d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
#if 0 #if 0
printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len); printf("%-13s: entry : %8ld bytes\n", getName(), (long) e_len);
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len); printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
@@ -130,65 +118,45 @@ void PackCom::patchLoader(OutputFile *fo,
#endif #endif
} }
void PackCom::buildLoader(const Filter *ft) {
void PackCom::buildLoader(const Filter *ft)
{
initLoader(stub_i086_dos16_com, sizeof(stub_i086_dos16_com)); initLoader(stub_i086_dos16_com, sizeof(stub_i086_dos16_com));
addLoader("COMMAIN1", addLoader("COMMAIN1", ph.first_offset_found == 1 ? "COMSBBBP" : "", "COMPSHDI",
ph.first_offset_found == 1 ? "COMSBBBP" : "", ft->id ? "COMCALLT" : "", "COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160",
"COMPSHDI", ft->id ? "NRVDDONE" : "NRVDRETU", "NRVDECO1",
ft->id ? "COMCALLT" : "", ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
"COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160", if (ft->id) {
ft->id ? "NRVDDONE" : "NRVDRETU",
"NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
"NRVDECO2",
nullptr
);
if (ft->id)
{
assert(ft->calls > 0); assert(ft->calls > 0);
addFilter16(ft->id); addFilter16(ft->id);
} }
} }
void PackCom::addFilter16(int filter_id) {
void PackCom::addFilter16(int filter_id)
{
assert(filter_id > 0); assert(filter_id > 0);
assert(isValidFilter(filter_id)); assert(isValidFilter(filter_id));
if (filter_id % 3 == 0) if (filter_id % 3 == 0)
addLoader("CALLTR16", addLoader("CALLTR16", filter_id < 4 ? "CT16SUB0" : "",
filter_id < 4 ? "CT16SUB0" : "", filter_id < 4 ? ""
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"), : (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"),
"CALLTRI2", "CALLTRI2", getFormat() == UPX_F_DOS_COM ? "CORETURN" : "", nullptr);
getFormat() == UPX_F_DOS_COM ? "CORETURN" : "",
nullptr
);
else else
addLoader(filter_id%3 == 1 ? "CT16E800" : "CT16E900", addLoader(
"CALLTRI5", filter_id % 3 == 1 ? "CT16E800" : "CT16E900", "CALLTRI5",
getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2", getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2", filter_id < 4 ? "CT16SUB1" : "",
filter_id < 4 ? "CT16SUB1" : "", filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I087" : "CT16I287,CT16SUB1"),
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I087" : "CT16I287,CT16SUB1"), "CALLTRI6", nullptr);
"CALLTRI6",
nullptr
);
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackCom::pack(OutputFile *fo) void PackCom::pack(OutputFile *fo) {
{
// read file // read file
ibuf.alloc(file_size); ibuf.alloc(file_size);
obuf.allocForCompression(file_size); obuf.allocForCompression(file_size);
fi->seek(0,SEEK_SET); fi->seek(0, SEEK_SET);
fi->readx(ibuf,file_size); fi->readx(ibuf, file_size);
// prepare packheader // prepare packheader
ph.u_len = file_size; ph.u_len = file_size;
@@ -201,7 +169,7 @@ void PackCom::pack(OutputFile *fo)
const int lsize = getLoaderSize(); const int lsize = getLoaderSize();
MemBuffer loader(lsize); MemBuffer loader(lsize);
memcpy(loader,getLoader(),lsize); memcpy(loader, getLoader(), lsize);
const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls; const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls;
patchLoader(fo, loader, lsize, calls); patchLoader(fo, loader, lsize, calls);
@@ -214,13 +182,11 @@ void PackCom::pack(OutputFile *fo)
throwNotCompressible(); throwNotCompressible();
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
int PackCom::canUnpack() int PackCom::canUnpack() {
{
if (!readPackHeader(128)) if (!readPackHeader(128))
return false; return false;
if (file_size_u <= ph.c_len) if (file_size_u <= ph.c_len)
@@ -228,19 +194,17 @@ int PackCom::canUnpack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackCom::unpack(OutputFile *fo) void PackCom::unpack(OutputFile *fo) {
{
ibuf.alloc(file_size); ibuf.alloc(file_size);
obuf.allocForDecompression(ph.u_len); obuf.allocForDecompression(ph.u_len);
// read whole file // read whole file
fi->seek(0,SEEK_SET); fi->seek(0, SEEK_SET);
fi->readx(ibuf,file_size); fi->readx(ibuf, file_size);
// get compressed data offset // get compressed data offset
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize(); unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
@@ -248,22 +212,18 @@ void PackCom::unpack(OutputFile *fo)
throwCantUnpack("file damaged"); throwCantUnpack("file damaged");
// decompress // decompress
decompress(ibuf+e_len,obuf); decompress(ibuf + e_len, obuf);
// unfilter // unfilter
Filter ft(ph.level); Filter ft(ph.level);
ft.init(ph.filter, getCallTrickOffset()); ft.init(ph.filter, getCallTrickOffset());
ft.unfilter(obuf,ph.u_len); ft.unfilter(obuf, ph.u_len);
// write decompressed file // write decompressed file
if (fo) if (fo)
fo->write(obuf,ph.u_len); fo->write(obuf, ph.u_len);
} }
Linker *PackCom::newLinker() const { return new ElfLinkerX86(); }
Linker* PackCom::newLinker() const
{
return new ElfLinkerX86();
}
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+6 -9
View File
@@ -25,24 +25,22 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_P_COM_H #ifndef UPX_P_COM_H__
#define __UPX_P_COM_H 1 #define UPX_P_COM_H__ 1
/************************************************************************* /*************************************************************************
// dos/com // dos/com
**************************************************************************/ **************************************************************************/
class PackCom : public Packer class PackCom : public Packer {
{
typedef Packer super; typedef Packer super;
public: public:
PackCom(InputFile *f) : super(f) { bele = &N_BELE_RTP::le_policy; } PackCom(InputFile *f) : super(f) { bele = &N_BELE_RTP::le_policy; }
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
virtual int getFormat() const override { return UPX_F_DOS_COM; } virtual int getFormat() const override { return UPX_F_DOS_COM; }
virtual const char *getName() const override { return "dos/com"; } virtual const char *getName() const override { return "dos/com"; }
//virtual const char *getFullName(const options_t *o) const override { return o && o->cpu == o->CPU_8086 ? "i086-dos16.com" : "i286-dos16.com"; }
virtual const char *getFullName(const options_t *) const override { return "i086-dos16.com"; } virtual const char *getFullName(const options_t *) const override { return "i086-dos16.com"; }
virtual const int *getCompressionMethods(int method, int level) const override; virtual const int *getCompressionMethods(int method, int level) const override;
virtual const int *getFilters() const override; virtual const int *getFilters() const override;
@@ -55,7 +53,7 @@ public:
protected: protected:
virtual unsigned getCallTrickOffset() const { return 0x100; } virtual unsigned getCallTrickOffset() const { return 0x100; }
virtual Linker* newLinker() const override; virtual Linker *newLinker() const override;
protected: protected:
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
@@ -63,7 +61,6 @@ protected:
virtual void addFilter16(int filter_id); virtual void addFilter16(int filter_id);
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+69 -129
View File
@@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@@ -33,19 +32,16 @@
#include "p_djgpp2.h" #include "p_djgpp2.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i386-dos32.djgpp2.h" #include "stub/i386-dos32.djgpp2.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i386-dos32.djgpp2-stubify.h" #include "stub/i386-dos32.djgpp2-stubify.h"
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
PackDjgpp2::PackDjgpp2(InputFile *f) : PackDjgpp2::PackDjgpp2(InputFile *f) : super(f), coff_offset(0) {
super(f), coff_offset(0)
{
bele = &N_BELE_RTP::le_policy; bele = &N_BELE_RTP::le_policy;
COMPILE_TIME_ASSERT(sizeof(external_scnhdr_t) == 40) COMPILE_TIME_ASSERT(sizeof(external_scnhdr_t) == 40)
COMPILE_TIME_ASSERT(sizeof(coff_header_t) == 0xa8) COMPILE_TIME_ASSERT(sizeof(coff_header_t) == 0xa8)
@@ -53,60 +49,38 @@ PackDjgpp2::PackDjgpp2(InputFile *f) :
COMPILE_TIME_ASSERT_ALIGNED1(coff_header_t) COMPILE_TIME_ASSERT_ALIGNED1(coff_header_t)
COMPILE_TIME_ASSERT(sizeof(stub_i386_dos32_djgpp2_stubify) == 2048) COMPILE_TIME_ASSERT(sizeof(stub_i386_dos32_djgpp2_stubify) == 2048)
COMPILE_TIME_ASSERT(STUB_I386_DOS32_DJGPP2_STUBIFY_ADLER32 == 0xbf689ba8) COMPILE_TIME_ASSERT(STUB_I386_DOS32_DJGPP2_STUBIFY_ADLER32 == 0xbf689ba8)
COMPILE_TIME_ASSERT(STUB_I386_DOS32_DJGPP2_STUBIFY_CRC32 == 0x2ae982b2) COMPILE_TIME_ASSERT(STUB_I386_DOS32_DJGPP2_STUBIFY_CRC32 == 0x2ae982b2)
//printf("0x%08x\n", upx_adler32(stubify_stub, sizeof(stubify_stub))); // printf("0x%08x\n", upx_adler32(stubify_stub, sizeof(stubify_stub)));
//assert(upx_adler32(stubify_stub, sizeof(stubify_stub)) == STUBIFY_STUB_ADLER32); // assert(upx_adler32(stubify_stub, sizeof(stubify_stub)) == STUBIFY_STUB_ADLER32);
} }
const int *PackDjgpp2::getCompressionMethods(int method, int level) const {
const int *PackDjgpp2::getCompressionMethods(int method, int level) const
{
return Packer::getDefaultCompressionMethods_le32(method, level); return Packer::getDefaultCompressionMethods_le32(method, level);
} }
const int *PackDjgpp2::getFilters() const {
const int *PackDjgpp2::getFilters() const static const int filters[] = {0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14,
{ 0x11, FT_ULTRA_BRUTE, 0x25, 0x15, 0x12, FT_END};
static const int filters[] = {
0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14, 0x11,
FT_ULTRA_BRUTE, 0x25, 0x15, 0x12,
FT_END };
return filters; return filters;
} }
unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf, unsigned range,
unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf, unsigned upper_limit) const {
const upx_bytep tbuf,
unsigned range,
unsigned upper_limit) const
{
unsigned o = super::findOverlapOverhead(buf, tbuf, range, upper_limit); unsigned o = super::findOverlapOverhead(buf, tbuf, range, upper_limit);
o = (o + 0x3ff) &~ 0x1ff; o = (o + 0x3ff) & ~0x1ff;
return o; return o;
} }
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
Linker* PackDjgpp2::newLinker() const void PackDjgpp2::buildLoader(const Filter *ft) {
{
return new ElfLinkerX86;
}
void PackDjgpp2::buildLoader(const Filter *ft)
{
// prepare loader // prepare loader
initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2)); initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2));
addLoader("IDENTSTR,DJ2MAIN1", addLoader("IDENTSTR,DJ2MAIN1", ft->id ? "DJCALLT1" : "",
ft->id ? "DJCALLT1" : "",
ph.first_offset_found == 1 ? "DJ2MAIN2" : "", ph.first_offset_found == 1 ? "DJ2MAIN2" : "",
M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "", M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "", getDecompressorSections(),
getDecompressorSections(), M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "", "DJ2BSS00", nullptr);
M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "", if (ft->id) {
"DJ2BSS00",
nullptr
);
if (ft->id)
{
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader("DJCALLT2", nullptr); addLoader("DJCALLT2", nullptr);
addFilter32(ft->id); addFilter32(ft->id);
@@ -114,32 +88,24 @@ void PackDjgpp2::buildLoader(const Filter *ft)
addLoader("DJRETURN,+40C,UPX1HEAD", nullptr); addLoader("DJRETURN,+40C,UPX1HEAD", nullptr);
} }
/************************************************************************* /*************************************************************************
// util // util
**************************************************************************/ **************************************************************************/
void PackDjgpp2::handleStub(OutputFile *fo) void PackDjgpp2::handleStub(OutputFile *fo) {
{ if (fo && !opt->djgpp2_coff.coff) {
if (fo && !opt->djgpp2_coff.coff) if (coff_offset > 0) {
{
if (coff_offset > 0)
{
// copy stub from exe // copy stub from exe
Packer::handleStub(fi, fo, coff_offset); Packer::handleStub(fi, fo, coff_offset);
} } else {
else
{
// "stubify" stub // "stubify" stub
info("Adding stub: %ld bytes", (long)sizeof(stub_i386_dos32_djgpp2_stubify)); info("Adding stub: %ld bytes", (long) sizeof(stub_i386_dos32_djgpp2_stubify));
fo->write(stub_i386_dos32_djgpp2_stubify, sizeof(stub_i386_dos32_djgpp2_stubify)); fo->write(stub_i386_dos32_djgpp2_stubify, sizeof(stub_i386_dos32_djgpp2_stubify));
} }
} }
} }
static bool is_dlm(InputFile *fi, unsigned coff_offset) {
static bool is_dlm(InputFile *fi, unsigned coff_offset)
{
unsigned char buf[4]; unsigned char buf[4];
unsigned off; unsigned off;
@@ -153,14 +119,12 @@ static bool is_dlm(InputFile *fi, unsigned coff_offset)
fi->readx(buf, 4); fi->readx(buf, 4);
if (memcmp(buf, "DLMF", 4) == 0) if (memcmp(buf, "DLMF", 4) == 0)
return true; return true;
} catch (const IOException&) { } catch (const IOException &) {
} }
return false; return false;
} }
static void handle_allegropak(InputFile *fi, OutputFile *fo) {
static void handle_allegropak(InputFile *fi, OutputFile *fo)
{
unsigned char b[8]; unsigned char b[8];
int pfsize = 0; int pfsize = 0;
@@ -169,80 +133,71 @@ static void handle_allegropak(InputFile *fi, OutputFile *fo)
fi->readx(b, 8); fi->readx(b, 8);
if (memcmp(b, "slh+", 4) != 0) if (memcmp(b, "slh+", 4) != 0)
return; return;
pfsize = get_be32_signed(b+4); pfsize = get_be32_signed(b + 4);
if (pfsize <= 8 || pfsize >= fi->st.st_size) if (pfsize <= 8 || pfsize >= fi->st.st_size)
return; return;
fi->seek(-pfsize, SEEK_END); fi->seek(-pfsize, SEEK_END);
} catch (const IOException&) { } catch (const IOException &) {
return; return;
} }
MemBuffer buf(0x4000); MemBuffer buf(0x4000);
while (pfsize > 0) while (pfsize > 0) {
{ const int len = UPX_MIN(pfsize, (int) buf.getSize());
const int len = UPX_MIN(pfsize, (int)buf.getSize());
fi->readx(buf, len); fi->readx(buf, len);
fo->write(buf, len); fo->write(buf, len);
pfsize -= len; pfsize -= len;
} }
} }
int PackDjgpp2::readFileHeader() {
int PackDjgpp2::readFileHeader()
{
unsigned char hdr[0x1c]; unsigned char hdr[0x1c];
unsigned char magic[8]; unsigned char magic[8];
fi->seek(0, SEEK_SET); fi->seek(0, SEEK_SET);
fi->readx(hdr, sizeof(hdr)); fi->readx(hdr, sizeof(hdr));
if (get_le16(hdr) == 0x5a4d) // MZ exe signature, stubbed? if (get_le16(hdr) == 0x5a4d) // MZ exe signature, stubbed?
{ {
coff_offset = 512 * get_le16(hdr+4); coff_offset = 512 * get_le16(hdr + 4);
if (get_le16(hdr+2) != 0) if (get_le16(hdr + 2) != 0)
coff_offset += get_le16(hdr+2) - 512; coff_offset += get_le16(hdr + 2) - 512;
fi->seek(512, SEEK_SET); fi->seek(512, SEEK_SET);
fi->readx(magic, 8); fi->readx(magic, 8);
if (memcmp("go32stub", magic, 8) != 0) if (memcmp("go32stub", magic, 8) != 0)
return 0; // not V2 image return 0; // not V2 image
fi->seek(coff_offset, SEEK_SET); fi->seek(coff_offset, SEEK_SET);
if (fi->read(&coff_hdr, sizeof(coff_hdr)) != sizeof(coff_hdr)) if (fi->read(&coff_hdr, sizeof(coff_hdr)) != sizeof(coff_hdr))
throwCantPack("skipping djgpp symlink"); throwCantPack("skipping djgpp symlink");
} } else {
else
{
fi->seek(coff_offset, SEEK_SET); fi->seek(coff_offset, SEEK_SET);
fi->readx(&coff_hdr, 0xa8); fi->readx(&coff_hdr, 0xa8);
} }
if (coff_hdr.f_magic != 0x014c) // I386MAGIC if (coff_hdr.f_magic != 0x014c) // I386MAGIC
return 0; return 0;
if ((coff_hdr.f_flags & 2) == 0) // F_EXEC - COFF executable if ((coff_hdr.f_flags & 2) == 0) // F_EXEC - COFF executable
return 0; return 0;
if (coff_hdr.a_magic != 0413) // ZMAGIC - demand load format if (coff_hdr.a_magic != 0413) // ZMAGIC - demand load format
return 0; return 0;
// FIXME: check for Linux etc. // FIXME: check for Linux etc.
text = coff_hdr.sh; text = coff_hdr.sh;
data = text + 1; data = text + 1;
bss = data + 1; bss = data + 1;
return UPX_F_DJGPP2_COFF; return UPX_F_DJGPP2_COFF;
} }
// "strip" debug info // "strip" debug info
void PackDjgpp2::stripDebug() void PackDjgpp2::stripDebug() {
{
coff_hdr.f_symptr = 0; coff_hdr.f_symptr = 0;
coff_hdr.f_nsyms = 0; coff_hdr.f_nsyms = 0;
coff_hdr.f_flags = 0x10f; // 0x100: "32 bit machine: LSB first" coff_hdr.f_flags = 0x10f; // 0x100: "32 bit machine: LSB first"
memset(text->misc, 0, 12); memset(text->misc, 0, 12);
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
bool PackDjgpp2::canPack() bool PackDjgpp2::canPack() {
{
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
if (is_dlm(fi, coff_offset)) if (is_dlm(fi, coff_offset))
@@ -253,38 +208,32 @@ bool PackDjgpp2::canPack()
throwAlreadyPacked(); throwAlreadyPacked();
// Check for gap in vaddr between text and data, or between data and bss. // Check for gap in vaddr between text and data, or between data and bss.
if (text->vaddr + text->size != data->vaddr if (text->vaddr + text->size != data->vaddr || data->vaddr + data->size != bss->vaddr) {
|| data->vaddr + data->size != bss->vaddr)
{
// "Non-standard" layout of text,data,bss: not contiguous in vaddr. // "Non-standard" layout of text,data,bss: not contiguous in vaddr.
// But should be OK if no overlap. // But should be OK if no overlap.
// Check for no overlap of text and data: // Check for no overlap of text and data:
// neither by vaddr, nor by image data // neither by vaddr, nor by image data
if (text->vaddr + text->size <= data->vaddr && if (text->vaddr + text->size <= data->vaddr &&
data->scnptr - text->scnptr <= data->vaddr - text->vaddr) data->scnptr - text->scnptr <= data->vaddr - text->vaddr) {
{
// Examples: Quake1; FreePascal(DOS) install.exe (github-issue45) // Examples: Quake1; FreePascal(DOS) install.exe (github-issue45)
// Hack: enlarge text image data to eliminate the gap. // Hack: enlarge text image data to eliminate the gap.
text->size = coff_hdr.a_tsize = data->scnptr - text->scnptr; text->size = coff_hdr.a_tsize = data->scnptr - text->scnptr;
// But complain if this causes overlap in vaddr // But complain if this causes overlap in vaddr
if (text->vaddr + text->size > data->vaddr) if (text->vaddr + text->size > data->vaddr)
throwAlreadyPacked(); throwAlreadyPacked();
} } else
else
throwAlreadyPacked(); throwAlreadyPacked();
} }
// FIXME: check for Linux etc. // FIXME: check for Linux etc.
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackDjgpp2::pack(OutputFile *fo) void PackDjgpp2::pack(OutputFile *fo) {
{
handleStub(fo); handleStub(fo);
// patch coff header #1: "strip" debug info // patch coff header #1: "strip" debug info
@@ -302,7 +251,7 @@ void PackDjgpp2::pack(OutputFile *fo)
obuf.allocForCompression(usize); obuf.allocForCompression(usize);
fi->seek(coff_offset, SEEK_SET); fi->seek(coff_offset, SEEK_SET);
fi->readx(ibuf, hdrsize); // orig. coff header fi->readx(ibuf, hdrsize); // orig. coff header
fi->seek(coff_offset + tpos, SEEK_SET); fi->seek(coff_offset + tpos, SEEK_SET);
fi->readx(ibuf + hdrsize, size); fi->readx(ibuf + hdrsize, size);
@@ -313,7 +262,8 @@ void PackDjgpp2::pack(OutputFile *fo)
ft.buf_len = usize - data->size; ft.buf_len = usize - data->size;
ft.addvalue = text->vaddr - hdrsize; ft.addvalue = text->vaddr - hdrsize;
// compress // compress
upx_compress_config_t cconf; cconf.reset(); upx_compress_config_t cconf;
cconf.reset();
// limit stack size needed for runtime decompression // limit stack size needed for runtime decompression
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
compressWithFilters(&ft, 512, &cconf); compressWithFilters(&ft, 512, &cconf);
@@ -321,24 +271,25 @@ void PackDjgpp2::pack(OutputFile *fo)
// patch coff header #2 // patch coff header #2
const unsigned lsize = getLoaderSize(); const unsigned lsize = getLoaderSize();
assert(lsize % 4 == 0); assert(lsize % 4 == 0);
text->size = lsize; // new size of .text text->size = lsize; // new size of .text
data->size = ph.c_len; // new size of .data data->size = ph.c_len; // new size of .data
unsigned stack = 1024 + ph.overlap_overhead + getDecompressorWrkmemSize(); unsigned stack = 1024 + ph.overlap_overhead + getDecompressorWrkmemSize();
stack = ALIGN_UP(stack, 16u); stack = ALIGN_UP(stack, 16u);
if (bss->size < stack) // give it a .bss if (bss->size < stack) // give it a .bss
bss->size = stack; bss->size = stack;
text->scnptr = sizeof(coff_hdr); text->scnptr = sizeof(coff_hdr);
data->scnptr = text->scnptr + text->size; data->scnptr = text->scnptr + text->size;
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + ph.overlap_overhead - 0x200; data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size +
ph.overlap_overhead - 0x200;
coff_hdr.f_nscns = 3; coff_hdr.f_nscns = 3;
linker->defineSymbol("original_entry", coff_hdr.a_entry); linker->defineSymbol("original_entry", coff_hdr.a_entry);
linker->defineSymbol("length_of_bss", ph.overlap_overhead / 4); linker->defineSymbol("length_of_bss", ph.overlap_overhead / 4);
defineDecompressorSymbols(); defineDecompressorSymbols();
// Just need no overlap; non-contiguous (gap length > 0)) is OK // Just need no overlap; non-contiguous (gap length > 0)) is OK
assert(bss->vaddr >= ((size + 0x1ff) &~ 0x1ff) + (text->vaddr &~ 0x1ff)); assert(bss->vaddr >= ((size + 0x1ff) & ~0x1ff) + (text->vaddr & ~0x1ff));
linker->defineSymbol("stack_for_lzma", bss->vaddr + bss->size); linker->defineSymbol("stack_for_lzma", bss->vaddr + bss->size);
linker->defineSymbol("start_of_uncompressed", text->vaddr - hdrsize); linker->defineSymbol("start_of_uncompressed", text->vaddr - hdrsize);
linker->defineSymbol("start_of_compressed", data->vaddr); linker->defineSymbol("start_of_compressed", data->vaddr);
@@ -356,7 +307,7 @@ void PackDjgpp2::pack(OutputFile *fo)
bss->size -= ph.overlap_overhead; bss->size -= ph.overlap_overhead;
// because of a feature (bug?) in stub.asm we need some padding // because of a feature (bug?) in stub.asm we need some padding
memcpy(obuf+data->size, "UPX", 3); memcpy(obuf + data->size, "UPX", 3);
data->size = ALIGN_UP(data->size, 4u); data->size = ALIGN_UP(data->size, 4u);
linker->defineSymbol("DJ2MAIN1", coff_hdr.a_entry); linker->defineSymbol("DJ2MAIN1", coff_hdr.a_entry);
@@ -391,13 +342,11 @@ void PackDjgpp2::pack(OutputFile *fo)
throwNotCompressible(); throwNotCompressible();
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
int PackDjgpp2::canUnpack() int PackDjgpp2::canUnpack() {
{
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
if (is_dlm(fi, coff_offset)) if (is_dlm(fi, coff_offset))
@@ -406,13 +355,11 @@ int PackDjgpp2::canUnpack()
return readPackHeader(4096) ? 1 : -1; return readPackHeader(4096) ? 1 : -1;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackDjgpp2::unpack(OutputFile *fo) void PackDjgpp2::unpack(OutputFile *fo) {
{
handleStub(fo); handleStub(fo);
ibuf.alloc(ph.c_len); ibuf.alloc(ph.c_len);
@@ -424,27 +371,24 @@ void PackDjgpp2::unpack(OutputFile *fo)
// decompress // decompress
decompress(ibuf, obuf); decompress(ibuf, obuf);
coff_header_t *chdr = (coff_header_t*) obuf.getVoidPtr(); coff_header_t *chdr = (coff_header_t *) obuf.getVoidPtr();
text = chdr->sh; text = chdr->sh;
data = text + 1; data = text + 1;
const unsigned hdrsize = 20 + 28 const unsigned hdrsize = 20 + 28 + sizeof(external_scnhdr_t) * chdr->f_nscns;
+ sizeof(external_scnhdr_t) * chdr->f_nscns;
unsigned addvalue; unsigned addvalue;
if (ph.version >= 14) if (ph.version >= 14)
addvalue = text->vaddr - hdrsize; addvalue = text->vaddr - hdrsize;
else else
addvalue = text->vaddr &~ 0x1ff; // for old versions addvalue = text->vaddr & ~0x1ff; // for old versions
// unfilter // unfilter
if (ph.filter) if (ph.filter) {
{
Filter ft(ph.level); Filter ft(ph.level);
ft.init(ph.filter, addvalue); ft.init(ph.filter, addvalue);
ft.cto = (unsigned char) ph.filter_cto; ft.cto = (unsigned char) ph.filter_cto;
if (ph.version < 11) if (ph.version < 11) {
{
unsigned char ctobuf[4]; unsigned char ctobuf[4];
fi->readx(ctobuf, 4); fi->readx(ctobuf, 4);
ft.cto = (unsigned char) (get_le32(ctobuf) >> 24); ft.cto = (unsigned char) (get_le32(ctobuf) >> 24);
@@ -452,17 +396,14 @@ void PackDjgpp2::unpack(OutputFile *fo)
ft.unfilter(obuf, ph.u_len - data->size); ft.unfilter(obuf, ph.u_len - data->size);
} }
if (ph.version < 14) if (ph.version < 14) {
{
// fixup for the aligning bug in strip 2.8+ // fixup for the aligning bug in strip 2.8+
text->scnptr &= 0x1ff; text->scnptr &= 0x1ff;
data->scnptr = text->scnptr + text->size; data->scnptr = text->scnptr + text->size;
// write decompressed file // write decompressed file
if (fo) if (fo)
fo->write(obuf, ph.u_len); fo->write(obuf, ph.u_len);
} } else {
else
{
// write the header // write the header
// some padding might be required between the end // some padding might be required between the end
// of the header and the start of the .text section // of the header and the start of the .text section
@@ -470,8 +411,7 @@ void PackDjgpp2::unpack(OutputFile *fo)
const unsigned padding = text->scnptr - hdrsize; const unsigned padding = text->scnptr - hdrsize;
ibuf.clear(0, padding); ibuf.clear(0, padding);
if (fo) if (fo) {
{
fo->write(obuf, hdrsize); fo->write(obuf, hdrsize);
fo->write(ibuf, padding); fo->write(ibuf, padding);
fo->write(obuf + hdrsize, ph.u_len - hdrsize); fo->write(obuf + hdrsize, ph.u_len - hdrsize);
+34 -36
View File
@@ -25,17 +25,15 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_P_DJGPP2_H #ifndef UPX_P_DJGPP2_H__
#define __UPX_P_DJGPP2_H 1 #define UPX_P_DJGPP2_H__ 1
/************************************************************************* /*************************************************************************
// djgpp2/coff // djgpp2/coff
**************************************************************************/ **************************************************************************/
class PackDjgpp2 final : public Packer class PackDjgpp2 final : public Packer {
{
typedef Packer super; typedef Packer super;
public: public:
@@ -43,7 +41,9 @@ public:
virtual int getVersion() const override { return 14; } virtual int getVersion() const override { return 14; }
virtual int getFormat() const override { return UPX_F_DJGPP2_COFF; } virtual int getFormat() const override { return UPX_F_DJGPP2_COFF; }
virtual const char *getName() const override { return "djgpp2/coff"; } virtual const char *getName() const override { return "djgpp2/coff"; }
virtual const char *getFullName(const options_t *) const override { return "i386-dos32.djgpp2.coff"; } virtual const char *getFullName(const options_t *) const override {
return "i386-dos32.djgpp2.coff";
}
virtual const int *getCompressionMethods(int method, int level) const override; virtual const int *getCompressionMethods(int method, int level) const override;
virtual const int *getFilters() const override; virtual const int *getFilters() const override;
@@ -57,54 +57,52 @@ protected:
void handleStub(OutputFile *fo); void handleStub(OutputFile *fo);
int readFileHeader(); int readFileHeader();
virtual unsigned findOverlapOverhead(const upx_bytep buf, virtual unsigned findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf,
const upx_bytep tbuf,
unsigned range = 0, unsigned range = 0,
unsigned upper_limit = ~0u) const override; unsigned upper_limit = ~0u) const override;
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
virtual Linker* newLinker() const override; virtual Linker *newLinker() const override;
unsigned coff_offset; unsigned coff_offset;
__packed_struct(external_scnhdr_t) struct alignas(1) external_scnhdr_t {
char _[12]; // name, paddr char _[12]; // name, paddr
LE32 vaddr; LE32 vaddr;
LE32 size; LE32 size;
LE32 scnptr; LE32 scnptr;
char misc[12]; // relptr, lnnoptr, nreloc, nlnno char misc[12]; // relptr, lnnoptr, nreloc, nlnno
char __[4]; // flags char __[4]; // flags
__packed_struct_end() };
__packed_struct(coff_header_t) struct alignas(1) coff_header_t {
// ext_file_hdr // ext_file_hdr
LE16 f_magic; LE16 f_magic;
LE16 f_nscns; LE16 f_nscns;
char _[4]; // f_timdat char _[4]; // f_timdat
LE32 f_symptr; LE32 f_symptr;
LE32 f_nsyms; LE32 f_nsyms;
char __[2]; // f_opthdr char __[2]; // f_opthdr
LE16 f_flags; LE16 f_flags;
// aout_hdr // aout_hdr
LE16 a_magic; LE16 a_magic;
char ___[2]; // a_vstamp char ___[2]; // a_vstamp
LE32 a_tsize; LE32 a_tsize;
LE32 a_dsize; LE32 a_dsize;
char ____[4]; // a_bsize char ____[4]; // a_bsize
LE32 a_entry; LE32 a_entry;
char _____[8]; // a_text_start a_data_start char _____[8]; // a_text_start a_data_start
// section headers // section headers
external_scnhdr_t sh[3]; external_scnhdr_t sh[3];
__packed_struct_end() };
coff_header_t coff_hdr; coff_header_t coff_hdr;
external_scnhdr_t *text,*data,*bss; external_scnhdr_t *text, *data, *bss;
void stripDebug(); void stripDebug();
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+198 -301
View File
@@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@@ -33,23 +32,20 @@
#include "p_exe.h" #include "p_exe.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i086-dos16.exe.h" #include "stub/i086-dos16.exe.h"
#define RSFCRI 4096 // Reserved Space For Compressed Relocation Info #define RSFCRI 4096 // Reserved Space For Compressed Relocation Info
#define MAXMATCH 0x2000 #define MAXMATCH 0x2000
#define MAXRELOCS (0x8000-MAXMATCH) #define MAXRELOCS (0x8000 - MAXMATCH)
#define DI_LIMIT 0xff00 // see the assembly why
#define DI_LIMIT 0xff00 // see the assembly why
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
PackExe::PackExe(InputFile *f) : PackExe::PackExe(InputFile *f) : super(f) {
super(f)
{
bele = &N_BELE_RTP::le_policy; bele = &N_BELE_RTP::le_policy;
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 32) COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 32)
COMPILE_TIME_ASSERT_ALIGNED1(exe_header_t) COMPILE_TIME_ASSERT_ALIGNED1(exe_header_t)
@@ -58,10 +54,8 @@ PackExe::PackExe(InputFile *f) :
use_clear_dirty_stack = false; use_clear_dirty_stack = false;
} }
const int *PackExe::getCompressionMethods(int method, int level) const {
const int *PackExe::getCompressionMethods(int method, int level) const bool small = ih_imagesize <= 256 * 1024;
{
bool small = ih_imagesize <= 256*1024;
// disable lzma for "--brute" unless explicitly given "--lzma" // disable lzma for "--brute" unless explicitly given "--lzma"
// WARNING: this side effect may persists for later files; // WARNING: this side effect may persists for later files;
// but note that class PackMaster creates per-file local options // but note that class PackMaster creates per-file local options
@@ -70,16 +64,10 @@ const int *PackExe::getCompressionMethods(int method, int level) const
return Packer::getDefaultCompressionMethods_8(method, level, small); return Packer::getDefaultCompressionMethods_8(method, level, small);
} }
const int *PackExe::getFilters() const { return nullptr; }
const int *PackExe::getFilters() const int PackExe::fillExeHeader(struct exe_header_t *eh) const {
{ #define oh (*eh)
return nullptr;
}
int PackExe::fillExeHeader(struct exe_header_t *eh) const
{
#define oh (*eh)
// fill new exe header // fill new exe header
int flag = 0; int flag = 0;
if (!opt->dos_exe.no_reloc && !M_IS_LZMA(ph.method)) if (!opt->dos_exe.no_reloc && !M_IS_LZMA(ph.method))
@@ -87,7 +75,7 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
if (ih.relocs == 0) if (ih.relocs == 0)
flag |= NORELOC; flag |= NORELOC;
memset(&oh,0,sizeof(oh)); memset(&oh, 0, sizeof(oh));
oh.ident = 'M' + 'Z' * 256; oh.ident = 'M' + 'Z' * 256;
oh.headsize16 = 2; oh.headsize16 = 2;
@@ -103,11 +91,10 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
oh.sp = minsp; oh.sp = minsp;
unsigned destpara = (ph.u_len + ph.overlap_overhead - ph.c_len + 31) / 16; unsigned destpara = (ph.u_len + ph.overlap_overhead - ph.c_len + 31) / 16;
oh.ss = ph.c_len/16 + destpara; oh.ss = ph.c_len / 16 + destpara;
if (ih.ss*16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200) if (ih.ss * 16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200)
oh.ss = ih.ss; oh.ss = ih.ss;
if (oh.ss*16 + 0x50 < ih.ss*16 + ih.sp if (oh.ss * 16 + 0x50 < ih.ss * 16 + ih.sp && oh.ss * 16 + 0x200 > ih.ss * 16 + ih.sp)
&& oh.ss*16 + 0x200 > ih.ss*16 + ih.sp)
oh.ss += 0x20; oh.ss += 0x20;
if (oh.ss != ih.ss) if (oh.ss != ih.ss)
@@ -118,58 +105,38 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
#undef oh #undef oh
} }
void PackExe::addLoaderEpilogue(int flag) void PackExe::addLoaderEpilogue(int flag) {
{
addLoader("EXEMAIN5", nullptr); addLoader("EXEMAIN5", nullptr);
if (relocsize) if (relocsize)
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ" : "EXEADJUS", addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ"
"EXERELO1", : "EXEADJUS",
has_9a ? "EXEREL9A" : "", "EXERELO1", has_9a ? "EXEREL9A" : "", "EXERELO2",
"EXERELO2", ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3", nullptr);
ih_exesize > 0xFE00 ? "EXEREBIG" : "", addLoader("EXEMAIN8", device_driver ? "DEVICEEND" : "", (flag & SS) ? "EXESTACK" : "",
"EXERELO3", (flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "", nullptr);
nullptr
);
addLoader("EXEMAIN8",
device_driver ? "DEVICEEND" : "",
(flag & SS) ? "EXESTACK" : "",
(flag & SP) ? "EXESTASP" : "",
(flag & USEJUMP) ? "EXEJUMPF" : "",
nullptr
);
if (!(flag & USEJUMP)) if (!(flag & USEJUMP))
addLoader(ih.cs ? "EXERCSPO" : "", addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP", nullptr);
"EXERETIP",
nullptr
);
linker->defineSymbol("original_cs", ih.cs); linker->defineSymbol("original_cs", ih.cs);
linker->defineSymbol("original_ip", ih.ip); linker->defineSymbol("original_ip", ih.ip);
linker->defineSymbol("original_sp", ih.sp); linker->defineSymbol("original_sp", ih.sp);
linker->defineSymbol("original_ss", ih.ss); linker->defineSymbol("original_ss", ih.ss);
linker->defineSymbol("reloc_size", linker->defineSymbol(
(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) "reloc_size",
>= relocsize ? 0 : MAXRELOCS) - relocsize); (ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? 0 : MAXRELOCS) - relocsize);
} }
void PackExe::buildLoader(const Filter *) void PackExe::buildLoader(const Filter *) {
{
// get flag // get flag
exe_header_t dummy_oh; exe_header_t dummy_oh;
int flag = fillExeHeader(&dummy_oh); int flag = fillExeHeader(&dummy_oh);
initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe)); initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe));
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method)) {
{ addLoader("LZMA_DEC00", opt->small ? "LZMA_DEC10" : "LZMA_DEC20", "LZMA_DEC30",
addLoader("LZMA_DEC00", use_clear_dirty_stack ? "LZMA_DEC31" : "", "LZMA_DEC32",
opt->small ? "LZMA_DEC10" : "LZMA_DEC20", ph.u_len > 0xffff ? "LZMA_DEC33" : "", nullptr);
"LZMA_DEC30",
use_clear_dirty_stack ? "LZMA_DEC31" : "",
"LZMA_DEC32",
ph.u_len > 0xffff ? "LZMA_DEC33" : "",
nullptr
);
addLoaderEpilogue(flag); addLoaderEpilogue(flag);
defineDecompressorSymbols(); defineDecompressorSymbols();
@@ -196,9 +163,10 @@ void PackExe::buildLoader(const Filter *)
MemBuffer compressed_lzma; MemBuffer compressed_lzma;
compressed_lzma.allocForCompression(lsize); compressed_lzma.allocForCompression(lsize);
unsigned c_len_lzma = MemBuffer::getSizeForCompression(lsize); unsigned c_len_lzma = MemBuffer::getSizeForCompression(lsize);
int r = upx_compress(loader, lsize, compressed_lzma, &c_len_lzma, int r = upx_compress(loader, lsize, compressed_lzma, &c_len_lzma, nullptr, M_NRV2B_LE16, 9,
nullptr, M_NRV2B_LE16, 9, nullptr, nullptr); nullptr, nullptr);
assert(r == UPX_E_OK); assert(c_len_lzma < lsize); assert(r == UPX_E_OK);
assert(c_len_lzma < lsize);
info("lzma+relocator code compressed: %u -> %u", lsize, c_len_lzma); info("lzma+relocator code compressed: %u -> %u", lsize, c_len_lzma);
// reinit the loader // reinit the loader
@@ -208,61 +176,33 @@ void PackExe::buildLoader(const Filter *)
addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2", nullptr); addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2", nullptr);
linker->addSection("COMPRESSED_LZMA", compressed_lzma, c_len_lzma, 0); linker->addSection("COMPRESSED_LZMA", compressed_lzma, c_len_lzma, 0);
addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2", addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2", nullptr);
nullptr);
} } else if (device_driver)
else if (device_driver)
addLoader("DEVICEENTRY,DEVICEENTRY2", nullptr); addLoader("DEVICEENTRY,DEVICEENTRY2", nullptr);
addLoader("EXEENTRY", addLoader("EXEENTRY", M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB",
M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB", "JNCDOCOPY", relocsize ? "EXERELPU" : "", "EXEMAIN4",
"JNCDOCOPY", M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B", "EXEMAIN4C",
relocsize ? "EXERELPU" : "",
"EXEMAIN4",
M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B",
"EXEMAIN4C",
M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "", M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "",
"+G5DXXXX,UPX1HEAD,EXECUTPO", "+G5DXXXX,UPX1HEAD,EXECUTPO", nullptr);
nullptr
);
if (ph.method == M_NRV2B_8) if (ph.method == M_NRV2B_8)
addLoader("NRV2B16S", // decompressor addLoader("NRV2B16S", // decompressor
ph.u_len > DI_LIMIT ? "N2B64K01" : "", ph.u_len > DI_LIMIT ? "N2B64K01" : "", "NRV2BEX1",
"NRV2BEX1", opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", "NRV2BEX2",
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602", "NRV2BEX3",
"NRV2BEX2", ph.c_len > 0xffff ? "N2B64K02" : "", "NRV2BEX9", nullptr);
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602",
"NRV2BEX3",
ph.c_len > 0xffff ? "N2B64K02" : "",
"NRV2BEX9",
nullptr
);
else if (ph.method == M_NRV2D_8) else if (ph.method == M_NRV2D_8)
addLoader("NRV2D16S", addLoader("NRV2D16S", ph.u_len > DI_LIMIT ? "N2D64K01" : "", "NRV2DEX1",
ph.u_len > DI_LIMIT ? "N2D64K01" : "", opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", "NRV2DEX2",
"NRV2DEX1", opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602", "NRV2DEX3",
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", ph.c_len > 0xffff ? "N2D64K02" : "", "NRV2DEX9", nullptr);
"NRV2DEX2",
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602",
"NRV2DEX3",
ph.c_len > 0xffff ? "N2D64K02" : "",
"NRV2DEX9",
nullptr
);
else if (ph.method == M_NRV2E_8) else if (ph.method == M_NRV2E_8)
addLoader("NRV2E16S", addLoader("NRV2E16S", ph.u_len > DI_LIMIT ? "N2E64K01" : "", "NRV2EEX1",
ph.u_len > DI_LIMIT ? "N2E64K01" : "", opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", "NRV2EEX2",
"NRV2EEX1", opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602", "NRV2EEX3",
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", ph.c_len > 0xffff ? "N2E64K02" : "", "NRV2EEX9", nullptr);
"NRV2EEX2", else if M_IS_LZMA (ph.method)
opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602",
"NRV2EEX3",
ph.c_len > 0xffff ? "N2E64K02" : "",
"NRV2EEX9",
nullptr
);
else if M_IS_LZMA(ph.method)
return; return;
else else
throwInternalError("unknown compression method"); throwInternalError("unknown compression method");
@@ -270,25 +210,22 @@ void PackExe::buildLoader(const Filter *)
addLoaderEpilogue(flag); addLoaderEpilogue(flag);
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
int PackExe::readFileHeader() int PackExe::readFileHeader() {
{
ih_exesize = ih_imagesize = ih_overlay = 0; ih_exesize = ih_imagesize = ih_overlay = 0;
fi->readx(&ih,sizeof(ih)); fi->readx(&ih, sizeof(ih));
if (ih.ident != 'M' + 'Z'*256 && ih.ident != 'Z' + 'M'*256) if (ih.ident != 'M' + 'Z' * 256 && ih.ident != 'Z' + 'M' * 256)
return 0; return 0;
ih_exesize = ih.m512 + ih.p512*512 - (ih.m512 ? 512 : 0); ih_exesize = ih.m512 + ih.p512 * 512 - (ih.m512 ? 512 : 0);
if (!ih_exesize) { if (!ih_exesize) {
ih_exesize = file_size; ih_exesize = file_size;
} }
ih_imagesize = ih_exesize - ih.headsize16*16; ih_imagesize = ih_exesize - ih.headsize16 * 16;
ih_overlay = file_size - ih_exesize; ih_overlay = file_size - ih_exesize;
if (file_size_u < sizeof(ih) if (file_size_u < sizeof(ih) || ((ih.m512 | ih.p512) && ih.m512 + ih.p512 * 512u < sizeof(ih)))
|| ((ih.m512 | ih.p512) && ih.m512+ih.p512*512u < sizeof (ih)))
throwCantPack("illegal exe header"); throwCantPack("illegal exe header");
if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize) if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
throwCantPack("exe header corrupted"); throwCantPack("exe header corrupted");
@@ -298,20 +235,17 @@ int PackExe::readFileHeader()
return UPX_F_DOS_EXE; return UPX_F_DOS_EXE;
} }
bool PackExe::canPack() {
bool PackExe::canPack() if (fn_has_ext(fi->getName(), "sys"))
{
if (fn_has_ext(fi->getName(),"sys"))
return false; return false;
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
if (file_size < 1024) if (file_size < 1024)
throwCantPack("file is too small"); throwCantPack("file is too small");
fi->seek(0x3c,SEEK_SET); fi->seek(0x3c, SEEK_SET);
LE32 offs; LE32 offs;
fi->readx(&offs,sizeof (offs)); fi->readx(&offs, sizeof(offs));
if (ih.relocoffs >= 0x40 && offs) if (ih.relocoffs >= 0x40 && offs) {
{
if (opt->dos_exe.force_stub) if (opt->dos_exe.force_stub)
opt->overlay = opt->COPY_OVERLAY; opt->overlay = opt->COPY_OVERLAY;
else else
@@ -320,20 +254,16 @@ bool PackExe::canPack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
static static unsigned optimize_relocs(upx_byte *b, const unsigned size, const upx_byte *relocs,
unsigned optimize_relocs(upx_byte *b, const unsigned size, const unsigned nrelocs, upx_byte *crel, bool *has_9a) {
const upx_byte *relocs, const unsigned nrelocs,
upx_byte *crel, bool *has_9a)
{
if (opt->exact) if (opt->exact)
throwCantPackExact(); throwCantPackExact();
upx_byte * const crel_save = crel; upx_byte *const crel_save = crel;
unsigned i; unsigned i;
unsigned seg_high = 0; unsigned seg_high = 0;
#if 0 #if 0
@@ -345,14 +275,12 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
#endif #endif
// pass 1 - find 0x9a bounds // pass 1 - find 0x9a bounds
for (i = 0; i < nrelocs; i++) for (i = 0; i < nrelocs; i++) {
{ unsigned addr = get_le32(relocs + 4 * i);
unsigned addr = get_le32(relocs+4*i);
if (addr >= size - 1) if (addr >= size - 1)
throwCantPack("unexpected relocation 1"); throwCantPack("unexpected relocation 1");
if (addr >= 3 && b[addr-3] == 0x9a) if (addr >= 3 && b[addr - 3] == 0x9a) {
{ unsigned seg = get_le16(b + addr);
unsigned seg = get_le16(b+addr);
if (seg > seg_high) if (seg > seg_high)
seg_high = seg; seg_high = seg;
#if 0 #if 0
@@ -371,10 +299,9 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
#endif #endif
} }
} }
//printf("%d %d\n", seg_low, seg_high); // printf("%d %d\n", seg_low, seg_high);
//printf("%d %d\n", off_low, off_high); // printf("%d %d\n", off_low, off_high);
//printf("%d %d\n", linear_low, linear_high); // printf("%d %d\n", linear_low, linear_high);
// pass 2 - reloc // pass 2 - reloc
@@ -383,37 +310,30 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
unsigned ones = 0; unsigned ones = 0;
unsigned es = 0, di, t; unsigned es = 0, di, t;
i = 0; i = 0;
do do {
{ unsigned addr = get_le32(relocs + 4 * i);
unsigned addr = get_le32(relocs+4*i); set_le16(crel, di = addr & 0x0f);
set_le16(crel,di = addr & 0x0f); set_le16(crel + 2, (addr >> 4) - es);
set_le16(crel+2,(addr >> 4) - es);
es = addr >> 4; es = addr >> 4;
crel += 4; crel += 4;
for (++i; i < nrelocs; i++) for (++i; i < nrelocs; i++) {
{ addr = get_le32(relocs + 4 * i);
addr = get_le32(relocs+4*i); // printf ("%x\n",es*16+di);
//printf ("%x\n",es*16+di); if ((addr - es * 16 > 0xfffe) || (i == nrelocs - 1 && addr - es * 16 > 0xff00)) {
if ((addr - es*16 > 0xfffe)
|| (i == nrelocs - 1 && addr - es * 16 > 0xff00)
)
{
// segment change // segment change
t = 1+(0xffff-di)/254; t = 1 + (0xffff - di) / 254;
memset(crel,1,t); memset(crel, 1, t);
crel += t; crel += t;
ones += t-1; // -1 is used to help the assembly stuff ones += t - 1; // -1 is used to help the assembly stuff
break; break;
} }
unsigned offs = addr - es*16; unsigned offs = addr - es * 16;
if (offs >= 3 && b[es*16 + offs-3] == 0x9a && offs > di + 3) if (offs >= 3 && b[es * 16 + offs - 3] == 0x9a && offs > di + 3) {
{ for (t = di; t < offs - 3; t++)
for (t = di; t < offs-3; t++) if (b[es * 16 + t] == 0x9a && get_le16(b + es * 16 + t + 3) <= seg_high)
if (b[es*16+t] == 0x9a && get_le16(b+es*16+t+3) <= seg_high)
break; break;
if (t == offs-3) if (t == offs - 3) {
{
// code 0: search for 0x9a // code 0: search for 0x9a
*crel++ = 0; *crel++ = 0;
di = offs; di = offs;
@@ -425,8 +345,7 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
if (t < 2) if (t < 2)
throwCantPack("unexpected relocation 2"); throwCantPack("unexpected relocation 2");
while (t >= 256) while (t >= 256) {
{
// code 1: add 254, don't reloc // code 1: add 254, don't reloc
*crel++ = 1; *crel++ = 1;
t -= 254; t -= 254;
@@ -438,20 +357,18 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
} while (i < nrelocs); } while (i < nrelocs);
*crel++ = 1; *crel++ = 1;
ones++; ones++;
set_le16 (crel_save,ones); set_le16(crel_save, ones);
set_le16 (crel_save+2,seg_high); set_le16(crel_save + 2, seg_high);
//OutputFile::dump("x.rel", crel_save, crel - crel_save); // OutputFile::dump("x.rel", crel_save, crel - crel_save);
return (unsigned) (crel - crel_save); return (unsigned) (crel - crel_save);
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackExe::pack(OutputFile *fo) void PackExe::pack(OutputFile *fo) {
{
unsigned ic; unsigned ic;
if (ih.relocs > MAXRELOCS) if (ih.relocs > MAXRELOCS)
@@ -459,13 +376,13 @@ void PackExe::pack(OutputFile *fo)
checkOverlay(ih_overlay); checkOverlay(ih_overlay);
// alloc buffers // alloc buffers
relocsize = RSFCRI + 4*ih.relocs; relocsize = RSFCRI + 4 * ih.relocs;
ibuf.alloc(ih_imagesize+16+relocsize+2); ibuf.alloc(ih_imagesize + 16 + relocsize + 2);
obuf.allocForCompression(ih_imagesize+16+relocsize+2); obuf.allocForCompression(ih_imagesize + 16 + relocsize + 2);
// read image // read image
fi->seek(ih.headsize16*16,SEEK_SET); fi->seek(ih.headsize16 * 16, SEEK_SET);
fi->readx(ibuf,ih_imagesize); fi->readx(ibuf, ih_imagesize);
checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u)); checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u));
@@ -474,21 +391,19 @@ void PackExe::pack(OutputFile *fo)
// relocations // relocations
has_9a = false; has_9a = false;
upx_byte *w = ibuf + ih_imagesize; upx_byte *w = ibuf + ih_imagesize;
if (ih.relocs) if (ih.relocs) {
{
upx_byte *wr = w + RSFCRI; upx_byte *wr = w + RSFCRI;
fi->seek(ih.relocoffs,SEEK_SET); fi->seek(ih.relocoffs, SEEK_SET);
fi->readx(wr,4*ih.relocs); fi->readx(wr, 4 * ih.relocs);
for (ic = 0; ic < ih.relocs; ic++) for (ic = 0; ic < ih.relocs; ic++) {
{ unsigned jc = get_le32(wr + 4 * ic);
unsigned jc = get_le32(wr+4*ic); set_le32(wr + 4 * ic, ((jc >> 16) * 16 + (jc & 0xffff)) & 0xfffff);
set_le32(wr+4*ic, ((jc>>16)*16+(jc&0xffff)) & 0xfffff);
} }
qsort(wr,ih.relocs,4,le32_compare); qsort(wr, ih.relocs, 4, le32_compare);
relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a); relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a);
set_le16(w+relocsize, relocsize+2); set_le16(w + relocsize, relocsize + 2);
relocsize += 2; relocsize += 2;
if (relocsize > MAXRELOCS) if (relocsize > MAXRELOCS)
throwCantPack("too many relocations"); throwCantPack("too many relocations");
@@ -499,9 +414,7 @@ void PackExe::pack(OutputFile *fo)
ucl_nrv2b_99_compress(w, in_len, out, &out_len, nullptr, 9, nullptr, nullptr); ucl_nrv2b_99_compress(w, in_len, out, &out_len, nullptr, 9, nullptr, nullptr);
printf("reloc compress: %d -> %d\n", in_len, out_len); printf("reloc compress: %d -> %d\n", in_len, out_len);
#endif #endif
} } else {
else
{
relocsize = 0; relocsize = 0;
} }
@@ -510,7 +423,8 @@ void PackExe::pack(OutputFile *fo)
// prepare filter // prepare filter
Filter ft(ph.level); Filter ft(ph.level);
// compress (max_match = 8192) // compress (max_match = 8192)
upx_compress_config_t cconf; cconf.reset(); upx_compress_config_t cconf;
cconf.reset();
cconf.conf_ucl.max_match = MAXMATCH; cconf.conf_ucl.max_match = MAXMATCH;
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
compressWithFilters(&ft, 32, &cconf); compressWithFilters(&ft, 32, &cconf);
@@ -520,13 +434,11 @@ void PackExe::pack(OutputFile *fo)
throwCantPack("decompressor limit exceeded, send a bugreport"); throwCantPack("decompressor limit exceeded, send a bugreport");
#if TESTING #if TESTING
if (opt->debug.debug_level) if (opt->debug.debug_level) {
{ printf("image+relocs %d -> %d\n", ih_imagesize + relocsize, ph.c_len);
printf("image+relocs %d -> %d\n",ih_imagesize+relocsize,ph.c_len); printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n", 0 /*ph.min_offset_found*/,
printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n", ph.max_offset_found, 0 /*ph.min_match_found*/, ph.max_match_found,
0/*ph.min_offset_found*/,ph.max_offset_found, 0 /*ph.min_run_found*/, ph.max_run_found);
0/*ph.min_match_found*/,ph.max_match_found,
0/*ph.min_run_found*/,ph.max_run_found);
} }
#endif #endif
@@ -534,22 +446,22 @@ void PackExe::pack(OutputFile *fo)
const unsigned lsize = getLoaderSize(); const unsigned lsize = getLoaderSize();
MemBuffer loader(lsize); MemBuffer loader(lsize);
memcpy(loader,getLoader(),lsize); memcpy(loader, getLoader(), lsize);
//OutputFile::dump("xxloader.dat", loader, lsize); // OutputFile::dump("xxloader.dat", loader, lsize);
// patch loader // patch loader
const unsigned packedsize = ph.c_len; const unsigned packedsize = ph.c_len;
const unsigned e_len = getLoaderSectionStart("EXECUTPO"); const unsigned e_len = getLoaderSectionStart("EXECUTPO");
const unsigned d_len = lsize - e_len; const unsigned d_len = lsize - e_len;
assert((e_len&15) == 0); assert((e_len & 15) == 0);
const unsigned copysize = (1+packedsize+d_len) & ~1; const unsigned copysize = (1 + packedsize + d_len) & ~1;
const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000; const unsigned firstcopy = copysize % 0x10000 ? copysize % 0x10000 : 0x10000;
// set oh.min & oh.max // set oh.min & oh.max
ic = ih.min*16 + ih_imagesize; ic = ih.min * 16 + ih_imagesize;
if (ic < oh.ss*16u + oh.sp) if (ic < oh.ss * 16u + oh.sp)
ic = oh.ss*16u + oh.sp; ic = oh.ss * 16u + oh.sp;
oh.min = (ic - (packedsize + lsize)) / 16; oh.min = (ic - (packedsize + lsize)) / 16;
ic = oh.min + (ih.max - ih.min); ic = oh.min + (ih.max - ih.min);
oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff; oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff;
@@ -557,27 +469,23 @@ void PackExe::pack(OutputFile *fo)
// set extra info // set extra info
unsigned char extra_info[9]; unsigned char extra_info[9];
unsigned eisize = 0; unsigned eisize = 0;
if (oh.ss != ih.ss) if (oh.ss != ih.ss) {
{ set_le16(extra_info + eisize, ih.ss);
set_le16(extra_info+eisize,ih.ss);
eisize += 2; eisize += 2;
assert((flag & SS) != 0); // set in fillExeHeader() assert((flag & SS) != 0); // set in fillExeHeader()
} }
if (oh.sp != ih.sp) if (oh.sp != ih.sp) {
{ set_le16(extra_info + eisize, ih.sp);
set_le16(extra_info+eisize,ih.sp);
eisize += 2; eisize += 2;
assert((flag & SP) != 0); // set in fillExeHeader() assert((flag & SP) != 0); // set in fillExeHeader()
} }
if (ih.min != oh.min) if (ih.min != oh.min) {
{ set_le16(extra_info + eisize, ih.min);
set_le16(extra_info+eisize,ih.min);
eisize += 2; eisize += 2;
flag |= MINMEM; flag |= MINMEM;
} }
if (ih.max != oh.max) if (ih.max != oh.max) {
{ set_le16(extra_info + eisize, ih.max);
set_le16(extra_info+eisize,ih.max);
eisize += 2; eisize += 2;
flag |= MAXMEM; flag |= MAXMEM;
} }
@@ -592,28 +500,25 @@ void PackExe::pack(OutputFile *fo)
linker->defineSymbol("decompressor_entry", decompressor_entry); linker->defineSymbol("decompressor_entry", decompressor_entry);
// patch loader // patch loader
if (flag & USEJUMP) if (flag & USEJUMP) {
{
// I use a relocation entry to set the original cs // I use a relocation entry to set the original cs
unsigned n = getLoaderSectionStart("EXEJUMPF") + 1; unsigned n = getLoaderSectionStart("EXEJUMPF") + 1;
n += packedsize + 2; n += packedsize + 2;
oh.relocs = 1; oh.relocs = 1;
oh.firstreloc = (n & 0xf) + ((n >> 4) << 16); oh.firstreloc = (n & 0xf) + ((n >> 4) << 16);
} } else {
else
{
oh.relocs = 0; oh.relocs = 0;
oh.firstreloc = ih.cs * 0x10000 + ih.ip; oh.firstreloc = ih.cs * 0x10000 + ih.ip;
} }
// g++ 3.1 does not like the following line... // g++ 3.1 does not like the following line...
oh.relocoffs = offsetof(exe_header_t, firstreloc); oh.relocoffs = offsetof(exe_header_t, firstreloc);
//oh.relocoffs = ptr_udiff_bytes(&oh.firstreloc, &oh); // oh.relocoffs = ptr_udiff_bytes(&oh.firstreloc, &oh);
linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16); linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16);
linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16); linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16);
linker->defineSymbol("copy_offset", firstcopy - 2); linker->defineSymbol("copy_offset", firstcopy - 2);
linker->defineSymbol("words_to_copy",firstcopy / 2); linker->defineSymbol("words_to_copy", firstcopy / 2);
linker->defineSymbol("exe_stack_sp", oh.sp); linker->defineSymbol("exe_stack_sp", oh.sp);
linker->defineSymbol("exe_stack_ss", oh.ss); linker->defineSymbol("exe_stack_ss", oh.ss);
@@ -621,7 +526,7 @@ void PackExe::pack(OutputFile *fo)
linker->defineSymbol("attribute", get_le16(ibuf + 4)); linker->defineSymbol("attribute", get_le16(ibuf + 4));
linker->defineSymbol("orig_strategy", get_le16(ibuf + 6)); linker->defineSymbol("orig_strategy", get_le16(ibuf + 6));
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize; const unsigned outputlen = sizeof(oh) + lsize + packedsize + eisize;
oh.m512 = outputlen & 511; oh.m512 = outputlen & 511;
oh.p512 = (outputlen + 511) >> 9; oh.p512 = (outputlen + 511) >> 9;
@@ -631,20 +536,21 @@ void PackExe::pack(OutputFile *fo)
defineDecompressorSymbols(); defineDecompressorSymbols();
relocateLoader(); relocateLoader();
memcpy(loader, getLoader(), lsize); memcpy(loader, getLoader(), lsize);
patchPackHeader(loader,e_len); patchPackHeader(loader, e_len);
//fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize); // fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x
// images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize);
// write header + write loader + compressed file // write header + write loader + compressed file
#if TESTING #if TESTING
if (opt->debug.debug_level) if (opt->debug.debug_level)
printf("\n%d %d %d %d\n",(int)sizeof(oh),e_len,packedsize,d_len); printf("\n%d %d %d %d\n", (int) sizeof(oh), e_len, packedsize, d_len);
#endif #endif
fo->write(&oh,sizeof(oh)); fo->write(&oh, sizeof(oh));
fo->write(loader,e_len); // entry fo->write(loader, e_len); // entry
fo->write(obuf,packedsize); fo->write(obuf, packedsize);
fo->write(loader+e_len,d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
fo->write(extra_info,eisize); fo->write(extra_info, eisize);
assert(eisize <= 9); assert(eisize <= 9);
#if 0 #if 0
printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh)); printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh));
@@ -659,20 +565,18 @@ void PackExe::pack(OutputFile *fo)
// copy the overlay // copy the overlay
copyOverlay(fo, ih_overlay, obuf); copyOverlay(fo, ih_overlay, obuf);
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len); // fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
// finally check the compression ratio // finally check the compression ratio
if (!checkFinalCompressionRatio(fo)) if (!checkFinalCompressionRatio(fo))
throwNotCompressible(); throwNotCompressible();
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
int PackExe::canUnpack() int PackExe::canUnpack() {
{
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
const unsigned off = ih.headsize16 * 16; const unsigned off = ih.headsize16 * 16;
@@ -681,19 +585,17 @@ int PackExe::canUnpack()
return b && (off + ph.c_len <= file_size_u); return b && (off + ph.c_len <= file_size_u);
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackExe::unpack(OutputFile *fo) void PackExe::unpack(OutputFile *fo) {
{
ibuf.alloc(file_size); ibuf.alloc(file_size);
obuf.allocForDecompression(ph.u_len); obuf.allocForDecompression(ph.u_len);
// read the file // read the file
fi->seek(ih.headsize16*16,SEEK_SET); fi->seek(ih.headsize16 * 16, SEEK_SET);
fi->readx(ibuf,ih_imagesize); fi->readx(ibuf, ih_imagesize);
// get compressed data offset // get compressed data offset
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize(); unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
@@ -703,7 +605,7 @@ void PackExe::unpack(OutputFile *fo)
checkOverlay(ih_overlay); checkOverlay(ih_overlay);
// decompress // decompress
decompress(ibuf+e_len,obuf); decompress(ibuf + e_len, obuf);
unsigned imagesize = ih_imagesize; unsigned imagesize = ih_imagesize;
imagesize--; imagesize--;
@@ -713,82 +615,81 @@ void PackExe::unpack(OutputFile *fo)
SPAN_S_VAR(upx_byte, relocs, obuf + ph.u_len, obuf); SPAN_S_VAR(upx_byte, relocs, obuf + ph.u_len, obuf);
MemBuffer wrkmem; MemBuffer wrkmem;
if (!(flag & NORELOC)) if (!(flag & NORELOC)) {
{ relocs -= get_le16(obuf + ph.u_len - 2);
relocs -= get_le16(obuf+ph.u_len-2);
ph.u_len -= 2; ph.u_len -= 2;
wrkmem.alloc(4*MAXRELOCS); wrkmem.alloc(4 * MAXRELOCS);
unsigned es = 0, ones = get_le16(relocs); unsigned es = 0, ones = get_le16(relocs);
const unsigned seghi = get_le16(relocs+2); const unsigned seghi = get_le16(relocs + 2);
SPAN_S_VAR(const upx_byte, p, relocs + 4); SPAN_S_VAR(const upx_byte, p, relocs + 4);
while (ones) while (ones) {
{
unsigned di = get_le16(p); unsigned di = get_le16(p);
es += get_le16(p+2); es += get_le16(p + 2);
bool dorel = true; bool dorel = true;
for (p += 4; ones && di < 0x10000; p++) for (p += 4; ones && di < 0x10000; p++) {
{ if (dorel) {
if (dorel) set_le16(wrkmem + 4 * relocn, di);
{ set_le16(wrkmem + 2 + 4 * relocn++, es);
set_le16(wrkmem+4*relocn,di); // printf ("%x\n",es*16+di);
set_le16(wrkmem+2+4*relocn++,es);
//printf ("%x\n",es*16+di);
} }
dorel = true; dorel = true;
if (*p == 0) if (*p == 0) {
{
SPAN_S_VAR(const upx_byte, q, obuf); SPAN_S_VAR(const upx_byte, q, obuf);
for (q = obuf+es*16+di; !(*q == 0x9a && get_le16(q+3) <= seghi); q++) for (q = obuf + es * 16 + di; !(*q == 0x9a && get_le16(q + 3) <= seghi); q++)
; ;
di = ptr_diff_bytes(q, obuf+es*16) + 3; di = ptr_diff_bytes(q, obuf + es * 16) + 3;
} } else if (*p == 1) {
else if (*p == 1)
{
di += 254; di += 254;
if (di < 0x10000) if (di < 0x10000)
ones--; ones--;
dorel = false; dorel = false;
} } else
else
di += *p; di += *p;
} }
} }
} }
// fill new exe header // fill new exe header
memset(&oh,0,sizeof(oh)); memset(&oh, 0, sizeof(oh));
oh.ident = 'M' + 'Z'*256; oh.ident = 'M' + 'Z' * 256;
if (relocn) if (relocn) {
{
oh.relocs = relocn; oh.relocs = relocn;
while (relocn & 3) while (relocn & 3)
set_le32(wrkmem+4*relocn++,0); set_le32(wrkmem + 4 * relocn++, 0);
} }
unsigned outputlen = ptr_udiff_bytes(relocs, obuf) + sizeof(oh) + relocn*4; unsigned outputlen = ptr_udiff_bytes(relocs, obuf) + sizeof(oh) + relocn * 4;
oh.m512 = outputlen & 511; oh.m512 = outputlen & 511;
oh.p512 = (outputlen + 511) >> 9; oh.p512 = (outputlen + 511) >> 9;
oh.headsize16 = 2+relocn/4; oh.headsize16 = 2 + relocn / 4;
oh.max = ih.max; oh.max = ih.max;
oh.min = ih.min; oh.min = ih.min;
oh.sp = ih.sp; oh.sp = ih.sp;
oh.ss = ih.ss; oh.ss = ih.ss;
if (flag & MAXMEM) if (flag & MAXMEM) {
{ imagesize -= 2; oh.max = get_le16(ibuf+imagesize); } imagesize -= 2;
if (flag & MINMEM) oh.max = get_le16(ibuf + imagesize);
{ imagesize -= 2; oh.min = get_le16(ibuf+imagesize); } }
if (flag & SP) if (flag & MINMEM) {
{ imagesize -= 2; oh.sp = get_le16(ibuf+imagesize); } imagesize -= 2;
if (flag & SS) oh.min = get_le16(ibuf + imagesize);
{ imagesize -= 2; oh.ss = get_le16(ibuf+imagesize); } }
if (flag & SP) {
imagesize -= 2;
oh.sp = get_le16(ibuf + imagesize);
}
if (flag & SS) {
imagesize -= 2;
oh.ss = get_le16(ibuf + imagesize);
}
unsigned ip = (flag & USEJUMP) ? get_le32(ibuf+imagesize-4) : (unsigned) ih.firstreloc; unsigned ip = (flag & USEJUMP) ? get_le32(ibuf + imagesize - 4) : (unsigned) ih.firstreloc;
oh.ip = ip & 0xffff; oh.ip = ip & 0xffff;
oh.cs = ip >> 16; oh.cs = ip >> 16;
@@ -798,20 +699,16 @@ void PackExe::unpack(OutputFile *fo)
return; return;
// write header + relocations + uncompressed file // write header + relocations + uncompressed file
fo->write(&oh,sizeof(oh)); fo->write(&oh, sizeof(oh));
if (relocn) if (relocn)
fo->write(wrkmem,relocn*4); fo->write(wrkmem, relocn * 4);
fo->write(obuf, ptr_diff_bytes(relocs, obuf)); fo->write(obuf, ptr_diff_bytes(relocs, obuf));
// copy the overlay // copy the overlay
copyOverlay(fo, ih_overlay, obuf); copyOverlay(fo, ih_overlay, obuf);
} }
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
Linker* PackExe::newLinker() const
{
return new ElfLinkerX86();
}
/* /*
+14 -26
View File
@@ -25,24 +25,22 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_P_EXE_H #ifndef UPX_P_EXE_H__
#define __UPX_P_EXE_H 1 #define UPX_P_EXE_H__ 1
/************************************************************************* /*************************************************************************
// dos/exe // dos/exe
**************************************************************************/ **************************************************************************/
class PackExe final : public Packer class PackExe final : public Packer {
{
typedef Packer super; typedef Packer super;
public: public:
PackExe(InputFile *f); PackExe(InputFile *f);
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
virtual int getFormat() const override { return UPX_F_DOS_EXE; } virtual int getFormat() const override { return UPX_F_DOS_EXE; }
virtual const char *getName() const override { return "dos/exe"; } virtual const char *getName() const override { return "dos/exe"; }
//virtual const char *getFullName(const options_t *o) const { return o && o->cpu == o->CPU_8086 ? "i086-dos16.exe" : "i286-dos16.exe"; }
virtual const char *getFullName(const options_t *) const override { return "i086-dos16.exe"; } virtual const char *getFullName(const options_t *) const override { return "i086-dos16.exe"; }
virtual const int *getCompressionMethods(int method, int level) const override; virtual const int *getCompressionMethods(int method, int level) const override;
virtual const int *getFilters() const override; virtual const int *getFilters() const override;
@@ -54,13 +52,11 @@ public:
virtual int canUnpack() override; virtual int canUnpack() override;
// unpacker capabilities // unpacker capabilities
virtual bool canUnpackVersion(int version) const override virtual bool canUnpackVersion(int version) const override {
{
// NOTE: could adapt p_exe.cpp to support (version >= 8) // NOTE: could adapt p_exe.cpp to support (version >= 8)
return (version >= 10); return (version >= 10);
} }
virtual bool canUnpackFormat(int format) const override virtual bool canUnpackFormat(int format) const override {
{
return (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH); return (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH);
} }
@@ -71,10 +67,10 @@ protected:
virtual int fillExeHeader(struct exe_header_t *) const; virtual int fillExeHeader(struct exe_header_t *) const;
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
virtual Linker* newLinker() const override; virtual Linker *newLinker() const override;
void addLoaderEpilogue(int flag); void addLoaderEpilogue(int flag);
__packed_struct(exe_header_t) struct alignas(1) exe_header_t {
LE16 ident; LE16 ident;
LE16 m512; LE16 m512;
LE16 p512; LE16 p512;
@@ -84,13 +80,13 @@ protected:
LE16 max; LE16 max;
LE16 ss; LE16 ss;
LE16 sp; LE16 sp;
char _[2]; // checksum char _[2]; // checksum
LE16 ip; LE16 ip;
LE16 cs; LE16 cs;
LE16 relocoffs; LE16 relocoffs;
char __[2]; // overlnum char __[2]; // overlnum
LE32 firstreloc; LE32 firstreloc;
__packed_struct_end() };
exe_header_t ih, oh; exe_header_t ih, oh;
@@ -102,20 +98,12 @@ protected:
bool has_9a; bool has_9a;
bool device_driver; bool device_driver;
enum { enum { NORELOC = 1, USEJUMP = 2, SS = 4, SP = 8, MINMEM = 16, MAXMEM = 32 };
NORELOC = 1,
USEJUMP = 2,
SS = 4,
SP = 8,
MINMEM = 16,
MAXMEM = 32
};
unsigned stack_for_lzma; // stack size required for lzma unsigned stack_for_lzma; // stack size required for lzma
bool use_clear_dirty_stack; bool use_clear_dirty_stack;
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+161 -244
View File
@@ -29,7 +29,6 @@
<jssg@users.sourceforge.net> <jssg@users.sourceforge.net>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@@ -37,30 +36,29 @@
#include "p_ps1.h" #include "p_ps1.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/mipsel.r3000-ps1.h" #include "stub/mipsel.r3000-ps1.h"
#define CD_SEC 2048 #define CD_SEC 2048
#define PS_HDR_SIZE CD_SEC #define PS_HDR_SIZE CD_SEC
#define PS_RAM_SIZE ram_size #define PS_RAM_SIZE ram_size
#define PS_MIN_SIZE (PS_HDR_SIZE*3) #define PS_MIN_SIZE (PS_HDR_SIZE * 3)
#define PS_MAX_SIZE ((PS_RAM_SIZE*95) / 100) #define PS_MAX_SIZE ((PS_RAM_SIZE * 95) / 100)
#define PS_STACK_SIZE (PS_RAM_SIZE / 256) #define PS_STACK_SIZE (PS_RAM_SIZE / 256)
#define SZ_IH_BKUP (10 * sizeof(LE32)) #define SZ_IH_BKUP (10 * sizeof(LE32))
#define HD_CODE_OFS (sizeof(ps1_exe_t) + sz_cbh) #define HD_CODE_OFS (sizeof(ps1_exe_t) + sz_cbh)
#define K0_BS (0x80000000) #define K0_BS (0x80000000)
#define K1_BS (0xa0000000) #define K1_BS (0xa0000000)
#define EXE_BS (ih.epc & K0_BS) #define EXE_BS (ih.epc & K0_BS)
#define FIX_PSVR ((K1_BS - EXE_BS) + (PS_HDR_SIZE - HD_CODE_OFS)) #define FIX_PSVR ((K1_BS - EXE_BS) + (PS_HDR_SIZE - HD_CODE_OFS))
// lui / addiu // lui / addiu
#define MIPS_HI(a) (((a) >> 16) + (((a) & 0x8000) >> 15)) #define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15))
#define MIPS_LO(a) ((a) & 0xffff) #define MIPS_LO(a) ((a) &0xffff)
#define MIPS_PC16(a) ((a) >> 2) #define MIPS_PC16(a) ((a) >> 2)
#define MIPS_PC26(a) (((a) & 0x0fffffff) >> 2) #define MIPS_PC26(a) (((a) &0x0fffffff) >> 2)
/************************************************************************* /*************************************************************************
// ps1 exe looks like this: // ps1 exe looks like this:
@@ -76,12 +74,10 @@ static const
// optional: not aligned to 2048 (for console run only) // optional: not aligned to 2048 (for console run only)
**************************************************************************/ **************************************************************************/
PackPs1::PackPs1(InputFile *f) : PackPs1::PackPs1(InputFile *f)
super(f), : super(f), isCon(!opt->ps1_exe.boot_only), is32Bit(!opt->ps1_exe.do_8bit), buildPart2(0),
isCon(!opt->ps1_exe.boot_only), is32Bit(!opt->ps1_exe.do_8bit), foundBss(0), sa_cnt(0), overlap(0), sz_lunc(0), sz_lcpr(0), pad_code(0), bss_start(0),
buildPart2(0), foundBss(0), sa_cnt(0), overlap(0), sz_lunc(0), sz_lcpr(0), bss_end(0) {
pad_code(0), bss_start(0), bss_end(0)
{
bele = &N_BELE_RTP::le_policy; bele = &N_BELE_RTP::le_policy;
COMPILE_TIME_ASSERT(sizeof(ps1_exe_t) == 136) COMPILE_TIME_ASSERT(sizeof(ps1_exe_t) == 136)
@@ -98,24 +94,16 @@ PackPs1::PackPs1(InputFile *f) :
ram_size = !opt->ps1_exe.do_8mib ? 0x200000 : 0x800000; ram_size = !opt->ps1_exe.do_8mib ? 0x200000 : 0x800000;
} }
const int *PackPs1::getCompressionMethods(int method, int level) const const int *PackPs1::getCompressionMethods(int method, int level) const {
{
if (is32Bit) if (is32Bit)
return Packer::getDefaultCompressionMethods_le32(method, level); return Packer::getDefaultCompressionMethods_le32(method, level);
else else
return Packer::getDefaultCompressionMethods_8(method, level); return Packer::getDefaultCompressionMethods_8(method, level);
} }
const int *PackPs1::getFilters() const const int *PackPs1::getFilters() const { return nullptr; }
{
return nullptr;
}
Linker* PackPs1::newLinker() const
{
return new ElfLinkerMipsLE;
}
Linker *PackPs1::newLinker() const { return new ElfLinkerMipsLE; }
/************************************************************************* /*************************************************************************
// util // util
@@ -123,116 +111,105 @@ Linker* PackPs1::newLinker() const
// checkFileHeader() checks ih for legal but unsupported values // checkFileHeader() checks ih for legal but unsupported values
**************************************************************************/ **************************************************************************/
int PackPs1::readFileHeader() int PackPs1::readFileHeader() {
{
fi->seek(0, SEEK_SET); fi->seek(0, SEEK_SET);
fi->readx(&ih, sizeof(ih)); fi->readx(&ih, sizeof(ih));
if (memcmp(&ih.id[0], "PS-X EXE", 8) != 0 && if (memcmp(&ih.id[0], "PS-X EXE", 8) != 0 && memcmp(&ih.id[0], "EXE X-SP", 8) != 0)
memcmp(&ih.id[0], "EXE X-SP", 8) != 0)
return 0; return 0;
if (ih.text != 0 || ih.data != 0) if (ih.text != 0 || ih.data != 0)
return 0; return 0;
return UPX_F_PS1_EXE; return UPX_F_PS1_EXE;
} }
bool PackPs1::readBkupHeader() bool PackPs1::readBkupHeader() {
{ fi->seek(sizeof(ps1_exe_t) + 8, SEEK_SET);
fi->seek(sizeof(ps1_exe_t)+8, SEEK_SET);
fi->readx(&bh, sizeof(bh)); fi->readx(&bh, sizeof(bh));
if (bh.ih_csum != upx_adler32(&bh, SZ_IH_BKUP)) if (bh.ih_csum != upx_adler32(&bh, SZ_IH_BKUP)) {
{
unsigned char buf[sizeof(bh)]; unsigned char buf[sizeof(bh)];
fi->seek(sizeof(ps1_exe_t), SEEK_SET); fi->seek(sizeof(ps1_exe_t), SEEK_SET);
fi->readx(buf, sizeof(bh)); fi->readx(buf, sizeof(bh));
if (!getBkupHeader(buf, (unsigned char *)&bh)) if (!getBkupHeader(buf, (unsigned char *) &bh))
return false; return false;
} }
return true; return true;
} }
#define INIT_BH_BKUP(p, l) ACC_BLOCK_BEGIN {(p)->id = '1'; (p)->len = l;} ACC_BLOCK_END #define INIT_BH_BKUP(p, l) \
#define ADLER16(a) (((a) >> 16) ^ ((a) & 0xffff)) ACC_BLOCK_BEGIN \
{ \
(p)->id = '1'; \
(p)->len = l; \
} \
ACC_BLOCK_END
#define ADLER16(a) (((a) >> 16) ^ ((a) &0xffff))
void PackPs1::putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len) void PackPs1::putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len) {
{
unsigned sz_cbh = MemBuffer::getSizeForCompression(SZ_IH_BKUP); unsigned sz_cbh = MemBuffer::getSizeForCompression(SZ_IH_BKUP);
if (src && dst) if (src && dst) {
{
unsigned char *cpr_bh = New(unsigned char, sz_cbh); unsigned char *cpr_bh = New(unsigned char, sz_cbh);
memset(cpr_bh, 0, sizeof(bh)); memset(cpr_bh, 0, sizeof(bh));
ps1_exe_chb_t * p = (ps1_exe_chb_t * )cpr_bh; ps1_exe_chb_t *p = (ps1_exe_chb_t *) cpr_bh;
int r = upx_compress(src, SZ_IH_BKUP, int r = upx_compress(src, SZ_IH_BKUP, &p->ih_bkup, &sz_cbh, nullptr, M_NRV2E_8, 10, nullptr,
&p->ih_bkup, &sz_cbh, nullptr, M_NRV2E_8, 10, nullptr, nullptr ); nullptr);
if (r != UPX_E_OK || sz_cbh >= SZ_IH_BKUP) if (r != UPX_E_OK || sz_cbh >= SZ_IH_BKUP)
throwInternalError("header compression failed"); throwInternalError("header compression failed");
INIT_BH_BKUP(p, sz_cbh); INIT_BH_BKUP(p, sz_cbh);
*len = ALIGN_UP(sz_cbh + (unsigned) sizeof(ps1_exe_chb_t) - 1, 4u); *len = ALIGN_UP(sz_cbh + (unsigned) sizeof(ps1_exe_chb_t) - 1, 4u);
p->ih_csum = ADLER16(upx_adler32(&ih.epc, SZ_IH_BKUP)); p->ih_csum = ADLER16(upx_adler32(&ih.epc, SZ_IH_BKUP));
memcpy(dst, cpr_bh, SZ_IH_BKUP); memcpy(dst, cpr_bh, SZ_IH_BKUP);
delete [] cpr_bh; delete[] cpr_bh;
} } else
else
throwInternalError("header compression failed"); throwInternalError("header compression failed");
} }
#define ADLER16_HI(a, b) ((((a) & 0xffff) ^ (b)) << 16) #define ADLER16_HI(a, b) ((((a) &0xffff) ^ (b)) << 16)
#define ADLER16_LO(a, b) (((a) >> 16) ^ (b)) #define ADLER16_LO(a, b) (((a) >> 16) ^ (b))
#define RE_ADLER16(a, b) (ADLER16_HI(a,b) | ADLER16_LO(a,b)) #define RE_ADLER16(a, b) (ADLER16_HI(a, b) | ADLER16_LO(a, b))
bool PackPs1::getBkupHeader(unsigned char *p, unsigned char *dst) bool PackPs1::getBkupHeader(unsigned char *p, unsigned char *dst) {
{ ps1_exe_chb_t *src = (ps1_exe_chb_t *) p;
ps1_exe_chb_t *src = (ps1_exe_chb_t*)p;
if (src && (src->id == '1' && src->len < SZ_IH_BKUP) && dst) if (src && (src->id == '1' && src->len < SZ_IH_BKUP) && dst) {
{
unsigned char *unc_bh = New(unsigned char, MemBuffer::getSizeForDecompression(SZ_IH_BKUP)); unsigned char *unc_bh = New(unsigned char, MemBuffer::getSizeForDecompression(SZ_IH_BKUP));
unsigned sz_bh = SZ_IH_BKUP; unsigned sz_bh = SZ_IH_BKUP;
int r = upx_decompress((const unsigned char *)&src->ih_bkup, src->len, int r = upx_decompress((const unsigned char *) &src->ih_bkup, src->len, unc_bh, &sz_bh,
unc_bh, &sz_bh, M_NRV2E_8, nullptr ); M_NRV2E_8, nullptr);
if (r == UPX_E_OUT_OF_MEMORY) if (r == UPX_E_OUT_OF_MEMORY)
throwOutOfMemoryException(); throwOutOfMemoryException();
if (r != UPX_E_OK || sz_bh != SZ_IH_BKUP) if (r != UPX_E_OK || sz_bh != SZ_IH_BKUP)
throwInternalError("header decompression failed"); throwInternalError("header decompression failed");
unsigned ad = upx_adler32(unc_bh, SZ_IH_BKUP); unsigned ad = upx_adler32(unc_bh, SZ_IH_BKUP);
unsigned ch = src->ih_csum; unsigned ch = src->ih_csum;
if (ad != RE_ADLER16(ad,ch)) if (ad != RE_ADLER16(ad, ch))
throwInternalError("backup header damaged"); throwInternalError("backup header damaged");
memcpy(dst, unc_bh, SZ_IH_BKUP); memcpy(dst, unc_bh, SZ_IH_BKUP);
delete [] unc_bh; delete[] unc_bh;
} } else
else
return false; return false;
return true; return true;
} }
bool PackPs1::checkFileHeader() bool PackPs1::checkFileHeader() {
{ if (fdata_size != ih.tx_len || (ih.tx_len & 3)) {
if (fdata_size != ih.tx_len || (ih.tx_len & 3))
{
if (!opt->force) if (!opt->force)
throwCantPack("file size entry damaged (try --force)"); throwCantPack("file size entry damaged (try --force)");
else else {
{
opt->info_mode += !opt->info_mode ? 1 : 0; opt->info_mode += !opt->info_mode ? 1 : 0;
infoWarning("fixing damaged header, keeping backup file"); infoWarning("fixing damaged header, keeping backup file");
opt->backup = 1; opt->backup = 1;
ih.tx_len = fdata_size; ih.tx_len = fdata_size;
} }
} }
if (!opt->force && if (!opt->force && (ih.da_ptr != 0 || ih.da_len != 0 || ih.bs_ptr != 0 || ih.bs_len != 0)) {
(ih.da_ptr != 0 || ih.da_len != 0 ||
ih.bs_ptr != 0 || ih.bs_len != 0))
{
infoWarning("unsupported header field entry"); infoWarning("unsupported header field entry");
return false; return false;
} }
if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE))) if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE))) {
{
if (!opt->force) if (!opt->force)
return false; return false;
else else
@@ -241,13 +218,11 @@ bool PackPs1::checkFileHeader()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
bool PackPs1::canPack() bool PackPs1::canPack() {
{
unsigned char buf[PS_HDR_SIZE - sizeof(ps1_exe_t)]; unsigned char buf[PS_HDR_SIZE - sizeof(ps1_exe_t)];
if (!readFileHeader()) if (!readFileHeader())
@@ -257,12 +232,10 @@ bool PackPs1::canPack()
checkAlreadyPacked(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf));
for (size_t i = 0; i < sizeof(buf); i++) for (size_t i = 0; i < sizeof(buf); i++)
if (buf[i] != 0) if (buf[i] != 0) {
{
if (!opt->force) if (!opt->force)
throwCantPack("unknown data in header (try --force)"); throwCantPack("unknown data in header (try --force)");
else else {
{
opt->info_mode += !opt->info_mode ? 1 : 0; opt->info_mode += !opt->info_mode ? 1 : 0;
infoWarning("clearing header, keeping backup file"); infoWarning("clearing header, keeping backup file");
opt->backup = 1; opt->backup = 1;
@@ -278,114 +251,88 @@ bool PackPs1::canPack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackPs1::buildLoader(const Filter *) void PackPs1::buildLoader(const Filter *) {
{
const char *method = nullptr; const char *method = nullptr;
if (ph.method == M_NRV2B_8) if (ph.method == M_NRV2B_8)
method = isCon ? "nrv2b.small,8bit.sub,nrv.done" : method = isCon ? "nrv2b.small,8bit.sub,nrv.done" : "nrv2b.8bit,nrv.done";
"nrv2b.8bit,nrv.done";
else if (ph.method == M_NRV2D_8) else if (ph.method == M_NRV2D_8)
method = isCon ? "nrv2d.small,8bit.sub,nrv.done" : method = isCon ? "nrv2d.small,8bit.sub,nrv.done" : "nrv2d.8bit,nrv.done";
"nrv2d.8bit,nrv.done";
else if (ph.method == M_NRV2E_8) else if (ph.method == M_NRV2E_8)
method = isCon ? "nrv2e.small,8bit.sub,nrv.done" : method = isCon ? "nrv2e.small,8bit.sub,nrv.done" : "nrv2e.8bit,nrv.done";
"nrv2e.8bit,nrv.done";
else if (ph.method == M_NRV2B_LE32) else if (ph.method == M_NRV2B_LE32)
method = isCon ? "nrv2b.small,32bit.sub,nrv.done" : method = isCon ? "nrv2b.small,32bit.sub,nrv.done" : "nrv2b.32bit,nrv.done";
"nrv2b.32bit,nrv.done";
else if (ph.method == M_NRV2D_LE32) else if (ph.method == M_NRV2D_LE32)
method = isCon ? "nrv2d.small,32bit.sub,nrv.done" : method = isCon ? "nrv2d.small,32bit.sub,nrv.done" : "nrv2d.32bit,nrv.done";
"nrv2d.32bit,nrv.done";
else if (ph.method == M_NRV2E_LE32) else if (ph.method == M_NRV2E_LE32)
method = isCon ? "nrv2e.small,32bit.sub,nrv.done" : method = isCon ? "nrv2e.small,32bit.sub,nrv.done" : "nrv2e.32bit,nrv.done";
"nrv2e.32bit,nrv.done";
else if (M_IS_LZMA(ph.method)) else if (M_IS_LZMA(ph.method))
method = "nrv2b.small,8bit.sub,nrv.done,lzma.prep"; method = "nrv2b.small,8bit.sub,nrv.done,lzma.prep";
else else
throwInternalError("unknown compression method"); throwInternalError("unknown compression method");
unsigned sa_tmp = sa_cnt; unsigned sa_tmp = sa_cnt;
if (ph.overlap_overhead > sa_cnt) if (ph.overlap_overhead > sa_cnt) {
{ if (!opt->force) {
if (!opt->force)
{
infoWarning("not in-place decompressible"); infoWarning("not in-place decompressible");
throwCantPack("packed data overlap (try --force)"); throwCantPack("packed data overlap (try --force)");
} } else
else
sa_tmp += overlap = ALIGN_UP((ph.overlap_overhead - sa_tmp), 4u); sa_tmp += overlap = ALIGN_UP((ph.overlap_overhead - sa_tmp), 4u);
} }
if (isCon || M_IS_LZMA(ph.method)) if (isCon || M_IS_LZMA(ph.method))
foundBss = findBssSection(); foundBss = findBssSection();
if (M_IS_LZMA(ph.method) && !buildPart2) if (M_IS_LZMA(ph.method) && !buildPart2) {
{
initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1)); initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1));
addLoader("decompressor.start", addLoader("decompressor.start", isCon ? "LZMA_DEC20" : "LZMA_DEC10", "lzma.init", nullptr);
isCon ? "LZMA_DEC20" : "LZMA_DEC10", "lzma.init", nullptr);
addLoader(sa_tmp > (0x10000 << 2) ? "memset.long" : "memset.short", addLoader(sa_tmp > (0x10000 << 2) ? "memset.long" : "memset.short",
!foundBss ? "con.exit" : "bss.exit", nullptr); !foundBss ? "con.exit" : "bss.exit", nullptr);
} } else {
else if (M_IS_LZMA(ph.method) && buildPart2) {
{
if (M_IS_LZMA(ph.method) && buildPart2)
{
sz_lcpr = MemBuffer::getSizeForCompression(sz_lunc); sz_lcpr = MemBuffer::getSizeForCompression(sz_lunc);
unsigned char *cprLoader = New(unsigned char, sz_lcpr); unsigned char *cprLoader = New(unsigned char, sz_lcpr);
int r = upx_compress(getLoader(), sz_lunc, cprLoader, &sz_lcpr, int r = upx_compress(getLoader(), sz_lunc, cprLoader, &sz_lcpr, nullptr, M_NRV2B_8, 10,
nullptr, M_NRV2B_8, 10, nullptr, nullptr ); nullptr, nullptr);
if (r != UPX_E_OK || sz_lcpr >= sz_lunc) if (r != UPX_E_OK || sz_lcpr >= sz_lunc)
throwInternalError("loader compression failed"); throwInternalError("loader compression failed");
initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1), initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1),
isCon || !M_IS_LZMA(ph.method) ? 0 : 1); isCon || !M_IS_LZMA(ph.method) ? 0 : 1);
linker->addSection("lzma.exec", cprLoader, sz_lcpr, 0); linker->addSection("lzma.exec", cprLoader, sz_lcpr, 0);
delete [] cprLoader; delete[] cprLoader;
} } else
else
initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1)); initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1));
pad_code = ALIGN_GAP((ph.c_len + (isCon ? sz_lcpr : 0)), 4u); pad_code = ALIGN_GAP((ph.c_len + (isCon ? sz_lcpr : 0)), 4u);
assert(pad_code < 4); assert(pad_code < 4);
static const unsigned char pad_buffer[4] = { 0, 0, 0, 0 }; static const unsigned char pad_buffer[4] = {0, 0, 0, 0};
linker->addSection("pad.code", pad_buffer, pad_code, 0); linker->addSection("pad.code", pad_buffer, pad_code, 0);
if (isCon) if (isCon) {
{
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method))
addLoader(!foundBss ? "con.start" : "bss.con.start", addLoader(!foundBss ? "con.start" : "bss.con.start", method,
method, ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "con.entry", "pad.code",
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "lzma.exec", nullptr);
"con.entry", "pad.code", "lzma.exec", nullptr);
else else
addLoader(!foundBss ? "con.start" : "bss.con.start", "con.mcpy", addLoader(!foundBss ? "con.start" : "bss.con.start", "con.mcpy",
ph.c_len & 3 ? "con.padcd" : "", ph.c_len & 3 ? "con.padcd" : "",
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "con.entry", method,
"con.entry", method,
sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "", sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "",
!foundBss ? "con.exit" : "bss.exit", !foundBss ? "con.exit" : "bss.exit", "pad.code", nullptr);
"pad.code", nullptr); } else {
}
else
{
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method))
addLoader(!foundBss ? "cdb.start.lzma" : "bss.cdb.start.lzma", "pad.code", addLoader(!foundBss ? "cdb.start.lzma" : "bss.cdb.start.lzma", "pad.code",
!foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma", !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma", method,
method, "cdb.lzma.cpr", "cdb.lzma.cpr", ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
"lzma.exec", nullptr); "lzma.exec", nullptr);
else else {
{
assert(foundBss != true); assert(foundBss != true);
addLoader("cdb.start", "pad.code", "cdb.entry", addLoader("cdb.start", "pad.code", "cdb.entry",
ih.tx_ptr & 0xffff ? "cdb.dec.ptr" : "cdb.dec.ptr.hi", ih.tx_ptr & 0xffff ? "cdb.dec.ptr" : "cdb.dec.ptr.hi", method,
method,
sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "", sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "",
"cdb.exit", nullptr); "cdb.exit", nullptr);
} }
@@ -394,63 +341,55 @@ void PackPs1::buildLoader(const Filter *)
} }
} }
#define OPTYPE(x) (((x) >> 13) & 0x7) #define OPTYPE(x) (((x) >> 13) & 0x7)
#define OPCODE(x) (((x) >> 10) & 0x7) #define OPCODE(x) (((x) >> 10) & 0x7)
#define REG1(x) (((x) >> 5) & 0x1f) #define REG1(x) (((x) >> 5) & 0x1f)
#define REG2(x) ((x) & 0x1f) #define REG2(x) ((x) &0x1f)
#define MIPS_IMM(a,b) ((((a) - (((b) & 0x8000) >> 15)) << 16) | (b)) #define MIPS_IMM(a, b) ((((a) - (((b) &0x8000) >> 15)) << 16) | (b))
// Type // Type
#define REGIMM 1 #define REGIMM 1
#define STORE 5 #define STORE 5
// Op // Op
#define LUI 7 #define LUI 7
#define ADDIU 1 #define ADDIU 1
#define SW 3 #define SW 3
#define IS_LUI(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == LUI)) #define IS_LUI(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == LUI))
#define IS_ADDIU(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == ADDIU)) #define IS_ADDIU(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == ADDIU))
#define IS_SW_ZERO(a) ((OPTYPE(a) == STORE && OPCODE(a) == SW) && REG2(a) == 0) #define IS_SW_ZERO(a) ((OPTYPE(a) == STORE && OPCODE(a) == SW) && REG2(a) == 0)
#define BSS_CHK_LIMIT (18) #define BSS_CHK_LIMIT (18)
bool PackPs1::findBssSection() bool PackPs1::findBssSection() {
{
unsigned char reg; unsigned char reg;
const LE32 * const p1 = ACC_CCAST(const LE32 *, ibuf + (ih.epc - ih.tx_ptr)); const LE32 *const p1 = ACC_CCAST(const LE32 *, ibuf + (ih.epc - ih.tx_ptr));
if ((ih.epc - ih.tx_ptr + (BSS_CHK_LIMIT * 4)) > fdata_size) if ((ih.epc - ih.tx_ptr + (BSS_CHK_LIMIT * 4)) > fdata_size)
return false; return false;
// check 18 opcodes for sw zero,0(x) // check 18 opcodes for sw zero,0(x)
for (signed i = BSS_CHK_LIMIT; i >= 0; i--) for (signed i = BSS_CHK_LIMIT; i >= 0; i--) {
{
upx_uint16_t op = p1[i] >> 16; upx_uint16_t op = p1[i] >> 16;
if (IS_SW_ZERO(op)) if (IS_SW_ZERO(op)) {
{
// found! get reg (x) for bss_start // found! get reg (x) for bss_start
reg = REG1(op); reg = REG1(op);
for (; i >= 0; i--) for (; i >= 0; i--) {
{ const bss_nfo *const p = ACC_CCAST(const bss_nfo *, &p1[i]);
const bss_nfo * const p = ACC_CCAST(const bss_nfo *, &p1[i]);
upx_uint16_t op1 = p->op1, op2 = p->op2; upx_uint16_t op1 = p->op1, op2 = p->op2;
// check for la (x),bss_start // check for la (x),bss_start
if ((IS_LUI(op1) && REG2(op1) == reg) && if ((IS_LUI(op1) && REG2(op1) == reg) && (IS_ADDIU(op2) && REG1(op2) == reg)) {
(IS_ADDIU(op2) && REG1(op2) == reg))
{
op1 = p->op3, op2 = p->op4; op1 = p->op3, op2 = p->op4;
// check for la (y),bss_end // check for la (y),bss_end
if (IS_LUI(op1) && IS_ADDIU(op2)) if (IS_LUI(op1) && IS_ADDIU(op2)) {
{
// bss section info found! // bss section info found!
bss_start = MIPS_IMM(p->hi1, p->lo1); bss_start = MIPS_IMM(p->hi1, p->lo1);
bss_end = MIPS_IMM(p->hi2, p->lo2); bss_end = MIPS_IMM(p->hi2, p->lo2);
if (0 < ALIGN_DOWN(bss_end - bss_start, 4u)) if (0 < ALIGN_DOWN(bss_end - bss_start, 4u)) {
{
unsigned wkmem_sz = M_IS_LZMA(ph.method) ? 32768 : 800; unsigned wkmem_sz = M_IS_LZMA(ph.method) ? 32768 : 800;
unsigned end_offs = ih.tx_ptr + fdata_size + overlap; unsigned end_offs = ih.tx_ptr + fdata_size + overlap;
if (bss_end > (end_offs + wkmem_sz)) if (bss_end > (end_offs + wkmem_sz))
@@ -458,8 +397,7 @@ bool PackPs1::findBssSection()
else else
return false; return false;
} }
} } else
else
return false; return false;
} }
} }
@@ -468,24 +406,25 @@ bool PackPs1::findBssSection()
return false; return false;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackPs1::pack(OutputFile *fo) void PackPs1::pack(OutputFile *fo) {
{
ibuf.alloc(fdata_size); ibuf.alloc(fdata_size);
obuf.allocForCompression(fdata_size); obuf.allocForCompression(fdata_size);
const upx_byte *p_scan = ibuf + fdata_size; const upx_byte *p_scan = ibuf + fdata_size;
// read file // read file
fi->seek(PS_HDR_SIZE,SEEK_SET); fi->seek(PS_HDR_SIZE, SEEK_SET);
fi->readx(ibuf,fdata_size); fi->readx(ibuf, fdata_size);
// scan EOF for 2048 bytes sector alignment // scan EOF for 2048 bytes sector alignment
// the removed space will secure in-place decompression // the removed space will secure in-place decompression
while (!(*--p_scan)) { if (sa_cnt++ > (0x10000 << 5) || sa_cnt >= fdata_size - 1024) break; } while (!(*--p_scan)) {
if (sa_cnt++ > (0x10000 << 5) || sa_cnt >= fdata_size - 1024)
break;
}
if (sa_cnt > (0x10000 << 2)) if (sa_cnt > (0x10000 << 2))
sa_cnt = ALIGN_DOWN(sa_cnt, 32u); sa_cnt = ALIGN_DOWN(sa_cnt, 32u);
@@ -498,34 +437,32 @@ void PackPs1::pack(OutputFile *fo)
Filter ft(ph.level); Filter ft(ph.level);
// compress (max_match = 65535) // compress (max_match = 65535)
upx_compress_config_t cconf; cconf.reset(); upx_compress_config_t cconf;
cconf.reset();
cconf.conf_ucl.max_match = 65535; cconf.conf_ucl.max_match = 65535;
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
compressWithFilters(&ft, sa_cnt, &cconf); compressWithFilters(&ft, sa_cnt, &cconf);
if (overlap) if (overlap) {
{
opt->info_mode += !opt->info_mode ? 1 : 0; opt->info_mode += !opt->info_mode ? 1 : 0;
infoWarning("overlap - relocating load address (+%d bytes)", overlap); infoWarning("overlap - relocating load address (+%d bytes)", overlap);
sa_cnt += overlap; sa_cnt += overlap;
} }
/* /*
if (bss_start && bss_end && !foundBss) if (bss_start && bss_end && !foundBss)
infoWarning("%s: .bss section too small - use stack", fi->getName()); infoWarning("%s: .bss section too small - use stack", fi->getName());
*/ */
unsigned lzma_init = 0; unsigned lzma_init = 0;
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method)) {
{
sz_lunc = getLoaderSize(); sz_lunc = getLoaderSize();
lzma_init = 0u - (sz_lunc - linker->getSymbolOffset("lzma.init")); lzma_init = 0u - (sz_lunc - linker->getSymbolOffset("lzma.init"));
defineDecompressorSymbols(); defineDecompressorSymbols();
linker->defineSymbol("entry", ih.epc); linker->defineSymbol("entry", ih.epc);
linker->defineSymbol("SC", linker->defineSymbol("SC", sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2);
sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2);
relocateLoader(); relocateLoader();
buildPart2 = true; buildPart2 = true;
@@ -535,15 +472,13 @@ void PackPs1::pack(OutputFile *fo)
memcpy(&oh, &ih, sizeof(ih)); memcpy(&oh, &ih, sizeof(ih));
unsigned sz_cbh; unsigned sz_cbh;
putBkupHeader((const unsigned char *)&ih.epc, (unsigned char *)&bh, &sz_cbh); putBkupHeader((const unsigned char *) &ih.epc, (unsigned char *) &bh, &sz_cbh);
if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE))) if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE)))
oh.is_ptr = (EXE_BS | (PS_RAM_SIZE - 16)); oh.is_ptr = (EXE_BS | (PS_RAM_SIZE - 16));
if (ih.da_ptr != 0 || ih.da_len != 0 || if (ih.da_ptr != 0 || ih.da_len != 0 || ih.bs_ptr != 0 || ih.bs_len != 0)
ih.bs_ptr != 0 || ih.bs_len != 0) oh.da_ptr = oh.da_len = oh.bs_ptr = oh.bs_len = 0;
oh.da_ptr = oh.da_len =
oh.bs_ptr = oh.bs_len = 0;
const int lsize = getLoaderSize(); const int lsize = getLoaderSize();
@@ -556,84 +491,71 @@ void PackPs1::pack(OutputFile *fo)
int d_len = 0; int d_len = 0;
int e_len = 0; int e_len = 0;
if (isCon) if (isCon) {
{
e_len = lsize - h_len; e_len = lsize - h_len;
d_len = e_len - getLoaderSectionStart("con.entry"); d_len = e_len - getLoaderSectionStart("con.entry");
} } else {
else const char *entry_lzma = !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma";
{
const char* entry_lzma = !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma";
d_len = (lsize - h_len) - getLoaderSectionStart(M_IS_LZMA(ph.method) ? entry_lzma : "cdb.entry"); d_len = (lsize - h_len) -
getLoaderSectionStart(M_IS_LZMA(ph.method) ? entry_lzma : "cdb.entry");
e_len = (lsize - d_len) - h_len; e_len = (lsize - d_len) - h_len;
} }
linker->defineSymbol("entry", ih.epc); linker->defineSymbol("entry", ih.epc);
linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ? linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2));
sa_cnt >> 5 : sa_cnt >> 2));
linker->defineSymbol("DECO", decomp_data_start); linker->defineSymbol("DECO", decomp_data_start);
linker->defineSymbol("ldr_sz", M_IS_LZMA(ph.method) ? sz_lunc + 16 : (d_len-pad_code)); linker->defineSymbol("ldr_sz", M_IS_LZMA(ph.method) ? sz_lunc + 16 : (d_len - pad_code));
if (foundBss) if (foundBss) {
{
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method))
linker->defineSymbol("wrkmem", bss_end - 160 - getDecompressorWrkmemSize() linker->defineSymbol("wrkmem",
- (sz_lunc + 16)); bss_end - 160 - getDecompressorWrkmemSize() - (sz_lunc + 16));
else else
linker->defineSymbol("wrkmem", bss_end - 16 - (d_len - pad_code)); linker->defineSymbol("wrkmem", bss_end - 16 - (d_len - pad_code));
} }
const unsigned entry = comp_data_start - e_len; const unsigned entry = comp_data_start - e_len;
oh.epc = oh.tx_ptr = entry; oh.epc = oh.tx_ptr = entry;
oh.tx_len = ph.c_len + e_len; oh.tx_len = ph.c_len + e_len;
unsigned pad = 0; unsigned pad = 0;
if (!opt->ps1_exe.no_align || !isCon) if (!opt->ps1_exe.no_align || !isCon) {
{
pad = oh.tx_len; pad = oh.tx_len;
oh.tx_len = ALIGN_UP(oh.tx_len, CD_SEC+0u); oh.tx_len = ALIGN_UP(oh.tx_len, CD_SEC + 0u);
pad = oh.tx_len - pad; pad = oh.tx_len - pad;
oh.tx_ptr -= pad; oh.tx_ptr -= pad;
} }
ibuf.clear(0,fdata_size); ibuf.clear(0, fdata_size);
upx_bytep paddata = ibuf; upx_bytep paddata = ibuf;
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method)) {
{
linker->defineSymbol("lzma_init_off", lzma_init); linker->defineSymbol("lzma_init_off", lzma_init);
linker->defineSymbol("gb_e", linker->getSymbolOffset("gb8_e")); linker->defineSymbol("gb_e", linker->getSymbolOffset("gb8_e"));
} } else if (isCon)
else linker->defineSymbol("gb_e", linker->getSymbolOffset(is32Bit ? "gb32_e" : "gb8_e"));
if (isCon)
linker->defineSymbol("gb_e", linker->getSymbolOffset(is32Bit ? "gb32_e" : "gb8_e"));
if (isCon) if (isCon) {
{
linker->defineSymbol("PAD", pad_code); linker->defineSymbol("PAD", pad_code);
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method))
linker->defineSymbol("DCRT", (entry + getLoaderSectionStart("lzma.exec"))); linker->defineSymbol("DCRT", (entry + getLoaderSectionStart("lzma.exec")));
else else
linker->defineSymbol("DCRT", (entry + (e_len - d_len))); linker->defineSymbol("DCRT", (entry + (e_len - d_len)));
} } else {
else
{
linker->defineSymbol("PSVR", FIX_PSVR); linker->defineSymbol("PSVR", FIX_PSVR);
linker->defineSymbol("CPDO", comp_data_start); linker->defineSymbol("CPDO", comp_data_start);
if (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method)) {
{ unsigned entry_lzma =
unsigned entry_lzma = getLoaderSectionStart( !foundBss ? "cdb.entry.lzma" : getLoaderSectionStart(!foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma");
"bss.cdb.entry.lzma");
linker->defineSymbol("lzma_cpr", getLoaderSectionStart("lzma.exec") - entry_lzma); linker->defineSymbol("lzma_cpr", getLoaderSectionStart("lzma.exec") - entry_lzma);
} }
} }
relocateLoader(); relocateLoader();
//linker->dumpSymbols(); // linker->dumpSymbols();
MemBuffer loader(lsize); MemBuffer loader(lsize);
assert(lsize == getLoaderSize()); assert(lsize == getLoaderSize());
memcpy(loader, getLoader(), lsize); memcpy(loader, getLoader(), lsize);
@@ -680,13 +602,11 @@ void PackPs1::pack(OutputFile *fo)
#endif #endif
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
int PackPs1::canUnpack() int PackPs1::canUnpack() {
{
if (!readFileHeader()) if (!readFileHeader())
return false; return false;
if (!readPackHeader(CD_SEC)) if (!readPackHeader(CD_SEC))
@@ -700,13 +620,11 @@ int PackPs1::canUnpack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackPs1::unpack(OutputFile *fo) void PackPs1::unpack(OutputFile *fo) {
{
// restore orig exec hdr // restore orig exec hdr
memcpy(&oh, &ih, sizeof(ih)); memcpy(&oh, &ih, sizeof(ih));
memcpy((void *) &oh.epc, &bh, SZ_IH_BKUP); memcpy((void *) &oh.epc, &bh, SZ_IH_BKUP);
@@ -725,8 +643,7 @@ void PackPs1::unpack(OutputFile *fo)
decompress(ibuf + (fdata_size - ph.c_len), obuf); decompress(ibuf + (fdata_size - ph.c_len), obuf);
// write decompressed file // write decompressed file
if (fo) if (fo) {
{
// write header // write header
fo->write(&oh, sizeof(oh)); fo->write(&oh, sizeof(oh));
// align the ps exe header (mode 2 sector data size) // align the ps exe header (mode 2 sector data size)
+18 -20
View File
@@ -29,18 +29,17 @@
<jssg@users.sourceforge.net> <jssg@users.sourceforge.net>
*/ */
#pragma once
#ifndef __UPX_P_PS1_H #ifndef UPX_P_PS1_H__
#define __UPX_P_PS1_H 1 #define UPX_P_PS1_H__ 1
/************************************************************************* /*************************************************************************
// ps1/exe // ps1/exe
**************************************************************************/ **************************************************************************/
class PackPs1 final : public Packer class PackPs1 final : public Packer {
{
typedef Packer super; typedef Packer super;
public: public:
PackPs1(InputFile *f); PackPs1(InputFile *f);
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
@@ -58,16 +57,16 @@ public:
protected: protected:
void putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len); void putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len);
bool getBkupHeader(unsigned char *src, unsigned char * dst); bool getBkupHeader(unsigned char *src, unsigned char *dst);
bool readBkupHeader(); bool readBkupHeader();
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
bool findBssSection(); bool findBssSection();
virtual Linker* newLinker() const override; virtual Linker *newLinker() const override;
int readFileHeader(); int readFileHeader();
bool checkFileHeader(); bool checkFileHeader();
__packed_struct(ps1_exe_t) struct alignas(1) ps1_exe_t {
// ident string // ident string
char id[8]; char id[8];
// is nullptr // is nullptr
@@ -90,26 +89,26 @@ protected:
char origin[60]; char origin[60];
// backup of the original header (epc - is_len) // backup of the original header (epc - is_len)
// id & the upx header ... // id & the upx header ...
__packed_struct_end() };
// for unpack // for unpack
__packed_struct(ps1_exe_hb_t) struct alignas(1) ps1_exe_hb_t {
LE32 ih_bkup[10]; LE32 ih_bkup[10];
// plus checksum for the backup // plus checksum for the backup
LE32 ih_csum; LE32 ih_csum;
__packed_struct_end() };
__packed_struct(ps1_exe_chb_t) struct alignas(1) ps1_exe_chb_t {
unsigned char id; unsigned char id;
unsigned char len; unsigned char len;
LE16 ih_csum; LE16 ih_csum;
unsigned char ih_bkup; unsigned char ih_bkup;
__packed_struct_end() };
__packed_struct(bss_nfo) struct alignas(1) bss_nfo {
LE16 hi1, op1, lo1, op2; LE16 hi1, op1, lo1, op2;
LE16 hi2, op3, lo2, op4; LE16 hi2, op3, lo2, op4;
__packed_struct_end() };
ps1_exe_t ih, oh; ps1_exe_t ih, oh;
ps1_exe_hb_t bh; ps1_exe_hb_t bh;
@@ -127,7 +126,6 @@ protected:
unsigned fdata_size; unsigned fdata_size;
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+15 -35
View File
@@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@@ -34,22 +33,20 @@
#include "p_sys.h" #include "p_sys.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i086-dos16.sys.h" #include "stub/i086-dos16.sys.h"
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
bool PackSys::canPack() bool PackSys::canPack() {
{
unsigned char buf[128]; unsigned char buf[128];
fi->readx(buf, sizeof(buf)); fi->readx(buf, sizeof(buf));
if (memcmp (buf,"\xff\xff\xff\xff",4) != 0) if (memcmp(buf, "\xff\xff\xff\xff", 4) != 0)
return false; return false;
if (!fn_has_ext(fi->getName(),"sys")) if (!fn_has_ext(fi->getName(), "sys"))
return false; return false;
checkAlreadyPacked(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf));
if (file_size < 1024) if (file_size < 1024)
@@ -59,15 +56,11 @@ bool PackSys::canPack()
return true; return true;
} }
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
void PackSys::patchLoader(OutputFile *fo, void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
upx_byte *loader, int lsize,
unsigned calls)
{
const int e_len = getLoaderSectionStart("SYSCUTPO"); const int e_len = getLoaderSectionStart("SYSCUTPO");
const int d_len = lsize - e_len; const int d_len = lsize - e_len;
assert(e_len > 0 && e_len < 128); assert(e_len > 0 && e_len < 128);
@@ -92,37 +85,24 @@ void PackSys::patchLoader(OutputFile *fo,
relocateLoader(); relocateLoader();
loader = getLoader(); loader = getLoader();
patchPackHeader(loader,e_len); patchPackHeader(loader, e_len);
// write loader + compressed file // write loader + compressed file
fo->write(loader,e_len); // entry fo->write(loader, e_len); // entry
fo->write(obuf,ph.c_len); fo->write(obuf, ph.c_len);
fo->write(loader+e_len,d_len); // decompressor fo->write(loader + e_len, d_len); // decompressor
} }
void PackSys::buildLoader(const Filter *ft) {
void PackSys::buildLoader(const Filter *ft)
{
initLoader(stub_i086_dos16_sys, sizeof(stub_i086_dos16_sys)); initLoader(stub_i086_dos16_sys, sizeof(stub_i086_dos16_sys));
addLoader("SYSMAIN1", addLoader("SYSMAIN1", opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861", "SYSMAIN2",
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861", ph.first_offset_found == 1 ? "SYSSBBBP" : "", ft->id ? "SYSCALLT" : "",
"SYSMAIN2",
ph.first_offset_found == 1 ? "SYSSBBBP" : "",
ft->id ? "SYSCALLT" : "",
"SYSMAIN3,UPX1HEAD,SYSCUTPO,NRV2B160,NRVDDONE,NRVDECO1", "SYSMAIN3,UPX1HEAD,SYSCUTPO,NRV2B160,NRVDDONE,NRVDECO1",
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
"NRVDECO2", if (ft->id) {
nullptr
);
if (ft->id)
{
assert(ft->calls > 0); assert(ft->calls > 0);
addFilter16(ft->id); addFilter16(ft->id);
} }
addLoader("SYSMAIN5", addLoader("SYSMAIN5", opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862", "SYSJUMP1", nullptr);
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
"SYSJUMP1",
nullptr
);
} }
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+6 -9
View File
@@ -25,24 +25,22 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_P_SYS_H #ifndef UPX_P_SYS_H__
#define __UPX_P_SYS_H 1 #define UPX_P_SYS_H__ 1
/************************************************************************* /*************************************************************************
// dos/sys // dos/sys
**************************************************************************/ **************************************************************************/
class PackSys final : public PackCom class PackSys final : public PackCom {
{
typedef PackCom super; typedef PackCom super;
public: public:
PackSys(InputFile *f) : super(f) { } PackSys(InputFile *f) : super(f) {}
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
virtual int getFormat() const override { return UPX_F_DOS_SYS; } virtual int getFormat() const override { return UPX_F_DOS_SYS; }
virtual const char *getName() const override { return "dos/sys"; } virtual const char *getName() const override { return "dos/sys"; }
//virtual const char *getFullName(const options_t *o) const override { return o && o->cpu == o->CPU_8086 ? "i086-dos16.sys" : "i286-dos16.sys"; }
virtual const char *getFullName(const options_t *) const override { return "i086-dos16.sys"; } virtual const char *getFullName(const options_t *) const override { return "i086-dos16.sys"; }
virtual bool canPack() override; virtual bool canPack() override;
@@ -55,7 +53,6 @@ protected:
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned) override; virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned) override;
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */
+287 -372
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -25,24 +25,25 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_P_WCLE_H #ifndef UPX_P_WCLE_H__
#define __UPX_P_WCLE_H 1 #define UPX_P_WCLE_H__ 1
/************************************************************************* /*************************************************************************
// watcom/le // watcom/le
**************************************************************************/ **************************************************************************/
class PackWcle final : public Packer, public LeFile class PackWcle final : public Packer, public LeFile {
{
typedef Packer super; typedef Packer super;
public: public:
PackWcle(InputFile *f) : super(f), LeFile(f) { bele = &N_BELE_RTP::le_policy; } PackWcle(InputFile *f) : super(f), LeFile(f) { bele = &N_BELE_RTP::le_policy; }
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
virtual int getFormat() const override { return UPX_F_WATCOM_LE; } virtual int getFormat() const override { return UPX_F_WATCOM_LE; }
virtual const char *getName() const override { return "watcom/le"; } virtual const char *getName() const override { return "watcom/le"; }
virtual const char *getFullName(const options_t *) const override { return "i386-dos32.watcom.le"; } virtual const char *getFullName(const options_t *) const override {
return "i386-dos32.watcom.le";
}
virtual const int *getCompressionMethods(int method, int level) const override; virtual const int *getCompressionMethods(int method, int level) const override;
virtual const int *getFilters() const override; virtual const int *getFilters() const override;
@@ -56,7 +57,7 @@ protected:
virtual void handleStub(OutputFile *fo); virtual void handleStub(OutputFile *fo);
virtual void buildLoader(const Filter *ft) override; virtual void buildLoader(const Filter *ft) override;
virtual Linker* newLinker() const override; virtual Linker *newLinker() const override;
virtual void readObjectTable() override; virtual void readObjectTable() override;
virtual void encodeObjectTable(); virtual void encodeObjectTable();
@@ -87,7 +88,6 @@ protected:
unsigned neweip; unsigned neweip;
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */