src: clang-format various packers
This commit is contained in:
+2
-1
@@ -79,7 +79,8 @@ CLANG_FORMAT_FILES += except.cpp except.h
|
||||
CLANG_FORMAT_FILES += file.cpp file.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 += 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 += ui.cpp ui.h work.cpp
|
||||
CLANG_FORMAT_FILES += $(wildcard util/[a-ln-z]*.[ch]* util/mem*.[ch]*)
|
||||
|
||||
+27
-67
@@ -25,7 +25,6 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -33,42 +32,35 @@
|
||||
#include "p_com.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i086-dos16.com.h"
|
||||
|
||||
//#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};
|
||||
#if 0
|
||||
static const int m_nrv2d[] = { M_NRV2D_LE16, M_END };
|
||||
#endif
|
||||
UNUSED(method); UNUSED(level);
|
||||
UNUSED(method);
|
||||
UNUSED(level);
|
||||
return m_nrv2b;
|
||||
}
|
||||
|
||||
|
||||
const int *PackCom::getFilters() const
|
||||
{
|
||||
static const int filters[] = {
|
||||
0x06, 0x03, 0x04, 0x01, 0x05, 0x02,
|
||||
FT_END };
|
||||
const int *PackCom::getFilters() const {
|
||||
static const int filters[] = {0x06, 0x03, 0x04, 0x01, 0x05, 0x02, FT_END};
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackCom::canPack()
|
||||
{
|
||||
bool PackCom::canPack() {
|
||||
unsigned char buf[128];
|
||||
|
||||
fi->readx(buf, sizeof(buf));
|
||||
@@ -85,15 +77,11 @@ bool PackCom::canPack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackCom::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls)
|
||||
{
|
||||
void PackCom::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
|
||||
const int e_len = getLoaderSectionStart("COMCUTPO");
|
||||
const int d_len = lsize - e_len;
|
||||
assert(e_len > 0 && e_len < 128);
|
||||
@@ -130,60 +118,40 @@ void PackCom::patchLoader(OutputFile *fo,
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PackCom::buildLoader(const Filter *ft)
|
||||
{
|
||||
void PackCom::buildLoader(const Filter *ft) {
|
||||
initLoader(stub_i086_dos16_com, sizeof(stub_i086_dos16_com));
|
||||
addLoader("COMMAIN1",
|
||||
ph.first_offset_found == 1 ? "COMSBBBP" : "",
|
||||
"COMPSHDI",
|
||||
ft->id ? "COMCALLT" : "",
|
||||
"COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160",
|
||||
ft->id ? "NRVDDONE" : "NRVDRETU",
|
||||
"NRVDECO1",
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||
"NRVDECO2",
|
||||
nullptr
|
||||
);
|
||||
if (ft->id)
|
||||
{
|
||||
addLoader("COMMAIN1", ph.first_offset_found == 1 ? "COMSBBBP" : "", "COMPSHDI",
|
||||
ft->id ? "COMCALLT" : "", "COMMAIN2,UPX1HEAD,COMCUTPO,NRV2B160",
|
||||
ft->id ? "NRVDDONE" : "NRVDRETU", "NRVDECO1",
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
|
||||
if (ft->id) {
|
||||
assert(ft->calls > 0);
|
||||
addFilter16(ft->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PackCom::addFilter16(int filter_id)
|
||||
{
|
||||
void PackCom::addFilter16(int filter_id) {
|
||||
assert(filter_id > 0);
|
||||
assert(isValidFilter(filter_id));
|
||||
|
||||
if (filter_id % 3 == 0)
|
||||
addLoader("CALLTR16",
|
||||
filter_id < 4 ? "CT16SUB0" : "",
|
||||
filter_id < 4 ? "" : (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"),
|
||||
"CALLTRI2",
|
||||
getFormat() == UPX_F_DOS_COM ? "CORETURN" : "",
|
||||
nullptr
|
||||
);
|
||||
addLoader("CALLTR16", filter_id < 4 ? "CT16SUB0" : "",
|
||||
filter_id < 4 ? ""
|
||||
: (opt->cpu == opt->CPU_8086 ? "CT16I086" : "CT16I286,CT16SUB0"),
|
||||
"CALLTRI2", getFormat() == UPX_F_DOS_COM ? "CORETURN" : "", nullptr);
|
||||
else
|
||||
addLoader(filter_id%3 == 1 ? "CT16E800" : "CT16E900",
|
||||
"CALLTRI5",
|
||||
getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2",
|
||||
filter_id < 4 ? "CT16SUB1" : "",
|
||||
addLoader(
|
||||
filter_id % 3 == 1 ? "CT16E800" : "CT16E900", "CALLTRI5",
|
||||
getFormat() == UPX_F_DOS_COM ? "CT16JEND" : "CT16JUL2", filter_id < 4 ? "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
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForCompression(file_size);
|
||||
@@ -214,13 +182,11 @@ void PackCom::pack(OutputFile *fo)
|
||||
throwNotCompressible();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackCom::canUnpack()
|
||||
{
|
||||
int PackCom::canUnpack() {
|
||||
if (!readPackHeader(128))
|
||||
return false;
|
||||
if (file_size_u <= ph.c_len)
|
||||
@@ -228,13 +194,11 @@ int PackCom::canUnpack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackCom::unpack(OutputFile *fo)
|
||||
{
|
||||
void PackCom::unpack(OutputFile *fo) {
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForDecompression(ph.u_len);
|
||||
|
||||
@@ -260,10 +224,6 @@ void PackCom::unpack(OutputFile *fo)
|
||||
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: */
|
||||
|
||||
+5
-8
@@ -25,24 +25,22 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_COM_H
|
||||
#define __UPX_P_COM_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_COM_H__
|
||||
#define UPX_P_COM_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// dos/com
|
||||
**************************************************************************/
|
||||
|
||||
class PackCom : public Packer
|
||||
{
|
||||
class PackCom : public Packer {
|
||||
typedef Packer super;
|
||||
|
||||
public:
|
||||
PackCom(InputFile *f) : super(f) { bele = &N_BELE_RTP::le_policy; }
|
||||
virtual int getVersion() const override { return 13; }
|
||||
virtual int getFormat() const override { return UPX_F_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 int *getCompressionMethods(int method, int level) const override;
|
||||
virtual const int *getFilters() const override;
|
||||
@@ -63,7 +61,6 @@ protected:
|
||||
virtual void addFilter16(int filter_id);
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+42
-102
@@ -25,7 +25,6 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -33,19 +32,16 @@
|
||||
#include "p_djgpp2.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i386-dos32.djgpp2.h"
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i386-dos32.djgpp2-stubify.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
PackDjgpp2::PackDjgpp2(InputFile *f) :
|
||||
super(f), coff_offset(0)
|
||||
{
|
||||
PackDjgpp2::PackDjgpp2(InputFile *f) : super(f), coff_offset(0) {
|
||||
bele = &N_BELE_RTP::le_policy;
|
||||
COMPILE_TIME_ASSERT(sizeof(external_scnhdr_t) == 40)
|
||||
COMPILE_TIME_ASSERT(sizeof(coff_header_t) == 0xa8)
|
||||
@@ -58,55 +54,33 @@ PackDjgpp2::PackDjgpp2(InputFile *f) :
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
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 };
|
||||
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};
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned range,
|
||||
unsigned upper_limit) const
|
||||
{
|
||||
unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf, unsigned range,
|
||||
unsigned upper_limit) const {
|
||||
unsigned o = super::findOverlapOverhead(buf, tbuf, range, upper_limit);
|
||||
o = (o + 0x3ff) & ~0x1ff;
|
||||
return o;
|
||||
}
|
||||
|
||||
Linker *PackDjgpp2::newLinker() const { return new ElfLinkerX86; }
|
||||
|
||||
Linker* PackDjgpp2::newLinker() const
|
||||
{
|
||||
return new ElfLinkerX86;
|
||||
}
|
||||
|
||||
|
||||
void PackDjgpp2::buildLoader(const Filter *ft)
|
||||
{
|
||||
void PackDjgpp2::buildLoader(const Filter *ft) {
|
||||
// prepare loader
|
||||
initLoader(stub_i386_dos32_djgpp2, sizeof(stub_i386_dos32_djgpp2));
|
||||
addLoader("IDENTSTR,DJ2MAIN1",
|
||||
ft->id ? "DJCALLT1" : "",
|
||||
addLoader("IDENTSTR,DJ2MAIN1", ft->id ? "DJCALLT1" : "",
|
||||
ph.first_offset_found == 1 ? "DJ2MAIN2" : "",
|
||||
M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "",
|
||||
getDecompressorSections(),
|
||||
M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "",
|
||||
"DJ2BSS00",
|
||||
nullptr
|
||||
);
|
||||
if (ft->id)
|
||||
{
|
||||
M_IS_LZMA(ph.method) ? "LZMA_INIT_STACK" : "", getDecompressorSections(),
|
||||
M_IS_LZMA(ph.method) ? "LZMA_DONE_STACK" : "", "DJ2BSS00", nullptr);
|
||||
if (ft->id) {
|
||||
assert(ft->calls > 0);
|
||||
addLoader("DJCALLT2", nullptr);
|
||||
addFilter32(ft->id);
|
||||
@@ -114,22 +88,16 @@ void PackDjgpp2::buildLoader(const Filter *ft)
|
||||
addLoader("DJRETURN,+40C,UPX1HEAD", nullptr);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
void PackDjgpp2::handleStub(OutputFile *fo)
|
||||
{
|
||||
if (fo && !opt->djgpp2_coff.coff)
|
||||
{
|
||||
if (coff_offset > 0)
|
||||
{
|
||||
void PackDjgpp2::handleStub(OutputFile *fo) {
|
||||
if (fo && !opt->djgpp2_coff.coff) {
|
||||
if (coff_offset > 0) {
|
||||
// copy stub from exe
|
||||
Packer::handleStub(fi, fo, coff_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// "stubify" stub
|
||||
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));
|
||||
@@ -137,9 +105,7 @@ void PackDjgpp2::handleStub(OutputFile *fo)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool is_dlm(InputFile *fi, unsigned coff_offset)
|
||||
{
|
||||
static bool is_dlm(InputFile *fi, unsigned coff_offset) {
|
||||
unsigned char buf[4];
|
||||
unsigned off;
|
||||
|
||||
@@ -158,9 +124,7 @@ static bool is_dlm(InputFile *fi, unsigned coff_offset)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||
{
|
||||
static void handle_allegropak(InputFile *fi, OutputFile *fo) {
|
||||
unsigned char b[8];
|
||||
int pfsize = 0;
|
||||
|
||||
@@ -177,8 +141,7 @@ static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||
return;
|
||||
}
|
||||
MemBuffer buf(0x4000);
|
||||
while (pfsize > 0)
|
||||
{
|
||||
while (pfsize > 0) {
|
||||
const int len = UPX_MIN(pfsize, (int) buf.getSize());
|
||||
fi->readx(buf, len);
|
||||
fo->write(buf, len);
|
||||
@@ -186,9 +149,7 @@ static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PackDjgpp2::readFileHeader()
|
||||
{
|
||||
int PackDjgpp2::readFileHeader() {
|
||||
unsigned char hdr[0x1c];
|
||||
unsigned char magic[8];
|
||||
|
||||
@@ -206,9 +167,7 @@ int PackDjgpp2::readFileHeader()
|
||||
fi->seek(coff_offset, SEEK_SET);
|
||||
if (fi->read(&coff_hdr, sizeof(coff_hdr)) != sizeof(coff_hdr))
|
||||
throwCantPack("skipping djgpp symlink");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fi->seek(coff_offset, SEEK_SET);
|
||||
fi->readx(&coff_hdr, 0xa8);
|
||||
}
|
||||
@@ -226,23 +185,19 @@ int PackDjgpp2::readFileHeader()
|
||||
return UPX_F_DJGPP2_COFF;
|
||||
}
|
||||
|
||||
|
||||
// "strip" debug info
|
||||
void PackDjgpp2::stripDebug()
|
||||
{
|
||||
void PackDjgpp2::stripDebug() {
|
||||
coff_hdr.f_symptr = 0;
|
||||
coff_hdr.f_nsyms = 0;
|
||||
coff_hdr.f_flags = 0x10f; // 0x100: "32 bit machine: LSB first"
|
||||
memset(text->misc, 0, 12);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackDjgpp2::canPack()
|
||||
{
|
||||
bool PackDjgpp2::canPack() {
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (is_dlm(fi, coff_offset))
|
||||
@@ -253,38 +208,32 @@ bool PackDjgpp2::canPack()
|
||||
throwAlreadyPacked();
|
||||
|
||||
// Check for gap in vaddr between text and data, or between data and bss.
|
||||
if (text->vaddr + text->size != data->vaddr
|
||||
|| data->vaddr + data->size != bss->vaddr)
|
||||
{
|
||||
if (text->vaddr + text->size != data->vaddr || data->vaddr + data->size != bss->vaddr) {
|
||||
// "Non-standard" layout of text,data,bss: not contiguous in vaddr.
|
||||
// But should be OK if no overlap.
|
||||
|
||||
// Check for no overlap of text and data:
|
||||
// neither by vaddr, nor by image data
|
||||
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)
|
||||
// Hack: enlarge text image data to eliminate the gap.
|
||||
text->size = coff_hdr.a_tsize = data->scnptr - text->scnptr;
|
||||
// But complain if this causes overlap in vaddr
|
||||
if (text->vaddr + text->size > data->vaddr)
|
||||
throwAlreadyPacked();
|
||||
}
|
||||
else
|
||||
} else
|
||||
throwAlreadyPacked();
|
||||
}
|
||||
// FIXME: check for Linux etc.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackDjgpp2::pack(OutputFile *fo)
|
||||
{
|
||||
void PackDjgpp2::pack(OutputFile *fo) {
|
||||
handleStub(fo);
|
||||
|
||||
// patch coff header #1: "strip" debug info
|
||||
@@ -313,7 +262,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
ft.buf_len = usize - data->size;
|
||||
ft.addvalue = text->vaddr - hdrsize;
|
||||
// compress
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
upx_compress_config_t cconf;
|
||||
cconf.reset();
|
||||
// limit stack size needed for runtime decompression
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
||||
compressWithFilters(&ft, 512, &cconf);
|
||||
@@ -331,7 +281,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
|
||||
text->scnptr = sizeof(coff_hdr);
|
||||
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;
|
||||
|
||||
linker->defineSymbol("original_entry", coff_hdr.a_entry);
|
||||
@@ -391,13 +342,11 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
throwNotCompressible();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackDjgpp2::canUnpack()
|
||||
{
|
||||
int PackDjgpp2::canUnpack() {
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (is_dlm(fi, coff_offset))
|
||||
@@ -406,13 +355,11 @@ int PackDjgpp2::canUnpack()
|
||||
return readPackHeader(4096) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackDjgpp2::unpack(OutputFile *fo)
|
||||
{
|
||||
void PackDjgpp2::unpack(OutputFile *fo) {
|
||||
handleStub(fo);
|
||||
|
||||
ibuf.alloc(ph.c_len);
|
||||
@@ -428,8 +375,7 @@ void PackDjgpp2::unpack(OutputFile *fo)
|
||||
text = chdr->sh;
|
||||
data = text + 1;
|
||||
|
||||
const unsigned hdrsize = 20 + 28
|
||||
+ sizeof(external_scnhdr_t) * chdr->f_nscns;
|
||||
const unsigned hdrsize = 20 + 28 + sizeof(external_scnhdr_t) * chdr->f_nscns;
|
||||
|
||||
unsigned addvalue;
|
||||
if (ph.version >= 14)
|
||||
@@ -438,13 +384,11 @@ void PackDjgpp2::unpack(OutputFile *fo)
|
||||
addvalue = text->vaddr & ~0x1ff; // for old versions
|
||||
|
||||
// unfilter
|
||||
if (ph.filter)
|
||||
{
|
||||
if (ph.filter) {
|
||||
Filter ft(ph.level);
|
||||
ft.init(ph.filter, addvalue);
|
||||
ft.cto = (unsigned char) ph.filter_cto;
|
||||
if (ph.version < 11)
|
||||
{
|
||||
if (ph.version < 11) {
|
||||
unsigned char ctobuf[4];
|
||||
fi->readx(ctobuf, 4);
|
||||
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);
|
||||
}
|
||||
|
||||
if (ph.version < 14)
|
||||
{
|
||||
if (ph.version < 14) {
|
||||
// fixup for the aligning bug in strip 2.8+
|
||||
text->scnptr &= 0x1ff;
|
||||
data->scnptr = text->scnptr + text->size;
|
||||
// write decompressed file
|
||||
if (fo)
|
||||
fo->write(obuf, ph.u_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// write the header
|
||||
// some padding might be required between the end
|
||||
// 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;
|
||||
ibuf.clear(0, padding);
|
||||
|
||||
if (fo)
|
||||
{
|
||||
if (fo) {
|
||||
fo->write(obuf, hdrsize);
|
||||
fo->write(ibuf, padding);
|
||||
fo->write(obuf + hdrsize, ph.u_len - hdrsize);
|
||||
|
||||
+12
-14
@@ -25,17 +25,15 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_DJGPP2_H
|
||||
#define __UPX_P_DJGPP2_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_DJGPP2_H__
|
||||
#define UPX_P_DJGPP2_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// djgpp2/coff
|
||||
**************************************************************************/
|
||||
|
||||
class PackDjgpp2 final : public Packer
|
||||
{
|
||||
class PackDjgpp2 final : public Packer {
|
||||
typedef Packer super;
|
||||
|
||||
public:
|
||||
@@ -43,7 +41,9 @@ public:
|
||||
virtual int getVersion() const override { return 14; }
|
||||
virtual int getFormat() const override { return UPX_F_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 *getFilters() const override;
|
||||
|
||||
@@ -57,8 +57,7 @@ protected:
|
||||
void handleStub(OutputFile *fo);
|
||||
int readFileHeader();
|
||||
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf, const upx_bytep tbuf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const override;
|
||||
virtual void buildLoader(const Filter *ft) override;
|
||||
@@ -66,16 +65,16 @@ protected:
|
||||
|
||||
unsigned coff_offset;
|
||||
|
||||
__packed_struct(external_scnhdr_t)
|
||||
struct alignas(1) external_scnhdr_t {
|
||||
char _[12]; // name, paddr
|
||||
LE32 vaddr;
|
||||
LE32 size;
|
||||
LE32 scnptr;
|
||||
char misc[12]; // relptr, lnnoptr, nreloc, nlnno
|
||||
char __[4]; // flags
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
__packed_struct(coff_header_t)
|
||||
struct alignas(1) coff_header_t {
|
||||
// ext_file_hdr
|
||||
LE16 f_magic;
|
||||
LE16 f_nscns;
|
||||
@@ -96,7 +95,7 @@ protected:
|
||||
|
||||
// section headers
|
||||
external_scnhdr_t sh[3];
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
coff_header_t coff_hdr;
|
||||
external_scnhdr_t *text, *data, *bss;
|
||||
@@ -104,7 +103,6 @@ protected:
|
||||
void stripDebug();
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+102
-205
@@ -25,7 +25,6 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -33,7 +32,7 @@
|
||||
#include "p_exe.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i086-dos16.exe.h"
|
||||
|
||||
#define RSFCRI 4096 // Reserved Space For Compressed Relocation Info
|
||||
@@ -42,14 +41,11 @@ static const
|
||||
|
||||
#define DI_LIMIT 0xff00 // see the assembly why
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
PackExe::PackExe(InputFile *f) :
|
||||
super(f)
|
||||
{
|
||||
PackExe::PackExe(InputFile *f) : super(f) {
|
||||
bele = &N_BELE_RTP::le_policy;
|
||||
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 32)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(exe_header_t)
|
||||
@@ -58,9 +54,7 @@ PackExe::PackExe(InputFile *f) :
|
||||
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;
|
||||
// disable lzma for "--brute" unless explicitly given "--lzma"
|
||||
// WARNING: this side effect may persists for later files;
|
||||
@@ -70,15 +64,9 @@ const int *PackExe::getCompressionMethods(int method, int level) const
|
||||
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||
}
|
||||
|
||||
const int *PackExe::getFilters() const { return nullptr; }
|
||||
|
||||
const int *PackExe::getFilters() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
int PackExe::fillExeHeader(struct exe_header_t *eh) const
|
||||
{
|
||||
int PackExe::fillExeHeader(struct exe_header_t *eh) const {
|
||||
#define oh (*eh)
|
||||
// fill new exe header
|
||||
int flag = 0;
|
||||
@@ -106,8 +94,7 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
|
||||
oh.ss = ph.c_len / 16 + destpara;
|
||||
if (ih.ss * 16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200)
|
||||
oh.ss = ih.ss;
|
||||
if (oh.ss*16 + 0x50 < ih.ss*16 + ih.sp
|
||||
&& oh.ss*16 + 0x200 > 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 += 0x20;
|
||||
|
||||
if (oh.ss != ih.ss)
|
||||
@@ -118,58 +105,38 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
|
||||
#undef oh
|
||||
}
|
||||
|
||||
void PackExe::addLoaderEpilogue(int flag)
|
||||
{
|
||||
void PackExe::addLoaderEpilogue(int flag) {
|
||||
addLoader("EXEMAIN5", nullptr);
|
||||
if (relocsize)
|
||||
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ" : "EXEADJUS",
|
||||
"EXERELO1",
|
||||
has_9a ? "EXEREL9A" : "",
|
||||
"EXERELO2",
|
||||
ih_exesize > 0xFE00 ? "EXEREBIG" : "",
|
||||
"EXERELO3",
|
||||
nullptr
|
||||
);
|
||||
addLoader("EXEMAIN8",
|
||||
device_driver ? "DEVICEEND" : "",
|
||||
(flag & SS) ? "EXESTACK" : "",
|
||||
(flag & SP) ? "EXESTASP" : "",
|
||||
(flag & USEJUMP) ? "EXEJUMPF" : "",
|
||||
nullptr
|
||||
);
|
||||
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ"
|
||||
: "EXEADJUS",
|
||||
"EXERELO1", has_9a ? "EXEREL9A" : "", "EXERELO2",
|
||||
ih_exesize > 0xFE00 ? "EXEREBIG" : "", "EXERELO3", nullptr);
|
||||
addLoader("EXEMAIN8", device_driver ? "DEVICEEND" : "", (flag & SS) ? "EXESTACK" : "",
|
||||
(flag & SP) ? "EXESTASP" : "", (flag & USEJUMP) ? "EXEJUMPF" : "", nullptr);
|
||||
if (!(flag & USEJUMP))
|
||||
addLoader(ih.cs ? "EXERCSPO" : "",
|
||||
"EXERETIP",
|
||||
nullptr
|
||||
);
|
||||
addLoader(ih.cs ? "EXERCSPO" : "", "EXERETIP", nullptr);
|
||||
|
||||
linker->defineSymbol("original_cs", ih.cs);
|
||||
linker->defineSymbol("original_ip", ih.ip);
|
||||
linker->defineSymbol("original_sp", ih.sp);
|
||||
linker->defineSymbol("original_ss", ih.ss);
|
||||
linker->defineSymbol("reloc_size",
|
||||
(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff)
|
||||
>= relocsize ? 0 : MAXRELOCS) - relocsize);
|
||||
linker->defineSymbol(
|
||||
"reloc_size",
|
||||
(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
|
||||
exe_header_t dummy_oh;
|
||||
int flag = fillExeHeader(&dummy_oh);
|
||||
|
||||
initLoader(stub_i086_dos16_exe, sizeof(stub_i086_dos16_exe));
|
||||
|
||||
if (M_IS_LZMA(ph.method))
|
||||
{
|
||||
addLoader("LZMA_DEC00",
|
||||
opt->small ? "LZMA_DEC10" : "LZMA_DEC20",
|
||||
"LZMA_DEC30",
|
||||
use_clear_dirty_stack ? "LZMA_DEC31" : "",
|
||||
"LZMA_DEC32",
|
||||
ph.u_len > 0xffff ? "LZMA_DEC33" : "",
|
||||
nullptr
|
||||
);
|
||||
if (M_IS_LZMA(ph.method)) {
|
||||
addLoader("LZMA_DEC00", opt->small ? "LZMA_DEC10" : "LZMA_DEC20", "LZMA_DEC30",
|
||||
use_clear_dirty_stack ? "LZMA_DEC31" : "", "LZMA_DEC32",
|
||||
ph.u_len > 0xffff ? "LZMA_DEC33" : "", nullptr);
|
||||
|
||||
addLoaderEpilogue(flag);
|
||||
defineDecompressorSymbols();
|
||||
@@ -196,9 +163,10 @@ void PackExe::buildLoader(const Filter *)
|
||||
MemBuffer compressed_lzma;
|
||||
compressed_lzma.allocForCompression(lsize);
|
||||
unsigned c_len_lzma = MemBuffer::getSizeForCompression(lsize);
|
||||
int r = upx_compress(loader, lsize, compressed_lzma, &c_len_lzma,
|
||||
nullptr, M_NRV2B_LE16, 9, nullptr, nullptr);
|
||||
assert(r == UPX_E_OK); assert(c_len_lzma < lsize);
|
||||
int r = upx_compress(loader, lsize, compressed_lzma, &c_len_lzma, nullptr, M_NRV2B_LE16, 9,
|
||||
nullptr, nullptr);
|
||||
assert(r == UPX_E_OK);
|
||||
assert(c_len_lzma < lsize);
|
||||
|
||||
info("lzma+relocator code compressed: %u -> %u", lsize, c_len_lzma);
|
||||
// reinit the loader
|
||||
@@ -208,60 +176,32 @@ void PackExe::buildLoader(const Filter *)
|
||||
addLoader("DEVICEENTRY,LZMADEVICE,DEVICEENTRY2", nullptr);
|
||||
|
||||
linker->addSection("COMPRESSED_LZMA", compressed_lzma, c_len_lzma, 0);
|
||||
addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2",
|
||||
nullptr);
|
||||
addLoader("LZMAENTRY,NRV2B160,NRVDDONE,NRVDECO1,NRVGTD00,NRVDECO2", nullptr);
|
||||
|
||||
}
|
||||
else if (device_driver)
|
||||
} else if (device_driver)
|
||||
addLoader("DEVICEENTRY,DEVICEENTRY2", nullptr);
|
||||
|
||||
addLoader("EXEENTRY",
|
||||
M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB",
|
||||
"JNCDOCOPY",
|
||||
relocsize ? "EXERELPU" : "",
|
||||
"EXEMAIN4",
|
||||
M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B",
|
||||
"EXEMAIN4C",
|
||||
addLoader("EXEENTRY", M_IS_LZMA(ph.method) && device_driver ? "LONGSUB" : "SHORTSUB",
|
||||
"JNCDOCOPY", relocsize ? "EXERELPU" : "", "EXEMAIN4",
|
||||
M_IS_LZMA(ph.method) ? "" : "EXEMAIN4B", "EXEMAIN4C",
|
||||
M_IS_LZMA(ph.method) ? "COMPRESSED_LZMA_START,COMPRESSED_LZMA" : "",
|
||||
"+G5DXXXX,UPX1HEAD,EXECUTPO",
|
||||
nullptr
|
||||
);
|
||||
"+G5DXXXX,UPX1HEAD,EXECUTPO", nullptr);
|
||||
if (ph.method == M_NRV2B_8)
|
||||
addLoader("NRV2B16S", // decompressor
|
||||
ph.u_len > DI_LIMIT ? "N2B64K01" : "",
|
||||
"NRV2BEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601",
|
||||
"NRV2BEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602",
|
||||
"NRV2BEX3",
|
||||
ph.c_len > 0xffff ? "N2B64K02" : "",
|
||||
"NRV2BEX9",
|
||||
nullptr
|
||||
);
|
||||
ph.u_len > DI_LIMIT ? "N2B64K01" : "", "NRV2BEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601", "NRV2BEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602", "NRV2BEX3",
|
||||
ph.c_len > 0xffff ? "N2B64K02" : "", "NRV2BEX9", nullptr);
|
||||
else if (ph.method == M_NRV2D_8)
|
||||
addLoader("NRV2D16S",
|
||||
ph.u_len > DI_LIMIT ? "N2D64K01" : "",
|
||||
"NRV2DEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601",
|
||||
"NRV2DEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602",
|
||||
"NRV2DEX3",
|
||||
ph.c_len > 0xffff ? "N2D64K02" : "",
|
||||
"NRV2DEX9",
|
||||
nullptr
|
||||
);
|
||||
addLoader("NRV2D16S", ph.u_len > DI_LIMIT ? "N2D64K01" : "", "NRV2DEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601", "NRV2DEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602", "NRV2DEX3",
|
||||
ph.c_len > 0xffff ? "N2D64K02" : "", "NRV2DEX9", nullptr);
|
||||
else if (ph.method == M_NRV2E_8)
|
||||
addLoader("NRV2E16S",
|
||||
ph.u_len > DI_LIMIT ? "N2E64K01" : "",
|
||||
"NRV2EEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601",
|
||||
"NRV2EEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602",
|
||||
"NRV2EEX3",
|
||||
ph.c_len > 0xffff ? "N2E64K02" : "",
|
||||
"NRV2EEX9",
|
||||
nullptr
|
||||
);
|
||||
addLoader("NRV2E16S", ph.u_len > DI_LIMIT ? "N2E64K01" : "", "NRV2EEX1",
|
||||
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601", "NRV2EEX2",
|
||||
opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602", "NRV2EEX3",
|
||||
ph.c_len > 0xffff ? "N2E64K02" : "", "NRV2EEX9", nullptr);
|
||||
else if M_IS_LZMA (ph.method)
|
||||
return;
|
||||
else
|
||||
@@ -270,13 +210,11 @@ void PackExe::buildLoader(const Filter *)
|
||||
addLoaderEpilogue(flag);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackExe::readFileHeader()
|
||||
{
|
||||
int PackExe::readFileHeader() {
|
||||
ih_exesize = ih_imagesize = ih_overlay = 0;
|
||||
fi->readx(&ih, sizeof(ih));
|
||||
if (ih.ident != 'M' + 'Z' * 256 && ih.ident != 'Z' + 'M' * 256)
|
||||
@@ -287,8 +225,7 @@ int PackExe::readFileHeader()
|
||||
}
|
||||
ih_imagesize = ih_exesize - ih.headsize16 * 16;
|
||||
ih_overlay = file_size - ih_exesize;
|
||||
if (file_size_u < sizeof(ih)
|
||||
|| ((ih.m512 | ih.p512) && ih.m512+ih.p512*512u < sizeof (ih)))
|
||||
if (file_size_u < sizeof(ih) || ((ih.m512 | ih.p512) && ih.m512 + ih.p512 * 512u < sizeof(ih)))
|
||||
throwCantPack("illegal exe header");
|
||||
if (file_size_u < ih_exesize || ih_imagesize <= 0 || ih_imagesize > ih_exesize)
|
||||
throwCantPack("exe header corrupted");
|
||||
@@ -298,9 +235,7 @@ int PackExe::readFileHeader()
|
||||
return UPX_F_DOS_EXE;
|
||||
}
|
||||
|
||||
|
||||
bool PackExe::canPack()
|
||||
{
|
||||
bool PackExe::canPack() {
|
||||
if (fn_has_ext(fi->getName(), "sys"))
|
||||
return false;
|
||||
if (!readFileHeader())
|
||||
@@ -310,8 +245,7 @@ bool PackExe::canPack()
|
||||
fi->seek(0x3c, SEEK_SET);
|
||||
LE32 offs;
|
||||
fi->readx(&offs, sizeof(offs));
|
||||
if (ih.relocoffs >= 0x40 && offs)
|
||||
{
|
||||
if (ih.relocoffs >= 0x40 && offs) {
|
||||
if (opt->dos_exe.force_stub)
|
||||
opt->overlay = opt->COPY_OVERLAY;
|
||||
else
|
||||
@@ -320,16 +254,12 @@ bool PackExe::canPack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static
|
||||
unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
const upx_byte *relocs, const unsigned nrelocs,
|
||||
upx_byte *crel, bool *has_9a)
|
||||
{
|
||||
static unsigned optimize_relocs(upx_byte *b, const unsigned size, const upx_byte *relocs,
|
||||
const unsigned nrelocs, upx_byte *crel, bool *has_9a) {
|
||||
if (opt->exact)
|
||||
throwCantPackExact();
|
||||
|
||||
@@ -345,13 +275,11 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
#endif
|
||||
|
||||
// pass 1 - find 0x9a bounds
|
||||
for (i = 0; i < nrelocs; i++)
|
||||
{
|
||||
for (i = 0; i < nrelocs; i++) {
|
||||
unsigned addr = get_le32(relocs + 4 * i);
|
||||
if (addr >= size - 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);
|
||||
if (seg > seg_high)
|
||||
seg_high = seg;
|
||||
@@ -375,7 +303,6 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
// printf("%d %d\n", off_low, off_high);
|
||||
// printf("%d %d\n", linear_low, linear_high);
|
||||
|
||||
|
||||
// pass 2 - reloc
|
||||
|
||||
crel += 4; // to be filled in later
|
||||
@@ -383,22 +310,17 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
unsigned ones = 0;
|
||||
unsigned es = 0, di, t;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
do {
|
||||
unsigned addr = get_le32(relocs + 4 * i);
|
||||
set_le16(crel, di = addr & 0x0f);
|
||||
set_le16(crel + 2, (addr >> 4) - es);
|
||||
es = addr >> 4;
|
||||
crel += 4;
|
||||
|
||||
for (++i; i < nrelocs; i++)
|
||||
{
|
||||
for (++i; i < nrelocs; i++) {
|
||||
addr = get_le32(relocs + 4 * i);
|
||||
// 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
|
||||
t = 1 + (0xffff - di) / 254;
|
||||
memset(crel, 1, t);
|
||||
@@ -407,13 +329,11 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
break;
|
||||
}
|
||||
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++)
|
||||
if (b[es * 16 + t] == 0x9a && get_le16(b + es * 16 + t + 3) <= seg_high)
|
||||
break;
|
||||
if (t == offs-3)
|
||||
{
|
||||
if (t == offs - 3) {
|
||||
// code 0: search for 0x9a
|
||||
*crel++ = 0;
|
||||
di = offs;
|
||||
@@ -425,8 +345,7 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
if (t < 2)
|
||||
throwCantPack("unexpected relocation 2");
|
||||
|
||||
while (t >= 256)
|
||||
{
|
||||
while (t >= 256) {
|
||||
// code 1: add 254, don't reloc
|
||||
*crel++ = 1;
|
||||
t -= 254;
|
||||
@@ -445,13 +364,11 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
return (unsigned) (crel - crel_save);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackExe::pack(OutputFile *fo)
|
||||
{
|
||||
void PackExe::pack(OutputFile *fo) {
|
||||
unsigned ic;
|
||||
|
||||
if (ih.relocs > MAXRELOCS)
|
||||
@@ -474,15 +391,13 @@ void PackExe::pack(OutputFile *fo)
|
||||
// relocations
|
||||
has_9a = false;
|
||||
upx_byte *w = ibuf + ih_imagesize;
|
||||
if (ih.relocs)
|
||||
{
|
||||
if (ih.relocs) {
|
||||
upx_byte *wr = w + RSFCRI;
|
||||
|
||||
fi->seek(ih.relocoffs, SEEK_SET);
|
||||
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);
|
||||
set_le32(wr + 4 * ic, ((jc >> 16) * 16 + (jc & 0xffff)) & 0xfffff);
|
||||
}
|
||||
@@ -499,9 +414,7 @@ void PackExe::pack(OutputFile *fo)
|
||||
ucl_nrv2b_99_compress(w, in_len, out, &out_len, nullptr, 9, nullptr, nullptr);
|
||||
printf("reloc compress: %d -> %d\n", in_len, out_len);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
relocsize = 0;
|
||||
}
|
||||
|
||||
@@ -510,7 +423,8 @@ void PackExe::pack(OutputFile *fo)
|
||||
// prepare filter
|
||||
Filter ft(ph.level);
|
||||
// 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_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
||||
compressWithFilters(&ft, 32, &cconf);
|
||||
@@ -520,12 +434,10 @@ void PackExe::pack(OutputFile *fo)
|
||||
throwCantPack("decompressor limit exceeded, send a bugreport");
|
||||
|
||||
#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("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n",
|
||||
0/*ph.min_offset_found*/,ph.max_offset_found,
|
||||
0/*ph.min_match_found*/,ph.max_match_found,
|
||||
printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n", 0 /*ph.min_offset_found*/,
|
||||
ph.max_offset_found, 0 /*ph.min_match_found*/, ph.max_match_found,
|
||||
0 /*ph.min_run_found*/, ph.max_run_found);
|
||||
}
|
||||
#endif
|
||||
@@ -557,26 +469,22 @@ void PackExe::pack(OutputFile *fo)
|
||||
// set extra info
|
||||
unsigned char extra_info[9];
|
||||
unsigned eisize = 0;
|
||||
if (oh.ss != ih.ss)
|
||||
{
|
||||
if (oh.ss != ih.ss) {
|
||||
set_le16(extra_info + eisize, ih.ss);
|
||||
eisize += 2;
|
||||
assert((flag & SS) != 0); // set in fillExeHeader()
|
||||
}
|
||||
if (oh.sp != ih.sp)
|
||||
{
|
||||
if (oh.sp != ih.sp) {
|
||||
set_le16(extra_info + eisize, ih.sp);
|
||||
eisize += 2;
|
||||
assert((flag & SP) != 0); // set in fillExeHeader()
|
||||
}
|
||||
if (ih.min != oh.min)
|
||||
{
|
||||
if (ih.min != oh.min) {
|
||||
set_le16(extra_info + eisize, ih.min);
|
||||
eisize += 2;
|
||||
flag |= MINMEM;
|
||||
}
|
||||
if (ih.max != oh.max)
|
||||
{
|
||||
if (ih.max != oh.max) {
|
||||
set_le16(extra_info + eisize, ih.max);
|
||||
eisize += 2;
|
||||
flag |= MAXMEM;
|
||||
@@ -592,16 +500,13 @@ void PackExe::pack(OutputFile *fo)
|
||||
linker->defineSymbol("decompressor_entry", decompressor_entry);
|
||||
|
||||
// patch loader
|
||||
if (flag & USEJUMP)
|
||||
{
|
||||
if (flag & USEJUMP) {
|
||||
// I use a relocation entry to set the original cs
|
||||
unsigned n = getLoaderSectionStart("EXEJUMPF") + 1;
|
||||
n += packedsize + 2;
|
||||
oh.relocs = 1;
|
||||
oh.firstreloc = (n & 0xf) + ((n >> 4) << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
oh.relocs = 0;
|
||||
oh.firstreloc = ih.cs * 0x10000 + ih.ip;
|
||||
}
|
||||
@@ -633,7 +538,8 @@ void PackExe::pack(OutputFile *fo)
|
||||
memcpy(loader, getLoader(), lsize);
|
||||
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
|
||||
#if TESTING
|
||||
@@ -666,13 +572,11 @@ void PackExe::pack(OutputFile *fo)
|
||||
throwNotCompressible();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackExe::canUnpack()
|
||||
{
|
||||
int PackExe::canUnpack() {
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
const unsigned off = ih.headsize16 * 16;
|
||||
@@ -681,13 +585,11 @@ int PackExe::canUnpack()
|
||||
return b && (off + ph.c_len <= file_size_u);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackExe::unpack(OutputFile *fo)
|
||||
{
|
||||
void PackExe::unpack(OutputFile *fo) {
|
||||
ibuf.alloc(file_size);
|
||||
obuf.allocForDecompression(ph.u_len);
|
||||
|
||||
@@ -713,8 +615,7 @@ void PackExe::unpack(OutputFile *fo)
|
||||
SPAN_S_VAR(upx_byte, relocs, obuf + ph.u_len, obuf);
|
||||
|
||||
MemBuffer wrkmem;
|
||||
if (!(flag & NORELOC))
|
||||
{
|
||||
if (!(flag & NORELOC)) {
|
||||
relocs -= get_le16(obuf + ph.u_len - 2);
|
||||
ph.u_len -= 2;
|
||||
|
||||
@@ -723,36 +624,29 @@ void PackExe::unpack(OutputFile *fo)
|
||||
const unsigned seghi = get_le16(relocs + 2);
|
||||
SPAN_S_VAR(const upx_byte, p, relocs + 4);
|
||||
|
||||
while (ones)
|
||||
{
|
||||
while (ones) {
|
||||
unsigned di = get_le16(p);
|
||||
es += get_le16(p + 2);
|
||||
bool dorel = true;
|
||||
for (p += 4; ones && di < 0x10000; p++)
|
||||
{
|
||||
if (dorel)
|
||||
{
|
||||
for (p += 4; ones && di < 0x10000; p++) {
|
||||
if (dorel) {
|
||||
set_le16(wrkmem + 4 * relocn, di);
|
||||
set_le16(wrkmem + 2 + 4 * relocn++, es);
|
||||
// printf ("%x\n",es*16+di);
|
||||
}
|
||||
dorel = true;
|
||||
if (*p == 0)
|
||||
{
|
||||
if (*p == 0) {
|
||||
SPAN_S_VAR(const upx_byte, q, obuf);
|
||||
|
||||
for (q = obuf + es * 16 + di; !(*q == 0x9a && get_le16(q + 3) <= seghi); q++)
|
||||
;
|
||||
di = ptr_diff_bytes(q, obuf + es * 16) + 3;
|
||||
}
|
||||
else if (*p == 1)
|
||||
{
|
||||
} else if (*p == 1) {
|
||||
di += 254;
|
||||
if (di < 0x10000)
|
||||
ones--;
|
||||
dorel = false;
|
||||
}
|
||||
else
|
||||
} else
|
||||
di += *p;
|
||||
}
|
||||
}
|
||||
@@ -762,8 +656,7 @@ void PackExe::unpack(OutputFile *fo)
|
||||
memset(&oh, 0, sizeof(oh));
|
||||
oh.ident = 'M' + 'Z' * 256;
|
||||
|
||||
if (relocn)
|
||||
{
|
||||
if (relocn) {
|
||||
oh.relocs = relocn;
|
||||
while (relocn & 3)
|
||||
set_le32(wrkmem + 4 * relocn++, 0);
|
||||
@@ -779,14 +672,22 @@ void PackExe::unpack(OutputFile *fo)
|
||||
oh.sp = ih.sp;
|
||||
oh.ss = ih.ss;
|
||||
|
||||
if (flag & MAXMEM)
|
||||
{ imagesize -= 2; oh.max = get_le16(ibuf+imagesize); }
|
||||
if (flag & MINMEM)
|
||||
{ imagesize -= 2; oh.min = 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); }
|
||||
if (flag & MAXMEM) {
|
||||
imagesize -= 2;
|
||||
oh.max = get_le16(ibuf + imagesize);
|
||||
}
|
||||
if (flag & MINMEM) {
|
||||
imagesize -= 2;
|
||||
oh.min = 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;
|
||||
oh.ip = ip & 0xffff;
|
||||
@@ -807,11 +708,7 @@ void PackExe::unpack(OutputFile *fo)
|
||||
copyOverlay(fo, ih_overlay, obuf);
|
||||
}
|
||||
|
||||
|
||||
Linker* PackExe::newLinker() const
|
||||
{
|
||||
return new ElfLinkerX86();
|
||||
}
|
||||
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
|
||||
|
||||
/*
|
||||
|
||||
|
||||
+10
-22
@@ -25,24 +25,22 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_EXE_H
|
||||
#define __UPX_P_EXE_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_EXE_H__
|
||||
#define UPX_P_EXE_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// dos/exe
|
||||
**************************************************************************/
|
||||
|
||||
class PackExe final : public Packer
|
||||
{
|
||||
class PackExe final : public Packer {
|
||||
typedef Packer super;
|
||||
|
||||
public:
|
||||
PackExe(InputFile *f);
|
||||
virtual int getVersion() const override { return 13; }
|
||||
virtual int getFormat() const override { return UPX_F_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 int *getCompressionMethods(int method, int level) const override;
|
||||
virtual const int *getFilters() const override;
|
||||
@@ -54,13 +52,11 @@ public:
|
||||
virtual int canUnpack() override;
|
||||
|
||||
// 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)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -74,7 +70,7 @@ protected:
|
||||
virtual Linker *newLinker() const override;
|
||||
void addLoaderEpilogue(int flag);
|
||||
|
||||
__packed_struct(exe_header_t)
|
||||
struct alignas(1) exe_header_t {
|
||||
LE16 ident;
|
||||
LE16 m512;
|
||||
LE16 p512;
|
||||
@@ -90,7 +86,7 @@ protected:
|
||||
LE16 relocoffs;
|
||||
char __[2]; // overlnum
|
||||
LE32 firstreloc;
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
exe_header_t ih, oh;
|
||||
|
||||
@@ -102,20 +98,12 @@ protected:
|
||||
bool has_9a;
|
||||
bool device_driver;
|
||||
|
||||
enum {
|
||||
NORELOC = 1,
|
||||
USEJUMP = 2,
|
||||
SS = 4,
|
||||
SP = 8,
|
||||
MINMEM = 16,
|
||||
MAXMEM = 32
|
||||
};
|
||||
enum { NORELOC = 1, USEJUMP = 2, SS = 4, SP = 8, MINMEM = 16, MAXMEM = 32 };
|
||||
|
||||
unsigned stack_for_lzma; // stack size required for lzma
|
||||
bool use_clear_dirty_stack;
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+104
-187
@@ -29,7 +29,6 @@
|
||||
<jssg@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -37,7 +36,7 @@
|
||||
#include "p_ps1.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/mipsel.r3000-ps1.h"
|
||||
|
||||
#define CD_SEC 2048
|
||||
@@ -61,7 +60,6 @@ static const
|
||||
#define MIPS_PC16(a) ((a) >> 2)
|
||||
#define MIPS_PC26(a) (((a) &0x0fffffff) >> 2)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// ps1 exe looks like this:
|
||||
// 1. <header> 2048 bytes
|
||||
@@ -76,12 +74,10 @@ static const
|
||||
// optional: not aligned to 2048 (for console run only)
|
||||
**************************************************************************/
|
||||
|
||||
PackPs1::PackPs1(InputFile *f) :
|
||||
super(f),
|
||||
isCon(!opt->ps1_exe.boot_only), is32Bit(!opt->ps1_exe.do_8bit),
|
||||
buildPart2(0), foundBss(0), sa_cnt(0), overlap(0), sz_lunc(0), sz_lcpr(0),
|
||||
pad_code(0), bss_start(0), bss_end(0)
|
||||
{
|
||||
PackPs1::PackPs1(InputFile *f)
|
||||
: super(f), isCon(!opt->ps1_exe.boot_only), is32Bit(!opt->ps1_exe.do_8bit), buildPart2(0),
|
||||
foundBss(0), sa_cnt(0), overlap(0), sz_lunc(0), sz_lcpr(0), pad_code(0), bss_start(0),
|
||||
bss_end(0) {
|
||||
bele = &N_BELE_RTP::le_policy;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const int *PackPs1::getCompressionMethods(int method, int level) const
|
||||
{
|
||||
const int *PackPs1::getCompressionMethods(int method, int level) const {
|
||||
if (is32Bit)
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
else
|
||||
return Packer::getDefaultCompressionMethods_8(method, level);
|
||||
}
|
||||
|
||||
const int *PackPs1::getFilters() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Linker* PackPs1::newLinker() const
|
||||
{
|
||||
return new ElfLinkerMipsLE;
|
||||
}
|
||||
const int *PackPs1::getFilters() const { return nullptr; }
|
||||
|
||||
Linker *PackPs1::newLinker() const { return new ElfLinkerMipsLE; }
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
@@ -123,25 +111,21 @@ Linker* PackPs1::newLinker() const
|
||||
// checkFileHeader() checks ih for legal but unsupported values
|
||||
**************************************************************************/
|
||||
|
||||
int PackPs1::readFileHeader()
|
||||
{
|
||||
int PackPs1::readFileHeader() {
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(&ih, sizeof(ih));
|
||||
if (memcmp(&ih.id[0], "PS-X EXE", 8) != 0 &&
|
||||
memcmp(&ih.id[0], "EXE X-SP", 8) != 0)
|
||||
if (memcmp(&ih.id[0], "PS-X EXE", 8) != 0 && memcmp(&ih.id[0], "EXE X-SP", 8) != 0)
|
||||
return 0;
|
||||
if (ih.text != 0 || ih.data != 0)
|
||||
return 0;
|
||||
return UPX_F_PS1_EXE;
|
||||
}
|
||||
|
||||
bool PackPs1::readBkupHeader()
|
||||
{
|
||||
bool PackPs1::readBkupHeader() {
|
||||
fi->seek(sizeof(ps1_exe_t) + 8, SEEK_SET);
|
||||
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)];
|
||||
fi->seek(sizeof(ps1_exe_t), SEEK_SET);
|
||||
fi->readx(buf, sizeof(bh));
|
||||
@@ -151,22 +135,26 @@ bool PackPs1::readBkupHeader()
|
||||
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) \
|
||||
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);
|
||||
|
||||
if (src && dst)
|
||||
{
|
||||
if (src && dst) {
|
||||
unsigned char *cpr_bh = New(unsigned char, sz_cbh);
|
||||
|
||||
memset(cpr_bh, 0, sizeof(bh));
|
||||
ps1_exe_chb_t *p = (ps1_exe_chb_t *) cpr_bh;
|
||||
|
||||
int r = upx_compress(src, SZ_IH_BKUP,
|
||||
&p->ih_bkup, &sz_cbh, nullptr, M_NRV2E_8, 10, nullptr, nullptr );
|
||||
int r = upx_compress(src, SZ_IH_BKUP, &p->ih_bkup, &sz_cbh, nullptr, M_NRV2E_8, 10, nullptr,
|
||||
nullptr);
|
||||
if (r != UPX_E_OK || sz_cbh >= SZ_IH_BKUP)
|
||||
throwInternalError("header compression failed");
|
||||
INIT_BH_BKUP(p, sz_cbh);
|
||||
@@ -174,8 +162,7 @@ void PackPs1::putBkupHeader(const unsigned char *src, unsigned char *dst, unsign
|
||||
p->ih_csum = ADLER16(upx_adler32(&ih.epc, SZ_IH_BKUP));
|
||||
memcpy(dst, cpr_bh, SZ_IH_BKUP);
|
||||
delete[] cpr_bh;
|
||||
}
|
||||
else
|
||||
} else
|
||||
throwInternalError("header compression failed");
|
||||
}
|
||||
|
||||
@@ -183,17 +170,15 @@ void PackPs1::putBkupHeader(const unsigned char *src, unsigned char *dst, unsign
|
||||
#define ADLER16_LO(a, b) (((a) >> 16) ^ (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;
|
||||
|
||||
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 sz_bh = SZ_IH_BKUP;
|
||||
int r = upx_decompress((const unsigned char *)&src->ih_bkup, src->len,
|
||||
unc_bh, &sz_bh, M_NRV2E_8, nullptr );
|
||||
int r = upx_decompress((const unsigned char *) &src->ih_bkup, src->len, unc_bh, &sz_bh,
|
||||
M_NRV2E_8, nullptr);
|
||||
if (r == UPX_E_OUT_OF_MEMORY)
|
||||
throwOutOfMemoryException();
|
||||
if (r != UPX_E_OK || sz_bh != SZ_IH_BKUP)
|
||||
@@ -204,35 +189,27 @@ bool PackPs1::getBkupHeader(unsigned char *p, unsigned char *dst)
|
||||
throwInternalError("backup header damaged");
|
||||
memcpy(dst, unc_bh, SZ_IH_BKUP);
|
||||
delete[] unc_bh;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackPs1::checkFileHeader()
|
||||
{
|
||||
if (fdata_size != ih.tx_len || (ih.tx_len & 3))
|
||||
{
|
||||
bool PackPs1::checkFileHeader() {
|
||||
if (fdata_size != ih.tx_len || (ih.tx_len & 3)) {
|
||||
if (!opt->force)
|
||||
throwCantPack("file size entry damaged (try --force)");
|
||||
else
|
||||
{
|
||||
else {
|
||||
opt->info_mode += !opt->info_mode ? 1 : 0;
|
||||
infoWarning("fixing damaged header, keeping backup file");
|
||||
opt->backup = 1;
|
||||
ih.tx_len = fdata_size;
|
||||
}
|
||||
}
|
||||
if (!opt->force &&
|
||||
(ih.da_ptr != 0 || ih.da_len != 0 ||
|
||||
ih.bs_ptr != 0 || ih.bs_len != 0))
|
||||
{
|
||||
if (!opt->force && (ih.da_ptr != 0 || ih.da_len != 0 || ih.bs_ptr != 0 || ih.bs_len != 0)) {
|
||||
infoWarning("unsupported header field entry");
|
||||
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)
|
||||
return false;
|
||||
else
|
||||
@@ -241,13 +218,11 @@ bool PackPs1::checkFileHeader()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackPs1::canPack()
|
||||
{
|
||||
bool PackPs1::canPack() {
|
||||
unsigned char buf[PS_HDR_SIZE - sizeof(ps1_exe_t)];
|
||||
|
||||
if (!readFileHeader())
|
||||
@@ -257,12 +232,10 @@ bool PackPs1::canPack()
|
||||
checkAlreadyPacked(buf, sizeof(buf));
|
||||
|
||||
for (size_t i = 0; i < sizeof(buf); i++)
|
||||
if (buf[i] != 0)
|
||||
{
|
||||
if (buf[i] != 0) {
|
||||
if (!opt->force)
|
||||
throwCantPack("unknown data in header (try --force)");
|
||||
else
|
||||
{
|
||||
else {
|
||||
opt->info_mode += !opt->info_mode ? 1 : 0;
|
||||
infoWarning("clearing header, keeping backup file");
|
||||
opt->backup = 1;
|
||||
@@ -278,77 +251,60 @@ bool PackPs1::canPack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackPs1::buildLoader(const Filter *)
|
||||
{
|
||||
void PackPs1::buildLoader(const Filter *) {
|
||||
const char *method = nullptr;
|
||||
|
||||
if (ph.method == M_NRV2B_8)
|
||||
method = isCon ? "nrv2b.small,8bit.sub,nrv.done" :
|
||||
"nrv2b.8bit,nrv.done";
|
||||
method = isCon ? "nrv2b.small,8bit.sub,nrv.done" : "nrv2b.8bit,nrv.done";
|
||||
else if (ph.method == M_NRV2D_8)
|
||||
method = isCon ? "nrv2d.small,8bit.sub,nrv.done" :
|
||||
"nrv2d.8bit,nrv.done";
|
||||
method = isCon ? "nrv2d.small,8bit.sub,nrv.done" : "nrv2d.8bit,nrv.done";
|
||||
else if (ph.method == M_NRV2E_8)
|
||||
method = isCon ? "nrv2e.small,8bit.sub,nrv.done" :
|
||||
"nrv2e.8bit,nrv.done";
|
||||
method = isCon ? "nrv2e.small,8bit.sub,nrv.done" : "nrv2e.8bit,nrv.done";
|
||||
else if (ph.method == M_NRV2B_LE32)
|
||||
method = isCon ? "nrv2b.small,32bit.sub,nrv.done" :
|
||||
"nrv2b.32bit,nrv.done";
|
||||
method = isCon ? "nrv2b.small,32bit.sub,nrv.done" : "nrv2b.32bit,nrv.done";
|
||||
else if (ph.method == M_NRV2D_LE32)
|
||||
method = isCon ? "nrv2d.small,32bit.sub,nrv.done" :
|
||||
"nrv2d.32bit,nrv.done";
|
||||
method = isCon ? "nrv2d.small,32bit.sub,nrv.done" : "nrv2d.32bit,nrv.done";
|
||||
else if (ph.method == M_NRV2E_LE32)
|
||||
method = isCon ? "nrv2e.small,32bit.sub,nrv.done" :
|
||||
"nrv2e.32bit,nrv.done";
|
||||
method = isCon ? "nrv2e.small,32bit.sub,nrv.done" : "nrv2e.32bit,nrv.done";
|
||||
else if (M_IS_LZMA(ph.method))
|
||||
method = "nrv2b.small,8bit.sub,nrv.done,lzma.prep";
|
||||
else
|
||||
throwInternalError("unknown compression method");
|
||||
|
||||
unsigned sa_tmp = sa_cnt;
|
||||
if (ph.overlap_overhead > sa_cnt)
|
||||
{
|
||||
if (!opt->force)
|
||||
{
|
||||
if (ph.overlap_overhead > sa_cnt) {
|
||||
if (!opt->force) {
|
||||
infoWarning("not in-place decompressible");
|
||||
throwCantPack("packed data overlap (try --force)");
|
||||
}
|
||||
else
|
||||
} else
|
||||
sa_tmp += overlap = ALIGN_UP((ph.overlap_overhead - sa_tmp), 4u);
|
||||
}
|
||||
|
||||
if (isCon || M_IS_LZMA(ph.method))
|
||||
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));
|
||||
addLoader("decompressor.start",
|
||||
isCon ? "LZMA_DEC20" : "LZMA_DEC10", "lzma.init", nullptr);
|
||||
addLoader("decompressor.start", isCon ? "LZMA_DEC20" : "LZMA_DEC10", "lzma.init", nullptr);
|
||||
addLoader(sa_tmp > (0x10000 << 2) ? "memset.long" : "memset.short",
|
||||
!foundBss ? "con.exit" : "bss.exit", nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (M_IS_LZMA(ph.method) && buildPart2)
|
||||
{
|
||||
} else {
|
||||
if (M_IS_LZMA(ph.method) && buildPart2) {
|
||||
sz_lcpr = MemBuffer::getSizeForCompression(sz_lunc);
|
||||
unsigned char *cprLoader = New(unsigned char, sz_lcpr);
|
||||
int r = upx_compress(getLoader(), sz_lunc, cprLoader, &sz_lcpr,
|
||||
nullptr, M_NRV2B_8, 10, nullptr, nullptr );
|
||||
int r = upx_compress(getLoader(), sz_lunc, cprLoader, &sz_lcpr, nullptr, M_NRV2B_8, 10,
|
||||
nullptr, nullptr);
|
||||
if (r != UPX_E_OK || sz_lcpr >= sz_lunc)
|
||||
throwInternalError("loader compression failed");
|
||||
initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1),
|
||||
isCon || !M_IS_LZMA(ph.method) ? 0 : 1);
|
||||
linker->addSection("lzma.exec", cprLoader, sz_lcpr, 0);
|
||||
delete[] cprLoader;
|
||||
}
|
||||
else
|
||||
} else
|
||||
initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1));
|
||||
|
||||
pad_code = ALIGN_GAP((ph.c_len + (isCon ? sz_lcpr : 0)), 4u);
|
||||
@@ -356,36 +312,27 @@ void PackPs1::buildLoader(const Filter *)
|
||||
static const unsigned char pad_buffer[4] = {0, 0, 0, 0};
|
||||
linker->addSection("pad.code", pad_buffer, pad_code, 0);
|
||||
|
||||
if (isCon)
|
||||
{
|
||||
if (isCon) {
|
||||
if (M_IS_LZMA(ph.method))
|
||||
addLoader(!foundBss ? "con.start" : "bss.con.start",
|
||||
method,
|
||||
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
|
||||
"con.entry", "pad.code", "lzma.exec", nullptr);
|
||||
addLoader(!foundBss ? "con.start" : "bss.con.start", method,
|
||||
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "con.entry", "pad.code",
|
||||
"lzma.exec", nullptr);
|
||||
else
|
||||
addLoader(!foundBss ? "con.start" : "bss.con.start", "con.mcpy",
|
||||
ph.c_len & 3 ? "con.padcd" : "",
|
||||
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
|
||||
"con.entry", method,
|
||||
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "con.entry", method,
|
||||
sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "",
|
||||
!foundBss ? "con.exit" : "bss.exit",
|
||||
"pad.code", nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
!foundBss ? "con.exit" : "bss.exit", "pad.code", nullptr);
|
||||
} else {
|
||||
if (M_IS_LZMA(ph.method))
|
||||
addLoader(!foundBss ? "cdb.start.lzma" : "bss.cdb.start.lzma", "pad.code",
|
||||
!foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma",
|
||||
method, "cdb.lzma.cpr",
|
||||
ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
|
||||
!foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma", method,
|
||||
"cdb.lzma.cpr", ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi",
|
||||
"lzma.exec", nullptr);
|
||||
else
|
||||
{
|
||||
else {
|
||||
assert(foundBss != true);
|
||||
addLoader("cdb.start", "pad.code", "cdb.entry",
|
||||
ih.tx_ptr & 0xffff ? "cdb.dec.ptr" : "cdb.dec.ptr.hi",
|
||||
method,
|
||||
ih.tx_ptr & 0xffff ? "cdb.dec.ptr" : "cdb.dec.ptr.hi", method,
|
||||
sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "",
|
||||
"cdb.exit", nullptr);
|
||||
}
|
||||
@@ -415,8 +362,7 @@ void PackPs1::buildLoader(const Filter *)
|
||||
|
||||
#define BSS_CHK_LIMIT (18)
|
||||
|
||||
bool PackPs1::findBssSection()
|
||||
{
|
||||
bool PackPs1::findBssSection() {
|
||||
unsigned char reg;
|
||||
const LE32 *const p1 = ACC_CCAST(const LE32 *, ibuf + (ih.epc - ih.tx_ptr));
|
||||
|
||||
@@ -424,33 +370,26 @@ bool PackPs1::findBssSection()
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
if (IS_SW_ZERO(op))
|
||||
{
|
||||
if (IS_SW_ZERO(op)) {
|
||||
// found! get reg (x) for bss_start
|
||||
reg = REG1(op);
|
||||
for (; i >= 0; i--)
|
||||
{
|
||||
for (; i >= 0; i--) {
|
||||
const bss_nfo *const p = ACC_CCAST(const bss_nfo *, &p1[i]);
|
||||
upx_uint16_t op1 = p->op1, op2 = p->op2;
|
||||
|
||||
// check for la (x),bss_start
|
||||
if ((IS_LUI(op1) && REG2(op1) == reg) &&
|
||||
(IS_ADDIU(op2) && REG1(op2) == reg))
|
||||
{
|
||||
if ((IS_LUI(op1) && REG2(op1) == reg) && (IS_ADDIU(op2) && REG1(op2) == reg)) {
|
||||
op1 = p->op3, op2 = p->op4;
|
||||
|
||||
// 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_start = MIPS_IMM(p->hi1, p->lo1);
|
||||
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 end_offs = ih.tx_ptr + fdata_size + overlap;
|
||||
if (bss_end > (end_offs + wkmem_sz))
|
||||
@@ -458,8 +397,7 @@ bool PackPs1::findBssSection()
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -468,13 +406,11 @@ bool PackPs1::findBssSection()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackPs1::pack(OutputFile *fo)
|
||||
{
|
||||
void PackPs1::pack(OutputFile *fo) {
|
||||
ibuf.alloc(fdata_size);
|
||||
obuf.allocForCompression(fdata_size);
|
||||
const upx_byte *p_scan = ibuf + fdata_size;
|
||||
@@ -485,7 +421,10 @@ void PackPs1::pack(OutputFile *fo)
|
||||
|
||||
// scan EOF for 2048 bytes sector alignment
|
||||
// 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))
|
||||
sa_cnt = ALIGN_DOWN(sa_cnt, 32u);
|
||||
@@ -498,13 +437,13 @@ void PackPs1::pack(OutputFile *fo)
|
||||
Filter ft(ph.level);
|
||||
|
||||
// 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_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
||||
compressWithFilters(&ft, sa_cnt, &cconf);
|
||||
|
||||
if (overlap)
|
||||
{
|
||||
if (overlap) {
|
||||
opt->info_mode += !opt->info_mode ? 1 : 0;
|
||||
infoWarning("overlap - relocating load address (+%d bytes)", overlap);
|
||||
sa_cnt += overlap;
|
||||
@@ -517,15 +456,13 @@ void PackPs1::pack(OutputFile *fo)
|
||||
|
||||
unsigned lzma_init = 0;
|
||||
|
||||
if (M_IS_LZMA(ph.method))
|
||||
{
|
||||
if (M_IS_LZMA(ph.method)) {
|
||||
sz_lunc = getLoaderSize();
|
||||
|
||||
lzma_init = 0u - (sz_lunc - linker->getSymbolOffset("lzma.init"));
|
||||
defineDecompressorSymbols();
|
||||
linker->defineSymbol("entry", ih.epc);
|
||||
linker->defineSymbol("SC",
|
||||
sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2);
|
||||
linker->defineSymbol("SC", sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2);
|
||||
relocateLoader();
|
||||
|
||||
buildPart2 = true;
|
||||
@@ -540,10 +477,8 @@ void PackPs1::pack(OutputFile *fo)
|
||||
if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE)))
|
||||
oh.is_ptr = (EXE_BS | (PS_RAM_SIZE - 16));
|
||||
|
||||
if (ih.da_ptr != 0 || ih.da_len != 0 ||
|
||||
ih.bs_ptr != 0 || ih.bs_len != 0)
|
||||
oh.da_ptr = oh.da_len =
|
||||
oh.bs_ptr = oh.bs_len = 0;
|
||||
if (ih.da_ptr != 0 || ih.da_len != 0 || ih.bs_ptr != 0 || ih.bs_len != 0)
|
||||
oh.da_ptr = oh.da_len = oh.bs_ptr = oh.bs_len = 0;
|
||||
|
||||
const int lsize = getLoaderSize();
|
||||
|
||||
@@ -556,43 +491,37 @@ void PackPs1::pack(OutputFile *fo)
|
||||
int d_len = 0;
|
||||
int e_len = 0;
|
||||
|
||||
if (isCon)
|
||||
{
|
||||
if (isCon) {
|
||||
e_len = lsize - h_len;
|
||||
d_len = e_len - getLoaderSectionStart("con.entry");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
linker->defineSymbol("entry", ih.epc);
|
||||
linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ?
|
||||
sa_cnt >> 5 : sa_cnt >> 2));
|
||||
linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2));
|
||||
linker->defineSymbol("DECO", decomp_data_start);
|
||||
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))
|
||||
linker->defineSymbol("wrkmem", bss_end - 160 - getDecompressorWrkmemSize()
|
||||
- (sz_lunc + 16));
|
||||
linker->defineSymbol("wrkmem",
|
||||
bss_end - 160 - getDecompressorWrkmemSize() - (sz_lunc + 16));
|
||||
else
|
||||
linker->defineSymbol("wrkmem", bss_end - 16 - (d_len - pad_code));
|
||||
}
|
||||
|
||||
|
||||
const unsigned entry = comp_data_start - e_len;
|
||||
oh.epc = oh.tx_ptr = entry;
|
||||
oh.tx_len = ph.c_len + e_len;
|
||||
|
||||
unsigned pad = 0;
|
||||
|
||||
if (!opt->ps1_exe.no_align || !isCon)
|
||||
{
|
||||
if (!opt->ps1_exe.no_align || !isCon) {
|
||||
pad = oh.tx_len;
|
||||
oh.tx_len = ALIGN_UP(oh.tx_len, CD_SEC + 0u);
|
||||
pad = oh.tx_len - pad;
|
||||
@@ -602,31 +531,24 @@ void PackPs1::pack(OutputFile *fo)
|
||||
ibuf.clear(0, fdata_size);
|
||||
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("gb_e", linker->getSymbolOffset("gb8_e"));
|
||||
}
|
||||
else
|
||||
if (isCon)
|
||||
} else if (isCon)
|
||||
linker->defineSymbol("gb_e", linker->getSymbolOffset(is32Bit ? "gb32_e" : "gb8_e"));
|
||||
|
||||
if (isCon)
|
||||
{
|
||||
if (isCon) {
|
||||
linker->defineSymbol("PAD", pad_code);
|
||||
if (M_IS_LZMA(ph.method))
|
||||
linker->defineSymbol("DCRT", (entry + getLoaderSectionStart("lzma.exec")));
|
||||
else
|
||||
linker->defineSymbol("DCRT", (entry + (e_len - d_len)));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
linker->defineSymbol("PSVR", FIX_PSVR);
|
||||
linker->defineSymbol("CPDO", comp_data_start);
|
||||
if (M_IS_LZMA(ph.method))
|
||||
{
|
||||
unsigned entry_lzma = getLoaderSectionStart( !foundBss ? "cdb.entry.lzma" :
|
||||
"bss.cdb.entry.lzma");
|
||||
if (M_IS_LZMA(ph.method)) {
|
||||
unsigned entry_lzma =
|
||||
getLoaderSectionStart(!foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma");
|
||||
|
||||
linker->defineSymbol("lzma_cpr", getLoaderSectionStart("lzma.exec") - entry_lzma);
|
||||
}
|
||||
@@ -680,13 +602,11 @@ void PackPs1::pack(OutputFile *fo)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int PackPs1::canUnpack()
|
||||
{
|
||||
int PackPs1::canUnpack() {
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (!readPackHeader(CD_SEC))
|
||||
@@ -700,13 +620,11 @@ int PackPs1::canUnpack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackPs1::unpack(OutputFile *fo)
|
||||
{
|
||||
void PackPs1::unpack(OutputFile *fo) {
|
||||
// restore orig exec hdr
|
||||
memcpy(&oh, &ih, sizeof(ih));
|
||||
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);
|
||||
|
||||
// write decompressed file
|
||||
if (fo)
|
||||
{
|
||||
if (fo) {
|
||||
// write header
|
||||
fo->write(&oh, sizeof(oh));
|
||||
// align the ps exe header (mode 2 sector data size)
|
||||
|
||||
+13
-15
@@ -29,18 +29,17 @@
|
||||
<jssg@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_PS1_H
|
||||
#define __UPX_P_PS1_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_PS1_H__
|
||||
#define UPX_P_PS1_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// ps1/exe
|
||||
**************************************************************************/
|
||||
|
||||
class PackPs1 final : public Packer
|
||||
{
|
||||
class PackPs1 final : public Packer {
|
||||
typedef Packer super;
|
||||
|
||||
public:
|
||||
PackPs1(InputFile *f);
|
||||
virtual int getVersion() const override { return 13; }
|
||||
@@ -67,7 +66,7 @@ protected:
|
||||
int readFileHeader();
|
||||
bool checkFileHeader();
|
||||
|
||||
__packed_struct(ps1_exe_t)
|
||||
struct alignas(1) ps1_exe_t {
|
||||
// ident string
|
||||
char id[8];
|
||||
// is nullptr
|
||||
@@ -90,26 +89,26 @@ protected:
|
||||
char origin[60];
|
||||
// backup of the original header (epc - is_len)
|
||||
// id & the upx header ...
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
// for unpack
|
||||
__packed_struct(ps1_exe_hb_t)
|
||||
struct alignas(1) ps1_exe_hb_t {
|
||||
LE32 ih_bkup[10];
|
||||
// plus checksum for the backup
|
||||
LE32 ih_csum;
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
__packed_struct(ps1_exe_chb_t)
|
||||
struct alignas(1) ps1_exe_chb_t {
|
||||
unsigned char id;
|
||||
unsigned char len;
|
||||
LE16 ih_csum;
|
||||
unsigned char ih_bkup;
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
__packed_struct(bss_nfo)
|
||||
struct alignas(1) bss_nfo {
|
||||
LE16 hi1, op1, lo1, op2;
|
||||
LE16 hi2, op3, lo2, op4;
|
||||
__packed_struct_end()
|
||||
};
|
||||
|
||||
ps1_exe_t ih, oh;
|
||||
ps1_exe_hb_t bh;
|
||||
@@ -127,7 +126,6 @@ protected:
|
||||
unsigned fdata_size;
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+9
-29
@@ -25,7 +25,6 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -34,16 +33,14 @@
|
||||
#include "p_sys.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i086-dos16.sys.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackSys::canPack()
|
||||
{
|
||||
bool PackSys::canPack() {
|
||||
unsigned char buf[128];
|
||||
|
||||
fi->readx(buf, sizeof(buf));
|
||||
@@ -59,15 +56,11 @@ bool PackSys::canPack()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackSys::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls)
|
||||
{
|
||||
void PackSys::patchLoader(OutputFile *fo, upx_byte *loader, int lsize, unsigned calls) {
|
||||
const int e_len = getLoaderSectionStart("SYSCUTPO");
|
||||
const int d_len = lsize - e_len;
|
||||
assert(e_len > 0 && e_len < 128);
|
||||
@@ -99,30 +92,17 @@ void PackSys::patchLoader(OutputFile *fo,
|
||||
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));
|
||||
addLoader("SYSMAIN1",
|
||||
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861",
|
||||
"SYSMAIN2",
|
||||
ph.first_offset_found == 1 ? "SYSSBBBP" : "",
|
||||
ft->id ? "SYSCALLT" : "",
|
||||
addLoader("SYSMAIN1", opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861", "SYSMAIN2",
|
||||
ph.first_offset_found == 1 ? "SYSSBBBP" : "", ft->id ? "SYSCALLT" : "",
|
||||
"SYSMAIN3,UPX1HEAD,SYSCUTPO,NRV2B160,NRVDDONE,NRVDECO1",
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||
"NRVDECO2",
|
||||
nullptr
|
||||
);
|
||||
if (ft->id)
|
||||
{
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00", "NRVDECO2", nullptr);
|
||||
if (ft->id) {
|
||||
assert(ft->calls > 0);
|
||||
addFilter16(ft->id);
|
||||
}
|
||||
addLoader("SYSMAIN5",
|
||||
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
|
||||
"SYSJUMP1",
|
||||
nullptr
|
||||
);
|
||||
addLoader("SYSMAIN5", opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862", "SYSJUMP1", nullptr);
|
||||
}
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+5
-8
@@ -25,24 +25,22 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_SYS_H
|
||||
#define __UPX_P_SYS_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_SYS_H__
|
||||
#define UPX_P_SYS_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// dos/sys
|
||||
**************************************************************************/
|
||||
|
||||
class PackSys final : public PackCom
|
||||
{
|
||||
class PackSys final : public PackCom {
|
||||
typedef PackCom super;
|
||||
|
||||
public:
|
||||
PackSys(InputFile *f) : super(f) {}
|
||||
virtual int getVersion() const override { return 13; }
|
||||
virtual int getFormat() const override { return UPX_F_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 bool canPack() override;
|
||||
@@ -55,7 +53,6 @@ protected:
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned) override;
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+94
-179
@@ -25,7 +25,6 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -34,7 +33,7 @@
|
||||
#include "p_wcle.h"
|
||||
#include "linker.h"
|
||||
|
||||
static const
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i386-dos32.watcom.le.h"
|
||||
|
||||
#define LEOF_READ (1 << 0)
|
||||
@@ -49,7 +48,11 @@ static const
|
||||
#define LE_STUB_EDI (1)
|
||||
|
||||
#ifdef TESTING
|
||||
# define dputc(x,y) do { if (opt->debug.debug_level) putc(x,y); } while (0)
|
||||
#define dputc(x, y) \
|
||||
do { \
|
||||
if (opt->debug.debug_level) \
|
||||
putc(x, y); \
|
||||
} while (0)
|
||||
#define Opt_debug opt->debug.debug_level
|
||||
#else
|
||||
#define dputc(x, y) ((void) 0)
|
||||
@@ -62,87 +65,59 @@ static const
|
||||
#define mps ih.memory_page_size
|
||||
#define opages oh.memory_pages
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
const int *PackWcle::getCompressionMethods(int method, int level) const
|
||||
{
|
||||
const int *PackWcle::getCompressionMethods(int method, int level) const {
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
}
|
||||
|
||||
|
||||
const int *PackWcle::getFilters() const
|
||||
{
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14, 0x11,
|
||||
FT_ULTRA_BRUTE, 0x25, 0x15, 0x12,
|
||||
FT_END };
|
||||
const int *PackWcle::getFilters() const {
|
||||
static const int filters[] = {0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14,
|
||||
0x11, FT_ULTRA_BRUTE, 0x25, 0x15, 0x12, FT_END};
|
||||
return filters;
|
||||
}
|
||||
|
||||
Linker *PackWcle::newLinker() const { return new ElfLinkerX86; }
|
||||
|
||||
Linker* PackWcle::newLinker() const
|
||||
{
|
||||
return new ElfLinkerX86;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::buildLoader(const Filter *ft)
|
||||
{
|
||||
void PackWcle::buildLoader(const Filter *ft) {
|
||||
// prepare loader
|
||||
initLoader(stub_i386_dos32_watcom_le, sizeof(stub_i386_dos32_watcom_le));
|
||||
addLoader("IDENTSTR,WCLEMAIN",
|
||||
ph.first_offset_found == 1 ? "WCLEMAIN02" : "",
|
||||
addLoader("IDENTSTR,WCLEMAIN", ph.first_offset_found == 1 ? "WCLEMAIN02" : "",
|
||||
"WCLEMAIN03,UPX1HEAD,WCLECUTP", nullptr);
|
||||
|
||||
// fake alignment for the start of the decompressor
|
||||
linker->defineSymbol("WCLECUTP", 0x1000);
|
||||
|
||||
addLoader(getDecompressorSections(), "WCLEMAI2", nullptr);
|
||||
if (ft->id)
|
||||
{
|
||||
if (ft->id) {
|
||||
assert(ft->calls > 0);
|
||||
addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL", nullptr);
|
||||
addFilter32(ft->id);
|
||||
}
|
||||
#if 1
|
||||
// FIXME: if (has_relocation)
|
||||
{
|
||||
addLoader("WCRELOC1,RELOC320",
|
||||
big_relocs ? "REL32BIG" : "",
|
||||
"RELOC32J",
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
{ addLoader("WCRELOC1,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", nullptr); }
|
||||
#endif
|
||||
addLoader(has_extra_code ? "WCRELSEL" : "",
|
||||
"WCLEMAI4",
|
||||
nullptr
|
||||
);
|
||||
addLoader(has_extra_code ? "WCRELSEL" : "", "WCLEMAI4", nullptr);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
void PackWcle::handleStub(OutputFile *fo)
|
||||
{
|
||||
void PackWcle::handleStub(OutputFile *fo) {
|
||||
if (fo && !opt->watcom_le.le)
|
||||
Packer::handleStub(fi, fo, le_offset);
|
||||
}
|
||||
|
||||
|
||||
bool PackWcle::canPack()
|
||||
{
|
||||
bool PackWcle::canPack() {
|
||||
if (!LeFile::readFileHeader())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
@@ -150,13 +125,11 @@ bool PackWcle::canPack()
|
||||
// IDEA: as all the entries go into object #1, I could create bundles with 255
|
||||
// elements (of course I still have to handle empty bundles)
|
||||
|
||||
void PackWcle::encodeEntryTable()
|
||||
{
|
||||
void PackWcle::encodeEntryTable() {
|
||||
unsigned count, object, n;
|
||||
upx_byte *p = ientries;
|
||||
n = 0;
|
||||
while (*p)
|
||||
{
|
||||
while (*p) {
|
||||
count = *p;
|
||||
n += count;
|
||||
if (p[1] == 0) // unused bundle
|
||||
@@ -168,8 +141,7 @@ void PackWcle::encodeEntryTable()
|
||||
p += 4;
|
||||
for (; count; count--, p += 5)
|
||||
set_le32(p + 1, IOT(object, my_base_address) + get_le32(p + 1));
|
||||
}
|
||||
else
|
||||
} else
|
||||
throwCantPack("unsupported bundle type in entry table");
|
||||
}
|
||||
|
||||
@@ -181,9 +153,7 @@ void PackWcle::encodeEntryTable()
|
||||
ientries = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::readObjectTable()
|
||||
{
|
||||
void PackWcle::readObjectTable() {
|
||||
LeFile::readObjectTable();
|
||||
|
||||
// temporary copy of the object descriptors
|
||||
@@ -192,8 +162,7 @@ void PackWcle::readObjectTable()
|
||||
|
||||
unsigned ic, jc, virtual_size;
|
||||
|
||||
for (ic = jc = virtual_size = 0; ic < objects; ic++)
|
||||
{
|
||||
for (ic = jc = virtual_size = 0; ic < objects; ic++) {
|
||||
jc += IOT(ic, npages);
|
||||
IOT(ic, my_base_address) = virtual_size;
|
||||
virtual_size += (IOT(ic, virtual_size) + mps - 1) & ~(mps - 1);
|
||||
@@ -202,9 +171,7 @@ void PackWcle::readObjectTable()
|
||||
throwCantPack("bad page number");
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::encodeObjectTable()
|
||||
{
|
||||
void PackWcle::encodeObjectTable() {
|
||||
unsigned ic, jc;
|
||||
|
||||
oobject_table = New(le_object_table_entry_t, soobject_table = 2);
|
||||
@@ -226,8 +193,7 @@ void PackWcle::encodeObjectTable()
|
||||
OOT(0, npages) = opages;
|
||||
|
||||
// object #2: stack
|
||||
OOT(1,base_address) = (OOT(0,base_address)
|
||||
+OOT(0,virtual_size)+mps-1) & ~(mps-1);
|
||||
OOT(1, base_address) = (OOT(0, base_address) + OOT(0, virtual_size) + mps - 1) & ~(mps - 1);
|
||||
OOT(1, virtual_size) = mps + getDecompressorWrkmemSize();
|
||||
OOT(1, flags) = LEOF_READ | LEOF_HUGE32 | LEOF_WRITE;
|
||||
OOT(1, pagemap_index) = 1;
|
||||
@@ -239,12 +205,9 @@ void PackWcle::encodeObjectTable()
|
||||
oh.automatic_data_object = 2;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::encodePageMap()
|
||||
{
|
||||
void PackWcle::encodePageMap() {
|
||||
opm_entries = New(le_pagemap_entry_t, sopm_entries = opages);
|
||||
for (unsigned ic = 0; ic < sopm_entries; ic++)
|
||||
{
|
||||
for (unsigned ic = 0; ic < sopm_entries; ic++) {
|
||||
opm_entries[ic].l = (unsigned char) (ic + 1);
|
||||
opm_entries[ic].m = (unsigned char) ((ic + 1) >> 8);
|
||||
opm_entries[ic].h = 0;
|
||||
@@ -252,18 +215,14 @@ void PackWcle::encodePageMap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::encodeFixupPageTable()
|
||||
{
|
||||
void PackWcle::encodeFixupPageTable() {
|
||||
unsigned ic;
|
||||
ofpage_table = New(unsigned, sofpage_table = 1 + opages);
|
||||
for (ofpage_table[0] = ic = 0; ic < opages; ic++)
|
||||
set_le32(ofpage_table + ic + 1, sofixups - FIXUP_EXTRA);
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::encodeFixups()
|
||||
{
|
||||
void PackWcle::encodeFixups() {
|
||||
ofixups = New(upx_byte, sofixups = 1 * 7 + FIXUP_EXTRA);
|
||||
memset(ofixups, 0, sofixups);
|
||||
ofixups[0] = 7;
|
||||
@@ -271,9 +230,7 @@ void PackWcle::encodeFixups()
|
||||
ofixups[4] = 1;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::preprocessFixups()
|
||||
{
|
||||
void PackWcle::preprocessFixups() {
|
||||
big_relocs = 0;
|
||||
|
||||
unsigned ic, jc;
|
||||
@@ -284,8 +241,7 @@ void PackWcle::preprocessFixups()
|
||||
for (ic = jc = 0; ic < objects; ic++)
|
||||
jc += counts[ic];
|
||||
|
||||
if (jc == 0)
|
||||
{
|
||||
if (jc == 0) {
|
||||
// FIXME: implement this
|
||||
throwCantPack("files without relocations are not supported");
|
||||
}
|
||||
@@ -300,25 +256,22 @@ void PackWcle::preprocessFixups()
|
||||
unsigned rc = 0;
|
||||
|
||||
upx_byte *fix = ifixups;
|
||||
for (ic = jc = 0; ic < pages; ic++)
|
||||
{
|
||||
while ((unsigned)(fix - ifixups) < get_le32(ifpage_table+ic+1))
|
||||
{
|
||||
for (ic = jc = 0; ic < pages; ic++) {
|
||||
while ((unsigned) (fix - ifixups) < get_le32(ifpage_table + ic + 1)) {
|
||||
const int fixp2 = get_le16_signed(fix + 2);
|
||||
unsigned value;
|
||||
|
||||
switch (*fix)
|
||||
{
|
||||
switch (*fix) {
|
||||
case 2: // selector fixup
|
||||
if (fixp2 < 0)
|
||||
{
|
||||
if (fixp2 < 0) {
|
||||
// cross page selector fixup
|
||||
dputc('S', stdout);
|
||||
fix += 5;
|
||||
break;
|
||||
}
|
||||
dputc('s', stdout);
|
||||
memcpy(selector_fixups,"\x8C\xCB\x66\x89\x9D",5); // mov bx, cs ; mov [xxx+ebp], bx
|
||||
memcpy(selector_fixups, "\x8C\xCB\x66\x89\x9D",
|
||||
5); // mov bx, cs ; mov [xxx+ebp], bx
|
||||
if (IOT(fix[4] - 1, flags) & LEOF_WRITE)
|
||||
selector_fixups[1] = 0xDB; // ds
|
||||
set_le32(selector_fixups + 5, jc + fixp2);
|
||||
@@ -333,8 +286,7 @@ void PackWcle::preprocessFixups()
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 6: // 16:32 pointer
|
||||
if (fixp2 < 0)
|
||||
{
|
||||
if (fixp2 < 0) {
|
||||
// cross page pointer fixup
|
||||
dputc('P', stdout);
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
@@ -343,7 +295,8 @@ void PackWcle::preprocessFixups()
|
||||
dputc('p', stdout);
|
||||
memcpy(iimage + jc + fixp2, fix + 5, (fix[1] & 0x10) ? 4 : 2);
|
||||
set_le32(rl + 4 * rc++, jc + fixp2);
|
||||
set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address));
|
||||
set_le32(iimage + jc + fixp2,
|
||||
get_le32(iimage + jc + fixp2) + IOT(fix[4] - 1, my_base_address));
|
||||
|
||||
memcpy(selector_fixups, "\x8C\xCA\x66\x89\x95", 5);
|
||||
if (IOT(fix[4] - 1, flags) & LEOF_WRITE)
|
||||
@@ -353,8 +306,7 @@ void PackWcle::preprocessFixups()
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 7: // 32-bit offset
|
||||
if (fixp2 < 0)
|
||||
{
|
||||
if (fixp2 < 0) {
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
}
|
||||
@@ -363,16 +315,15 @@ void PackWcle::preprocessFixups()
|
||||
|
||||
// work around a pmwunlite bug: remove duplicated fixups
|
||||
// FIXME: fix the other cases too
|
||||
if (rc == 0 || get_le32(rl+4*rc-4) != jc+fixp2)
|
||||
{
|
||||
if (rc == 0 || get_le32(rl + 4 * rc - 4) != jc + fixp2) {
|
||||
set_le32(rl + 4 * rc++, jc + fixp2);
|
||||
set_le32(iimage+jc+fixp2,get_le32(iimage+jc+fixp2)+IOT(fix[4]-1,my_base_address));
|
||||
set_le32(iimage + jc + fixp2,
|
||||
get_le32(iimage + jc + fixp2) + IOT(fix[4] - 1, my_base_address));
|
||||
}
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 8: // 32-bit self relative fixup
|
||||
if (fixp2 < 0)
|
||||
{
|
||||
if (fixp2 < 0) {
|
||||
// cross page self relative fixup
|
||||
dputc('R', stdout);
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
@@ -381,7 +332,8 @@ void PackWcle::preprocessFixups()
|
||||
value = get_le32(fix + 5);
|
||||
if (fix[1] == 0)
|
||||
value &= 0xffff;
|
||||
set_le32(iimage+jc+fixp2,(value+IOT(fix[4]-1,my_base_address))-jc-fixp2-4);
|
||||
set_le32(iimage + jc + fixp2,
|
||||
(value + IOT(fix[4] - 1, my_base_address)) - jc - fixp2 - 4);
|
||||
set_le32(selfrel_fixups, jc + fixp2);
|
||||
selfrel_fixups += 4;
|
||||
dputc('r', stdout);
|
||||
@@ -395,8 +347,7 @@ void PackWcle::preprocessFixups()
|
||||
}
|
||||
|
||||
// resize ifixups if it's too small
|
||||
if (sofixups < 1000)
|
||||
{
|
||||
if (sofixups < 1000) {
|
||||
delete[] ifixups;
|
||||
ifixups = new upx_byte[1000];
|
||||
}
|
||||
@@ -416,17 +367,16 @@ void PackWcle::preprocessFixups()
|
||||
sofixups = ptr_udiff_bytes(fix, ifixups);
|
||||
}
|
||||
|
||||
|
||||
#define RESERVED 0x1000
|
||||
void PackWcle::encodeImage(Filter *ft)
|
||||
{
|
||||
void PackWcle::encodeImage(Filter *ft) {
|
||||
// concatenate image & preprocessed fixups
|
||||
unsigned isize = soimage + sofixups;
|
||||
ibuf.alloc(isize);
|
||||
memcpy(ibuf, iimage, soimage);
|
||||
memcpy(ibuf + soimage, ifixups, sofixups);
|
||||
|
||||
delete[] ifixups; ifixups = nullptr;
|
||||
delete[] ifixups;
|
||||
ifixups = nullptr;
|
||||
|
||||
mb_oimage.allocForCompression(isize, RESERVED + 512);
|
||||
oimage = mb_oimage;
|
||||
@@ -434,13 +384,11 @@ void PackWcle::encodeImage(Filter *ft)
|
||||
ph.u_len = isize;
|
||||
// prepare filter [already done]
|
||||
// compress
|
||||
upx_compress_config_t cconf; cconf.reset();
|
||||
upx_compress_config_t cconf;
|
||||
cconf.reset();
|
||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28 KiB stack
|
||||
compressWithFilters(ibuf, isize,
|
||||
raw_bytes(oimage + RESERVED, mb_oimage.getSize() - RESERVED),
|
||||
ibuf + ft->addvalue, ft->buf_len,
|
||||
nullptr, 0,
|
||||
ft, 512, &cconf, 0);
|
||||
compressWithFilters(ibuf, isize, raw_bytes(oimage + RESERVED, mb_oimage.getSize() - RESERVED),
|
||||
ibuf + ft->addvalue, ft->buf_len, nullptr, 0, ft, 512, &cconf, 0);
|
||||
|
||||
ibuf.dealloc();
|
||||
soimage = ph.c_len;
|
||||
@@ -448,21 +396,13 @@ void PackWcle::encodeImage(Filter *ft)
|
||||
oimage[RESERVED + soimage++] = 0;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::pack(OutputFile *fo)
|
||||
{
|
||||
void PackWcle::pack(OutputFile *fo) {
|
||||
handleStub(fo);
|
||||
|
||||
if (ih.byte_order || ih.word_order
|
||||
|| ih.exe_format_level
|
||||
|| ih.cpu_type < 2 || ih.cpu_type > 5
|
||||
|| ih.target_os != 1
|
||||
|| ih.module_type != 0x200
|
||||
|| ih.object_iterate_data_map_offset
|
||||
|| ih.resource_entries
|
||||
|| ih.module_directives_entries
|
||||
|| ih.imported_modules_count
|
||||
|| ih.object_table_entries > 255)
|
||||
if (ih.byte_order || ih.word_order || ih.exe_format_level || ih.cpu_type < 2 ||
|
||||
ih.cpu_type > 5 || ih.target_os != 1 || ih.module_type != 0x200 ||
|
||||
ih.object_iterate_data_map_offset || ih.resource_entries || ih.module_directives_entries ||
|
||||
ih.imported_modules_count || ih.object_table_entries > 255)
|
||||
throwCantPack("watcom/le: unexpected value in header");
|
||||
|
||||
readObjectTable();
|
||||
@@ -493,7 +433,8 @@ void PackWcle::pack(OutputFile *fo)
|
||||
iobject_desc.dealloc();
|
||||
|
||||
sofixups += ic;
|
||||
set_le32(ifixups+sofixups,ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); // old stack pointer
|
||||
set_le32(ifixups + sofixups,
|
||||
ih.init_esp_offset + IOT(ih.init_ss_object - 1, my_base_address)); // old stack pointer
|
||||
set_le32(ifixups + sofixups + 4, ih.init_eip_offset + text_vaddr); // real entry point
|
||||
set_le32(ifixups + sofixups + 8, mps * pages); // virtual address of unpacked relocations
|
||||
ifixups[sofixups + 12] = (unsigned char) (unsigned) objects;
|
||||
@@ -534,8 +475,8 @@ void PackWcle::pack(OutputFile *fo)
|
||||
linker->defineSymbol("WCLECUTP", ic);
|
||||
|
||||
linker->defineSymbol("original_entry", ih.init_eip_offset + text_vaddr);
|
||||
linker->defineSymbol("original_stack", ih.init_esp_offset +
|
||||
IOT(ih.init_ss_object - 1, my_base_address));
|
||||
linker->defineSymbol("original_stack",
|
||||
ih.init_esp_offset + IOT(ih.init_ss_object - 1, my_base_address));
|
||||
linker->defineSymbol("start_of_relocs", mps * pages);
|
||||
defineDecompressorSymbols();
|
||||
defineFilterSymbols(&ft);
|
||||
@@ -561,8 +502,7 @@ void PackWcle::pack(OutputFile *fo)
|
||||
verifyOverlappingDecompression(mb_oimage + e_len, mb_oimage.getSize() - e_len);
|
||||
|
||||
// copy the overlay
|
||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
||||
+ getImageSize();
|
||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset + getImageSize();
|
||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||
checkOverlay(overlay);
|
||||
copyOverlay(fo, overlay, mb_oimage);
|
||||
@@ -572,13 +512,11 @@ void PackWcle::pack(OutputFile *fo)
|
||||
throwNotCompressible();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackWcle::decodeFixups()
|
||||
{
|
||||
void PackWcle::decodeFixups() {
|
||||
SPAN_P_VAR(upx_byte, p, oimage + soimage);
|
||||
// assert(p.raw_size_in_bytes() == mb_oimage.getSize()); // Span sanity check
|
||||
|
||||
@@ -590,8 +528,7 @@ void PackWcle::decodeFixups()
|
||||
|
||||
MemBuffer wrkmem(8 * fixupn + 8);
|
||||
unsigned ic, jc, o, r;
|
||||
for (ic=0; ic<fixupn; ic++)
|
||||
{
|
||||
for (ic = 0; ic < fixupn; ic++) {
|
||||
jc = get_le32(tmpbuf + 4 * ic);
|
||||
set_le32(wrkmem + ic * 8, jc);
|
||||
o = soobject_table;
|
||||
@@ -615,22 +552,23 @@ void PackWcle::decodeFixups()
|
||||
// "\x8C\xCB\x66\x89\x9D" // mov bx, cs ; mov [xxx+ebp], bx
|
||||
// "\x8C\xCA\x66\x89\x95"
|
||||
// and where byte [+1] also can be '\xDA' or '\xDB'.
|
||||
if (0x8C != q[0]
|
||||
|| 0x66 != q[2]
|
||||
|| 0x89 != q[3]) { // Unexpected; tampering?
|
||||
if (0x8C != q[0] || 0x66 != q[2] || 0x89 != q[3]) { // Unexpected; tampering?
|
||||
// Try to recover by looking for the RET.
|
||||
upx_byte const *q2 = (upx_byte const *) memchr(q, 0xC3, 9);
|
||||
if (q2) { // Assume recovery
|
||||
q = q2; break;
|
||||
q = q2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Guard against run-away.
|
||||
static unsigned char const blank[9] = {0};
|
||||
if (ptr_diff_bytes(oimage + ph.u_len - sizeof(blank), raw_bytes(q,0)) < 0 // catastrophic worst case
|
||||
if (ptr_diff_bytes(oimage + ph.u_len - sizeof(blank), raw_bytes(q, 0)) <
|
||||
0 // catastrophic worst case
|
||||
|| !memcmp(blank, q, sizeof(blank)) // no-good early warning
|
||||
) {
|
||||
char msg[50]; snprintf(msg, sizeof(msg),
|
||||
"bad selector_fixups %d", ptr_diff_bytes(q, selector_fixups));
|
||||
char msg[50];
|
||||
snprintf(msg, sizeof(msg), "bad selector_fixups %d",
|
||||
ptr_diff_bytes(q, selector_fixups));
|
||||
throwCantPack(msg);
|
||||
}
|
||||
q += 9;
|
||||
@@ -642,11 +580,9 @@ void PackWcle::decodeFixups()
|
||||
ofixups = New(upx_byte, fbytes);
|
||||
SPAN_S_VAR(upx_byte, fp, ofixups, fbytes, ofixups);
|
||||
|
||||
for (ic = 1, jc = 0; ic <= opages; ic++)
|
||||
{
|
||||
for (ic = 1, jc = 0; ic <= opages; ic++) {
|
||||
// self relative fixups
|
||||
while ((r = get_le32(selfrel_fixups))/mps == ic-1)
|
||||
{
|
||||
while ((r = get_le32(selfrel_fixups)) / mps == ic - 1) {
|
||||
fp[0] = 8;
|
||||
set_le16(fp + 2, r & (mps - 1));
|
||||
o = 4 + get_le32(oimage + r);
|
||||
@@ -662,8 +598,7 @@ void PackWcle::decodeFixups()
|
||||
dputc('r', stdout);
|
||||
}
|
||||
// selector fixups
|
||||
while (selectlen && (r = get_le32(selector_fixups+5))/mps == ic-1)
|
||||
{
|
||||
while (selectlen && (r = get_le32(selector_fixups + 5)) / mps == ic - 1) {
|
||||
fp[0] = 2;
|
||||
fp[1] = 0;
|
||||
set_le16(fp + 2, r & (mps - 1));
|
||||
@@ -675,9 +610,9 @@ void PackWcle::decodeFixups()
|
||||
dputc('s', stdout);
|
||||
}
|
||||
// 32 bit offset fixups
|
||||
while (get_le32(wrkmem+4*jc) < ic*mps)
|
||||
{
|
||||
if (jc > 1 && ((get_le32(wrkmem+4*(jc-2))+3) & (mps-1)) < 3) // cross page fixup?
|
||||
while (get_le32(wrkmem + 4 * jc) < ic * mps) {
|
||||
if (jc > 1 &&
|
||||
((get_le32(wrkmem + 4 * (jc - 2)) + 3) & (mps - 1)) < 3) // cross page fixup?
|
||||
{
|
||||
r = get_le32(oimage + get_le32(wrkmem + 4 * (jc - 2)));
|
||||
fp[0] = 7;
|
||||
@@ -710,17 +645,13 @@ void PackWcle::decodeFixups()
|
||||
sofixups = ptr_udiff_bytes(fp, ofixups);
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::decodeFixupPageTable()
|
||||
{
|
||||
void PackWcle::decodeFixupPageTable() {
|
||||
ofpage_table = New(unsigned, sofpage_table = 1 + opages);
|
||||
set_le32(ofpage_table, 0);
|
||||
// the rest of ofpage_table is filled by decodeFixups()
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::decodeObjectTable()
|
||||
{
|
||||
void PackWcle::decodeObjectTable() {
|
||||
soobject_table = oimage[ph.u_len - 1];
|
||||
oobject_table = New(le_object_table_entry_t, soobject_table);
|
||||
unsigned jc, ic = soobject_table * sizeof(*oobject_table);
|
||||
@@ -730,8 +661,7 @@ void PackWcle::decodeObjectTable()
|
||||
if (ph.version >= 12)
|
||||
oh.automatic_data_object = oimage[ph.u_len - ic - 14];
|
||||
|
||||
for (ic = jc = 0; ic < soobject_table; ic++)
|
||||
{
|
||||
for (ic = jc = 0; ic < soobject_table; ic++) {
|
||||
OOT(ic, my_base_address) = jc;
|
||||
jc += (OOT(ic, virtual_size) + mps - 1) & ~(mps - 1);
|
||||
}
|
||||
@@ -753,9 +683,7 @@ void PackWcle::decodeObjectTable()
|
||||
oh.init_esp_offset = jc;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::decodeImage()
|
||||
{
|
||||
void PackWcle::decodeImage() {
|
||||
mb_oimage.allocForDecompression(ph.u_len);
|
||||
oimage = mb_oimage;
|
||||
|
||||
@@ -765,14 +693,11 @@ void PackWcle::decodeImage()
|
||||
oh.memory_page_size = mps;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::decodeEntryTable()
|
||||
{
|
||||
void PackWcle::decodeEntryTable() {
|
||||
unsigned count, object, n, r;
|
||||
SPAN_S_VAR(upx_byte, p, ientries, soentries);
|
||||
n = 0;
|
||||
while (*p)
|
||||
{
|
||||
while (*p) {
|
||||
count = *p;
|
||||
n += count;
|
||||
if (p[1] == 0) // unused bundle
|
||||
@@ -789,8 +714,7 @@ void PackWcle::decodeEntryTable()
|
||||
p += 4;
|
||||
for (; count; count--, p += 5)
|
||||
set_le32(p + 1, get_le32(p + 1) - OOT(object, my_base_address));
|
||||
}
|
||||
else
|
||||
} else
|
||||
throwCantUnpack("unsupported bundle type in entry table");
|
||||
}
|
||||
|
||||
@@ -802,9 +726,7 @@ void PackWcle::decodeEntryTable()
|
||||
ientries = nullptr;
|
||||
}
|
||||
|
||||
|
||||
int PackWcle::canUnpack()
|
||||
{
|
||||
int PackWcle::canUnpack() {
|
||||
if (!LeFile::readFileHeader())
|
||||
return false;
|
||||
fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET);
|
||||
@@ -816,11 +738,8 @@ int PackWcle::canUnpack()
|
||||
return readPackHeader(len) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
void PackWcle::virt2rela(const le_object_table_entry_t *entr,unsigned *objn,unsigned *addr)
|
||||
{
|
||||
for (; *objn > 1; objn[0]--)
|
||||
{
|
||||
void PackWcle::virt2rela(const le_object_table_entry_t *entr, unsigned *objn, unsigned *addr) {
|
||||
for (; *objn > 1; objn[0]--) {
|
||||
if (entr[*objn - 1].my_base_address > *addr)
|
||||
continue;
|
||||
*addr -= entr[*objn - 1].my_base_address;
|
||||
@@ -828,13 +747,11 @@ void PackWcle::virt2rela(const le_object_table_entry_t *entr,unsigned *objn,unsi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void PackWcle::unpack(OutputFile *fo)
|
||||
{
|
||||
void PackWcle::unpack(OutputFile *fo) {
|
||||
handleStub(fo);
|
||||
|
||||
readObjectTable();
|
||||
@@ -851,8 +768,7 @@ void PackWcle::unpack(OutputFile *fo)
|
||||
decodeObjectTable();
|
||||
|
||||
// unfilter
|
||||
if (ph.filter)
|
||||
{
|
||||
if (ph.filter) {
|
||||
const unsigned text_size = OOT(oh.init_cs_object - 1, npages) * mps;
|
||||
const unsigned text_vaddr = OOT(oh.init_cs_object - 1, my_base_address);
|
||||
|
||||
@@ -883,8 +799,7 @@ void PackWcle::unpack(OutputFile *fo)
|
||||
writeFile(fo, opt->watcom_le.le);
|
||||
|
||||
// copy the overlay
|
||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
||||
+ getImageSize();
|
||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset + getImageSize();
|
||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||
checkOverlay(overlay);
|
||||
copyOverlay(fo, overlay, mb_oimage);
|
||||
|
||||
+8
-8
@@ -25,24 +25,25 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_P_WCLE_H
|
||||
#define __UPX_P_WCLE_H 1
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_P_WCLE_H__
|
||||
#define UPX_P_WCLE_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// watcom/le
|
||||
**************************************************************************/
|
||||
|
||||
class PackWcle final : public Packer, public LeFile
|
||||
{
|
||||
class PackWcle final : public Packer, public LeFile {
|
||||
typedef Packer super;
|
||||
|
||||
public:
|
||||
PackWcle(InputFile *f) : super(f), LeFile(f) { bele = &N_BELE_RTP::le_policy; }
|
||||
virtual int getVersion() const override { return 13; }
|
||||
virtual int getFormat() const override { return UPX_F_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 *getFilters() const override;
|
||||
|
||||
@@ -87,7 +88,6 @@ protected:
|
||||
unsigned neweip;
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
Reference in New Issue
Block a user