Initial lzma support.

This commit is contained in:
Markus F.X.J. Oberhumer 2006-06-07 04:42:15 +02:00
parent ee9f8c184b
commit 34ae413607
7 changed files with 226 additions and 2 deletions

View File

@ -1,5 +1,6 @@
syntax: regexp
^\.bzr
^ChangeLog
^build
^maint

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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},

View File

@ -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;

View File

@ -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;
}