src: clang-format various packers

This commit is contained in:
Markus F.X.J. Oberhumer
2022-11-26 17:45:25 +01:00
parent 93c6496ba8
commit 9f5d67e27c
13 changed files with 863 additions and 1275 deletions
+198 -301
View File
@@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#include "conf.h"
#include "file.h"
#include "filter.h"
@@ -33,23 +32,20 @@
#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
#define MAXMATCH 0x2000
#define MAXRELOCS (0x8000-MAXMATCH)
#define DI_LIMIT 0xff00 // see the assembly why
#define RSFCRI 4096 // Reserved Space For Compressed Relocation Info
#define MAXMATCH 0x2000
#define MAXRELOCS (0x8000 - MAXMATCH)
#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,10 +54,8 @@ PackExe::PackExe(InputFile *f) :
use_clear_dirty_stack = false;
}
const int *PackExe::getCompressionMethods(int method, int level) const
{
bool small = ih_imagesize <= 256*1024;
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;
// but note that class PackMaster creates per-file local options
@@ -70,16 +64,10 @@ const int *PackExe::getCompressionMethods(int method, int level) const
return Packer::getDefaultCompressionMethods_8(method, level, small);
}
const int *PackExe::getFilters() const { return nullptr; }
const int *PackExe::getFilters() const
{
return nullptr;
}
int PackExe::fillExeHeader(struct exe_header_t *eh) const
{
#define oh (*eh)
int PackExe::fillExeHeader(struct exe_header_t *eh) const {
#define oh (*eh)
// fill new exe header
int flag = 0;
if (!opt->dos_exe.no_reloc && !M_IS_LZMA(ph.method))
@@ -87,7 +75,7 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
if (ih.relocs == 0)
flag |= NORELOC;
memset(&oh,0,sizeof(oh));
memset(&oh, 0, sizeof(oh));
oh.ident = 'M' + 'Z' * 256;
oh.headsize16 = 2;
@@ -103,11 +91,10 @@ int PackExe::fillExeHeader(struct exe_header_t *eh) const
oh.sp = minsp;
unsigned destpara = (ph.u_len + ph.overlap_overhead - ph.c_len + 31) / 16;
oh.ss = ph.c_len/16 + destpara;
if (ih.ss*16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200)
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,61 +176,33 @@ 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
);
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);
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
);
else if M_IS_LZMA(ph.method)
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
throwInternalError("unknown compression method");
@@ -270,25 +210,22 @@ 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)
fi->readx(&ih, sizeof(ih));
if (ih.ident != 'M' + 'Z' * 256 && ih.ident != 'Z' + 'M' * 256)
return 0;
ih_exesize = ih.m512 + ih.p512*512 - (ih.m512 ? 512 : 0);
ih_exesize = ih.m512 + ih.p512 * 512 - (ih.m512 ? 512 : 0);
if (!ih_exesize) {
ih_exesize = file_size;
}
ih_imagesize = ih_exesize - ih.headsize16*16;
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,20 +235,17 @@ int PackExe::readFileHeader()
return UPX_F_DOS_EXE;
}
bool PackExe::canPack()
{
if (fn_has_ext(fi->getName(),"sys"))
bool PackExe::canPack() {
if (fn_has_ext(fi->getName(), "sys"))
return false;
if (!readFileHeader())
return false;
if (file_size < 1024)
throwCantPack("file is too small");
fi->seek(0x3c,SEEK_SET);
fi->seek(0x3c, SEEK_SET);
LE32 offs;
fi->readx(&offs,sizeof (offs));
if (ih.relocoffs >= 0x40 && offs)
{
fi->readx(&offs, sizeof(offs));
if (ih.relocoffs >= 0x40 && offs) {
if (opt->dos_exe.force_stub)
opt->overlay = opt->COPY_OVERLAY;
else
@@ -320,20 +254,16 @@ 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();
upx_byte * const crel_save = crel;
upx_byte *const crel_save = crel;
unsigned i;
unsigned seg_high = 0;
#if 0
@@ -345,14 +275,12 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
#endif
// pass 1 - find 0x9a bounds
for (i = 0; i < nrelocs; i++)
{
unsigned addr = get_le32(relocs+4*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)
{
unsigned seg = get_le16(b+addr);
if (addr >= 3 && b[addr - 3] == 0x9a) {
unsigned seg = get_le16(b + addr);
if (seg > seg_high)
seg_high = seg;
#if 0
@@ -371,10 +299,9 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
#endif
}
}
//printf("%d %d\n", seg_low, seg_high);
//printf("%d %d\n", off_low, off_high);
//printf("%d %d\n", linear_low, linear_high);
// printf("%d %d\n", seg_low, seg_high);
// printf("%d %d\n", off_low, off_high);
// printf("%d %d\n", linear_low, linear_high);
// pass 2 - reloc
@@ -383,37 +310,30 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
unsigned ones = 0;
unsigned es = 0, di, t;
i = 0;
do
{
unsigned addr = get_le32(relocs+4*i);
set_le16(crel,di = addr & 0x0f);
set_le16(crel+2,(addr >> 4) - es);
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++)
{
addr = get_le32(relocs+4*i);
//printf ("%x\n",es*16+di);
if ((addr - es*16 > 0xfffe)
|| (i == nrelocs - 1 && addr - es * 16 > 0xff00)
)
{
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)) {
// segment change
t = 1+(0xffff-di)/254;
memset(crel,1,t);
t = 1 + (0xffff - di) / 254;
memset(crel, 1, t);
crel += t;
ones += t-1; // -1 is used to help the assembly stuff
ones += t - 1; // -1 is used to help the assembly stuff
break;
}
unsigned offs = addr - es*16;
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)
unsigned offs = addr - es * 16;
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;
@@ -438,20 +357,18 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
} while (i < nrelocs);
*crel++ = 1;
ones++;
set_le16 (crel_save,ones);
set_le16 (crel_save+2,seg_high);
set_le16(crel_save, ones);
set_le16(crel_save + 2, seg_high);
//OutputFile::dump("x.rel", crel_save, crel - crel_save);
// OutputFile::dump("x.rel", crel_save, crel - crel_save);
return (unsigned) (crel - crel_save);
}
/*************************************************************************
//
**************************************************************************/
void PackExe::pack(OutputFile *fo)
{
void PackExe::pack(OutputFile *fo) {
unsigned ic;
if (ih.relocs > MAXRELOCS)
@@ -459,13 +376,13 @@ void PackExe::pack(OutputFile *fo)
checkOverlay(ih_overlay);
// alloc buffers
relocsize = RSFCRI + 4*ih.relocs;
ibuf.alloc(ih_imagesize+16+relocsize+2);
obuf.allocForCompression(ih_imagesize+16+relocsize+2);
relocsize = RSFCRI + 4 * ih.relocs;
ibuf.alloc(ih_imagesize + 16 + relocsize + 2);
obuf.allocForCompression(ih_imagesize + 16 + relocsize + 2);
// read image
fi->seek(ih.headsize16*16,SEEK_SET);
fi->readx(ibuf,ih_imagesize);
fi->seek(ih.headsize16 * 16, SEEK_SET);
fi->readx(ibuf, ih_imagesize);
checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u));
@@ -474,21 +391,19 @@ 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);
fi->seek(ih.relocoffs, SEEK_SET);
fi->readx(wr, 4 * ih.relocs);
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);
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);
}
qsort(wr,ih.relocs,4,le32_compare);
qsort(wr, ih.relocs, 4, le32_compare);
relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a);
set_le16(w+relocsize, relocsize+2);
set_le16(w + relocsize, relocsize + 2);
relocsize += 2;
if (relocsize > MAXRELOCS)
throwCantPack("too many relocations");
@@ -499,9 +414,7 @@ void PackExe::pack(OutputFile *fo)
ucl_nrv2b_99_compress(w, in_len, out, &out_len, nullptr, 9, nullptr, nullptr);
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,13 +434,11 @@ void PackExe::pack(OutputFile *fo)
throwCantPack("decompressor limit exceeded, send a bugreport");
#if TESTING
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,
0/*ph.min_run_found*/,ph.max_run_found);
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,
0 /*ph.min_run_found*/, ph.max_run_found);
}
#endif
@@ -534,22 +446,22 @@ void PackExe::pack(OutputFile *fo)
const unsigned lsize = getLoaderSize();
MemBuffer loader(lsize);
memcpy(loader,getLoader(),lsize);
//OutputFile::dump("xxloader.dat", loader, lsize);
memcpy(loader, getLoader(), lsize);
// OutputFile::dump("xxloader.dat", loader, lsize);
// patch loader
const unsigned packedsize = ph.c_len;
const unsigned e_len = getLoaderSectionStart("EXECUTPO");
const unsigned d_len = lsize - e_len;
assert((e_len&15) == 0);
assert((e_len & 15) == 0);
const unsigned copysize = (1+packedsize+d_len) & ~1;
const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000;
const unsigned copysize = (1 + packedsize + d_len) & ~1;
const unsigned firstcopy = copysize % 0x10000 ? copysize % 0x10000 : 0x10000;
// set oh.min & oh.max
ic = ih.min*16 + ih_imagesize;
if (ic < oh.ss*16u + oh.sp)
ic = oh.ss*16u + oh.sp;
ic = ih.min * 16 + ih_imagesize;
if (ic < oh.ss * 16u + oh.sp)
ic = oh.ss * 16u + oh.sp;
oh.min = (ic - (packedsize + lsize)) / 16;
ic = oh.min + (ih.max - ih.min);
oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff;
@@ -557,27 +469,23 @@ void PackExe::pack(OutputFile *fo)
// set extra info
unsigned char extra_info[9];
unsigned eisize = 0;
if (oh.ss != ih.ss)
{
set_le16(extra_info+eisize,ih.ss);
if (oh.ss != ih.ss) {
set_le16(extra_info + eisize, ih.ss);
eisize += 2;
assert((flag & SS) != 0); // set in fillExeHeader()
assert((flag & SS) != 0); // set in fillExeHeader()
}
if (oh.sp != ih.sp)
{
set_le16(extra_info+eisize,ih.sp);
if (oh.sp != ih.sp) {
set_le16(extra_info + eisize, ih.sp);
eisize += 2;
assert((flag & SP) != 0); // set in fillExeHeader()
assert((flag & SP) != 0); // set in fillExeHeader()
}
if (ih.min != oh.min)
{
set_le16(extra_info+eisize,ih.min);
if (ih.min != oh.min) {
set_le16(extra_info + eisize, ih.min);
eisize += 2;
flag |= MINMEM;
}
if (ih.max != oh.max)
{
set_le16(extra_info+eisize,ih.max);
if (ih.max != oh.max) {
set_le16(extra_info + eisize, ih.max);
eisize += 2;
flag |= MAXMEM;
}
@@ -592,28 +500,25 @@ 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;
}
// g++ 3.1 does not like the following line...
oh.relocoffs = offsetof(exe_header_t, firstreloc);
//oh.relocoffs = ptr_udiff_bytes(&oh.firstreloc, &oh);
// oh.relocoffs = ptr_udiff_bytes(&oh.firstreloc, &oh);
linker->defineSymbol("destination_segment", oh.ss - ph.c_len / 16 - e_len / 16);
linker->defineSymbol("source_segment", e_len / 16 + (copysize - firstcopy) / 16);
linker->defineSymbol("copy_offset", firstcopy - 2);
linker->defineSymbol("words_to_copy",firstcopy / 2);
linker->defineSymbol("words_to_copy", firstcopy / 2);
linker->defineSymbol("exe_stack_sp", oh.sp);
linker->defineSymbol("exe_stack_ss", oh.ss);
@@ -621,7 +526,7 @@ void PackExe::pack(OutputFile *fo)
linker->defineSymbol("attribute", get_le16(ibuf + 4));
linker->defineSymbol("orig_strategy", get_le16(ibuf + 6));
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;
const unsigned outputlen = sizeof(oh) + lsize + packedsize + eisize;
oh.m512 = outputlen & 511;
oh.p512 = (outputlen + 511) >> 9;
@@ -631,20 +536,21 @@ void PackExe::pack(OutputFile *fo)
defineDecompressorSymbols();
relocateLoader();
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader,e_len);
patchPackHeader(loader, e_len);
//fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize);
// fprintf(stderr,"\ne_len=%x d_len=%x c_len=%x oo=%x ulen=%x destp=%x copys=%x
// images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize);
// write header + write loader + compressed file
#if TESTING
if (opt->debug.debug_level)
printf("\n%d %d %d %d\n",(int)sizeof(oh),e_len,packedsize,d_len);
printf("\n%d %d %d %d\n", (int) sizeof(oh), e_len, packedsize, d_len);
#endif
fo->write(&oh,sizeof(oh));
fo->write(loader,e_len); // entry
fo->write(obuf,packedsize);
fo->write(loader+e_len,d_len); // decompressor
fo->write(extra_info,eisize);
fo->write(&oh, sizeof(oh));
fo->write(loader, e_len); // entry
fo->write(obuf, packedsize);
fo->write(loader + e_len, d_len); // decompressor
fo->write(extra_info, eisize);
assert(eisize <= 9);
#if 0
printf("%-13s: program hdr : %8ld bytes\n", getName(), (long) sizeof(oh));
@@ -659,20 +565,18 @@ void PackExe::pack(OutputFile *fo)
// copy the overlay
copyOverlay(fo, ih_overlay, obuf);
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
// fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
// finally check the compression ratio
if (!checkFinalCompressionRatio(fo))
throwNotCompressible();
}
/*************************************************************************
//
**************************************************************************/
int PackExe::canUnpack()
{
int PackExe::canUnpack() {
if (!readFileHeader())
return false;
const unsigned off = ih.headsize16 * 16;
@@ -681,19 +585,17 @@ 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);
// read the file
fi->seek(ih.headsize16*16,SEEK_SET);
fi->readx(ibuf,ih_imagesize);
fi->seek(ih.headsize16 * 16, SEEK_SET);
fi->readx(ibuf, ih_imagesize);
// get compressed data offset
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
@@ -703,7 +605,7 @@ void PackExe::unpack(OutputFile *fo)
checkOverlay(ih_overlay);
// decompress
decompress(ibuf+e_len,obuf);
decompress(ibuf + e_len, obuf);
unsigned imagesize = ih_imagesize;
imagesize--;
@@ -713,82 +615,81 @@ void PackExe::unpack(OutputFile *fo)
SPAN_S_VAR(upx_byte, relocs, obuf + ph.u_len, obuf);
MemBuffer wrkmem;
if (!(flag & NORELOC))
{
relocs -= get_le16(obuf+ph.u_len-2);
if (!(flag & NORELOC)) {
relocs -= get_le16(obuf + ph.u_len - 2);
ph.u_len -= 2;
wrkmem.alloc(4*MAXRELOCS);
wrkmem.alloc(4 * MAXRELOCS);
unsigned es = 0, ones = get_le16(relocs);
const unsigned seghi = get_le16(relocs+2);
const unsigned seghi = get_le16(relocs + 2);
SPAN_S_VAR(const upx_byte, p, relocs + 4);
while (ones)
{
while (ones) {
unsigned di = get_le16(p);
es += get_le16(p+2);
es += get_le16(p + 2);
bool dorel = true;
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);
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++)
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)
{
di = ptr_diff_bytes(q, obuf + es * 16) + 3;
} else if (*p == 1) {
di += 254;
if (di < 0x10000)
ones--;
dorel = false;
}
else
} else
di += *p;
}
}
}
// fill new exe header
memset(&oh,0,sizeof(oh));
oh.ident = 'M' + 'Z'*256;
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);
set_le32(wrkmem + 4 * relocn++, 0);
}
unsigned outputlen = ptr_udiff_bytes(relocs, obuf) + sizeof(oh) + relocn*4;
unsigned outputlen = ptr_udiff_bytes(relocs, obuf) + sizeof(oh) + relocn * 4;
oh.m512 = outputlen & 511;
oh.p512 = (outputlen + 511) >> 9;
oh.headsize16 = 2+relocn/4;
oh.headsize16 = 2 + relocn / 4;
oh.max = ih.max;
oh.min = ih.min;
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;
unsigned ip = (flag & USEJUMP) ? get_le32(ibuf + imagesize - 4) : (unsigned) ih.firstreloc;
oh.ip = ip & 0xffff;
oh.cs = ip >> 16;
@@ -798,20 +699,16 @@ void PackExe::unpack(OutputFile *fo)
return;
// write header + relocations + uncompressed file
fo->write(&oh,sizeof(oh));
fo->write(&oh, sizeof(oh));
if (relocn)
fo->write(wrkmem,relocn*4);
fo->write(wrkmem, relocn * 4);
fo->write(obuf, ptr_diff_bytes(relocs, obuf));
// copy the overlay
copyOverlay(fo, ih_overlay, obuf);
}
Linker* PackExe::newLinker() const
{
return new ElfLinkerX86();
}
Linker *PackExe::newLinker() const { return new ElfLinkerX86(); }
/*