mirror of https://github.com/upx/upx.git
Initial lzma support.
This commit is contained in:
parent
ee9f8c184b
commit
34ae413607
195
src/compress.ch
195
src/compress.ch
|
@ -66,6 +66,184 @@ unsigned upx_crc32(const void *buf, unsigned len, unsigned crc)
|
|||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if defined(ALG_LZMA)
|
||||
|
||||
#undef MSDOS
|
||||
#undef OS2
|
||||
#undef _WIN32
|
||||
#undef _WIN32_WCE
|
||||
#include "lzma/MyInitGuid.h"
|
||||
//#include "lzma/LZMADecoder.h"
|
||||
#include "lzma/LZMAEncoder.h"
|
||||
#undef RC_NORMALIZE
|
||||
|
||||
|
||||
struct CInStreamRam: public ISequentialInStream, public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
const Byte *Data; size_t Size; size_t Pos;
|
||||
void Init(const Byte *data, size_t size) {
|
||||
Data = data; Size = size; Pos = 0;
|
||||
}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 remain = Size - Pos;
|
||||
if (size > remain) size = remain;
|
||||
memmove(data, Data + Pos, size);
|
||||
Pos += size;
|
||||
if (processedSize != NULL) *processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct COutStreamRam : public ISequentialOutStream, public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
Byte *Data; size_t Size; size_t Pos; bool Overflow;
|
||||
void Init(Byte *data, size_t size) {
|
||||
Data = data; Size = size; Pos = 0; Overflow = false;
|
||||
}
|
||||
HRESULT WriteByte(Byte b) {
|
||||
if (Pos >= Size) { Overflow = true; return E_FAIL; }
|
||||
Data[Pos++] = b;
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < size && Pos < Size; i++)
|
||||
Data[Pos++] = ((const Byte *)data)[i];
|
||||
if (processedSize != NULL) *processedSize = i;
|
||||
if (i != size) { Overflow = true; return E_FAIL; }
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int upx_lzma_compress ( const upx_bytep src, upx_uint src_len,
|
||||
upx_bytep dst, upx_uintp dst_len,
|
||||
upx_progress_callback_t *cb,
|
||||
int level,
|
||||
const struct upx_compress_config_t *conf_parm,
|
||||
upx_uintp result )
|
||||
{
|
||||
UNUSED(cb); UNUSED(level);
|
||||
UNUSED(conf_parm); UNUSED(result);
|
||||
|
||||
int r = UPX_E_ERROR;
|
||||
HRESULT rh;
|
||||
|
||||
CInStreamRam* isp = new CInStreamRam;
|
||||
CInStreamRam& is = *isp;
|
||||
COutStreamRam* osp = new COutStreamRam;
|
||||
COutStreamRam& os = *osp;
|
||||
is.Init(src, src_len);
|
||||
// os.Init(dst, *dst_len);
|
||||
os.Init(dst, src_len);
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
|
||||
NCompress::NLZMA::CEncoder enc;
|
||||
PROPID propIDs[] = {
|
||||
NCoderPropID::kAlgorithm,
|
||||
NCoderPropID::kDictionarySize,
|
||||
NCoderPropID::kNumFastBytes,
|
||||
};
|
||||
const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
|
||||
PROPVARIANT properties[kNumProps];
|
||||
properties[0].vt = VT_UI4;
|
||||
properties[1].vt = VT_UI4;
|
||||
properties[2].vt = VT_UI4;
|
||||
properties[0].ulVal = (UInt32)2;
|
||||
// properties[1].ulVal = (UInt32)dictionarySize;
|
||||
properties[1].ulVal = (UInt32)1024 * 1024; // FIXME
|
||||
properties[2].ulVal = (UInt32)64;
|
||||
|
||||
if (enc.SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
|
||||
goto error;
|
||||
if (enc.WriteCoderProperties(&os) != S_OK)
|
||||
goto error;
|
||||
if (os.Pos != 5)
|
||||
goto error;
|
||||
|
||||
rh = enc.Code(&is, &os, 0, 0, 0);
|
||||
if (rh == E_OUTOFMEMORY)
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
#if 0
|
||||
else if (os.Overflow)
|
||||
r = UPX_E_OUPUT_OVERRUN; // FIXME - not compressible
|
||||
#endif
|
||||
else if (rh == S_OK)
|
||||
r = UPX_E_OK;
|
||||
error:
|
||||
*dst_len = os.Pos;
|
||||
return r;
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
} catch(...) { return UPX_E_OUT_OF_MEMORY; }
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#include "lzma/Alloc.cpp"
|
||||
#include "lzma/CRC.cpp"
|
||||
//#include "lzma/LZMADecoder.cpp"
|
||||
#include "lzma/LZMAEncoder.cpp"
|
||||
#include "lzma/LZInWindow.cpp"
|
||||
#include "lzma/OutBuffer.cpp"
|
||||
#include "lzma/RangeCoderBit.cpp"
|
||||
#include "lzma/StreamUtils.cpp"
|
||||
|
||||
|
||||
|
||||
#undef _LZMA_IN_CB
|
||||
#undef _LZMA_OUT_READ
|
||||
#undef _LZMA_PROB32
|
||||
#undef _LZMA_LOC_OPT
|
||||
#include "lzma/LzmaDecode.cpp"
|
||||
|
||||
static
|
||||
int upx_lzma_decompress ( const upx_bytep src, upx_uint src_len,
|
||||
upx_bytep dst, upx_uintp dst_len )
|
||||
{
|
||||
CLzmaDecoderState s;
|
||||
SizeT src_out = 0, dst_out = 0;
|
||||
int r;
|
||||
|
||||
s.Probs = NULL;
|
||||
#if defined(LzmaDecoderInit)
|
||||
LzmaDecoderInit(&s);
|
||||
#endif
|
||||
r = LzmaDecodeProperties(&s.Properties, src, src_len);
|
||||
if (r != 0)
|
||||
goto error;
|
||||
src += LZMA_PROPERTIES_SIZE; src_len -= LZMA_PROPERTIES_SIZE;
|
||||
s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties));
|
||||
if (!s.Probs)
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
else
|
||||
r = LzmaDecode(&s, src, src_len, &src_out, dst, *dst_len, &dst_out);
|
||||
error:
|
||||
*dst_len = dst_out;
|
||||
free(s.Probs);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
@ -133,6 +311,11 @@ int upx_compress ( const upx_bytep src, upx_uint src_len,
|
|||
r = cl1b_compress(src, src_len, dst, dst_len,
|
||||
cb, level, &conf, result);
|
||||
#endif /*}*/
|
||||
#if defined(ALG_LZMA)
|
||||
else if M_IS_LZMA(method)
|
||||
r = upx_lzma_compress(src, src_len, dst, dst_len,
|
||||
cb, level, &conf, result);
|
||||
#endif
|
||||
else
|
||||
throwInternalError("unknown compression method");
|
||||
|
||||
|
@ -196,6 +379,11 @@ int upx_decompress ( const upx_bytep src, upx_uint src_len,
|
|||
r = cl1b_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
||||
break;
|
||||
#endif /*}*/
|
||||
#if defined(ALG_LZMA)
|
||||
case M_LZMA:
|
||||
r = upx_lzma_decompress(src,src_len,dst,dst_len);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
break;
|
||||
|
@ -261,6 +449,13 @@ int upx_test_overlap ( const upx_bytep buf, upx_uint src_off,
|
|||
r = cl1b_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
||||
break;
|
||||
#endif /*}*/
|
||||
#if defined(ALG_LZMA)
|
||||
case M_LZMA:
|
||||
/* FIXME */
|
||||
if (src_off >= 256)
|
||||
r = UPX_E_OK;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
break;
|
||||
|
|
|
@ -29,10 +29,13 @@
|
|||
#include "conf.h"
|
||||
|
||||
|
||||
#if defined(WITH_LZMA)
|
||||
# define ALG_LZMA 1
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
# include "compress_nrv.ch"
|
||||
#elif defined(WITH_UCL)
|
||||
# define ALG_NRV2E
|
||||
# define ALG_NRV2E 1
|
||||
# define upx_adler32 upx_adler32
|
||||
//# define upx_crc32 upx_crc32
|
||||
# define upx_compress upx_compress
|
||||
|
|
|
@ -173,6 +173,9 @@
|
|||
#if defined(WITH_NRV)
|
||||
# include <nrv/nrvconf.h>
|
||||
#endif
|
||||
#if 1 && !defined(WITH_LZMA)
|
||||
# define WITH_LZMA 1
|
||||
#endif
|
||||
#if !defined(__UPX_CHECKER)
|
||||
# if defined(__UCL_CHECKER) || defined(__NRV_CHECKER)
|
||||
# define __UPX_CHECKER
|
||||
|
@ -429,11 +432,13 @@ inline void operator delete[](void *p)
|
|||
#define M_CL1B_LE32 11
|
||||
#define M_CL1B_8 12
|
||||
#define M_CL1B_LE16 13
|
||||
#define M_LZMA 14
|
||||
|
||||
#define M_IS_NRV2B(x) ((x) >= M_NRV2B_LE32 && (x) <= M_NRV2B_LE16)
|
||||
#define M_IS_NRV2D(x) ((x) >= M_NRV2D_LE32 && (x) <= M_NRV2D_LE16)
|
||||
#define M_IS_NRV2E(x) ((x) >= M_NRV2E_LE32 && (x) <= M_NRV2E_LE16)
|
||||
#define M_IS_CL1B(x) ((x) >= M_CL1B_LE32 && (x) <= M_CL1B_LE16)
|
||||
#define M_IS_LZMA(x) ((x) == M_LZMA)
|
||||
|
||||
|
||||
// Executable formats. Note: big endian types are >= 128.
|
||||
|
|
|
@ -511,6 +511,10 @@ static int do_option(int optc, const char *arg)
|
|||
if (!set_method(M_NRV2E_LE32, -1))
|
||||
e_method(M_NRV2E_LE32, opt->level);
|
||||
break;
|
||||
case 721:
|
||||
if (!set_method(M_LZMA, -1))
|
||||
e_method(M_LZMA, opt->level);
|
||||
break;
|
||||
|
||||
// compression level
|
||||
case '1':
|
||||
|
@ -824,6 +828,7 @@ static const struct mfx_option longopts[] =
|
|||
{"nrv2b", 0x10, 0, 702}, // --nrv2b
|
||||
{"nrv2d", 0x10, 0, 704}, // --nrv2d
|
||||
{"nrv2e", 0x10, 0, 705}, // --nrv2e
|
||||
{"lzma", 0x10, 0, 721}, // --lzma
|
||||
// compression settings
|
||||
{"all-filters", 0x10, 0, 523},
|
||||
{"all-methods", 0x10, 0, 524},
|
||||
|
|
|
@ -197,11 +197,14 @@ PackLinuxElf64amd::getCompressionMethods(int method, int level) const
|
|||
// No real dependency on LE32.
|
||||
static const int m_nrv2b[] = { M_NRV2B_LE32, M_NRV2E_LE32, -1 };
|
||||
static const int m_nrv2e[] = { M_NRV2E_LE32, M_NRV2B_LE32, -1 };
|
||||
static const int m_lzma[] = { M_LZMA,-1 };
|
||||
|
||||
if (M_IS_NRV2B(method))
|
||||
return m_nrv2b;
|
||||
if (M_IS_NRV2E(method))
|
||||
return m_nrv2e;
|
||||
if (M_IS_LZMA(method))
|
||||
return m_lzma;
|
||||
if (1==level)
|
||||
return m_nrv2b;
|
||||
return m_nrv2e;
|
||||
|
|
|
@ -942,7 +942,7 @@ unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image,
|
|||
|
||||
bool Packer::isValidCompressionMethod(int method)
|
||||
{
|
||||
return (method >= M_NRV2B_LE32 && method <= M_CL1B_LE16);
|
||||
return (method >= M_NRV2B_LE32 && method <= M_LZMA);
|
||||
}
|
||||
|
||||
|
||||
|
@ -952,6 +952,7 @@ const int *Packer::getDefaultCompressionMethods_8(int method, int level, int sma
|
|||
static const int m_nrv2d[] = { M_NRV2D_8, M_NRV2B_8, M_NRV2E_8, -1 };
|
||||
static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, M_NRV2D_8, -1 };
|
||||
static const int m_cl1b[] = { M_CL1B_8, -1 };
|
||||
static const int m_lzma[] = { M_LZMA, -1 };
|
||||
|
||||
if (small < 0)
|
||||
small = file_size <= 512*1024;
|
||||
|
@ -963,6 +964,8 @@ const int *Packer::getDefaultCompressionMethods_8(int method, int level, int sma
|
|||
return m_nrv2e;
|
||||
if (M_IS_CL1B(method))
|
||||
return m_cl1b;
|
||||
if (M_IS_LZMA(method))
|
||||
return m_lzma;
|
||||
if (level == 1 || small)
|
||||
return m_nrv2b;
|
||||
return m_nrv2e;
|
||||
|
@ -975,6 +978,7 @@ const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int
|
|||
static const int m_nrv2d[] = { M_NRV2D_LE32, M_NRV2B_LE32, M_NRV2E_LE32, -1 };
|
||||
static const int m_nrv2e[] = { M_NRV2E_LE32, M_NRV2B_LE32, M_NRV2D_LE32, -1 };
|
||||
static const int m_cl1b[] = { M_CL1B_LE32, -1 };
|
||||
static const int m_lzma[] = { M_LZMA, -1 };
|
||||
|
||||
if (small < 0)
|
||||
small = file_size <= 512*1024;
|
||||
|
@ -986,6 +990,8 @@ const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int
|
|||
return m_nrv2e;
|
||||
if (M_IS_CL1B(method))
|
||||
return m_cl1b;
|
||||
if (M_IS_LZMA(method))
|
||||
return m_lzma;
|
||||
if (level == 1 || small)
|
||||
return m_nrv2b;
|
||||
return m_nrv2e;
|
||||
|
@ -1224,6 +1230,10 @@ const char *Packer::getDecompressor() const
|
|||
"CL1LEN01,CL1FAS1B,"
|
||||
"CL1LEN02,"
|
||||
"CL1COPY0";
|
||||
static const char lzma_fast[] =
|
||||
"LZMA_SMALL"; // FIXME
|
||||
static const char lzma_small[] =
|
||||
"LZMA_SMALL";
|
||||
|
||||
if (ph.method == M_NRV2B_LE32)
|
||||
return opt->small ? nrv2b_le32_small : nrv2b_le32_fast;
|
||||
|
@ -1233,6 +1243,8 @@ const char *Packer::getDecompressor() const
|
|||
return opt->small ? nrv2e_le32_small : nrv2e_le32_fast;
|
||||
if (ph.method == M_CL1B_LE32)
|
||||
return opt->small ? cl1b_le32_small : cl1b_le32_fast;
|
||||
if (ph.method == M_LZMA)
|
||||
return opt->small ? lzma_small : lzma_fast;
|
||||
throwInternalError("bad decompressor");
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue