mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Merge branch 'devel' of https://github.com/upx/upx into devel
This commit is contained in:
commit
0e329336fc
|
@ -19,7 +19,7 @@ environment:
|
|||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
- where bash & where cat & where curl & where git & where sed & where tar
|
||||
- where bash & where cat & where curl & where git & where gzip & where readlink & where sed & where sha256sum & where tar
|
||||
# - bash --version & git --version & sed --version & tar --version
|
||||
- git --version & bash --version
|
||||
# - dir "c:\Program Files\Git\usr\bin"
|
||||
|
|
2
NEWS
2
NEWS
|
@ -2,7 +2,7 @@
|
|||
User visible changes for UPX
|
||||
==================================================================
|
||||
|
||||
Changes in 3.92 (XX XXX 2016):
|
||||
Changes in 3.92 (27 Nov 2016):
|
||||
* UPX has moved to GitHub - the new home page is https://upx.github.io
|
||||
* All pe formats: important internal changes - reunited the diverged
|
||||
source files - please report regressions into the bug tracker.
|
||||
|
|
|
@ -162,7 +162,7 @@ endif
|
|||
|
||||
# automatically format some C++ source code files
|
||||
ifeq ($(shell uname),Linux)
|
||||
CLANG_FORMAT_FILES += packhead.cpp
|
||||
CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp
|
||||
CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h
|
||||
CLANG_FORMAT_FILES += snprintf.cpp
|
||||
CLANG_FORMAT_FILES += stdcxx.cpp stdcxx.h
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#if (ACC_CC_MSC && (_MSC_VER < 1900))
|
||||
# pragma warning(disable: 4127) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
#if (ACC_CC_INTELC_GNUC)
|
||||
# pragma warning(error: 424) // #424: extra ";" ignored
|
||||
#endif
|
||||
|
||||
|
||||
void lzma_compress_config_t::reset()
|
||||
|
@ -54,15 +57,6 @@ void lzma_compress_config_t::reset()
|
|||
}
|
||||
|
||||
|
||||
#if !(WITH_LZMA)
|
||||
extern int compress_lzma_dummy;
|
||||
int compress_lzma_dummy = 0;
|
||||
#else
|
||||
#define opt compress_lzma_opt
|
||||
|
||||
#undef USE_LZMA_PROPERTIES
|
||||
|
||||
|
||||
// INFO: the LZMA SDK is covered by a permissive license which allows
|
||||
// using unmodified LZMA source code in UPX and the UPX stubs.
|
||||
// See SPECIAL EXCEPTION below.
|
||||
|
@ -100,28 +94,6 @@ int compress_lzma_dummy = 0;
|
|||
// while you keep LZMA SDK code unmodified.
|
||||
|
||||
|
||||
#if (WITH_LZMA >= 0x461)
|
||||
#include "C/7zVersion.h"
|
||||
#if (WITH_LZMA != ((0x1000 * (MY_VER_MAJOR / 10)) + (0x0100 * (MY_VER_MAJOR % 10)) +\
|
||||
(0x0010 * (MY_VER_MINOR / 10)) + (0x0001 * (MY_VER_MINOR % 10))))
|
||||
# error "WITH_LZMA version mismatch"
|
||||
#endif
|
||||
|
||||
#if (WITH_LZMA >= 0x938)
|
||||
#include "C/7zTypes.h"
|
||||
#else
|
||||
#include "C/Types.h"
|
||||
#endif
|
||||
|
||||
static void *cb_alloc(void *, size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
static void cb_free(void *, void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// compress defaults
|
||||
**************************************************************************/
|
||||
|
@ -138,13 +110,12 @@ static int prepare(lzma_compress_result_t *res,
|
|||
res->fast_mode = 2;
|
||||
res->num_fast_bytes = 64; // 5 .. 273
|
||||
res->match_finder_cycles = 0;
|
||||
#if 1
|
||||
// UPX overrides
|
||||
res->pos_bits = lzma_compress_config_t::pos_bits_t::default_value_c;
|
||||
res->lit_pos_bits = lzma_compress_config_t::lit_pos_bits_t::default_value_c;
|
||||
res->lit_context_bits = lzma_compress_config_t::lit_context_bits_t::default_value_c;
|
||||
res->dict_size = lzma_compress_config_t::dict_size_t::default_value_c;
|
||||
res->num_fast_bytes = lzma_compress_config_t::num_fast_bytes_t::default_value_c;
|
||||
#endif
|
||||
// method overrides
|
||||
if (method >= 0x100) {
|
||||
res->pos_bits = (method >> 16) & 15;
|
||||
|
@ -159,7 +130,7 @@ static int prepare(lzma_compress_result_t *res,
|
|||
res->lit_context_bits = 8;
|
||||
#endif
|
||||
|
||||
// FIXME: tune these settings according to level
|
||||
// TODO: tune these settings according to level
|
||||
switch (level)
|
||||
{
|
||||
case 1:
|
||||
|
@ -239,129 +210,19 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// compress
|
||||
**************************************************************************/
|
||||
|
||||
#if (WITH_LZMA >= 0x461)
|
||||
#define _7ZIP_ST 1
|
||||
#define kLiteralNextStates kLiteralNextStates_enc
|
||||
#include "C/LzmaEnc.h"
|
||||
#include "C/LzmaEnc.c"
|
||||
#include "C/LzFind.c"
|
||||
#undef kLiteralNextStates
|
||||
#undef kNumFullDistances
|
||||
|
||||
|
||||
struct upx_ICompressProgress {
|
||||
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||
upx_callback_p cb;
|
||||
};
|
||||
|
||||
static SRes cb_progress(void *p, UInt64 inSize, UInt64 outSize) {
|
||||
upx_callback_p cb = ((upx_ICompressProgress *) p)->cb;
|
||||
if (cb && cb->nprogress)
|
||||
cb->nprogress(cb, (unsigned) inSize, (unsigned) outSize);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf_parm,
|
||||
upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(M_IS_LZMA(method));
|
||||
assert(level > 0); assert(cresult != NULL);
|
||||
COMPILE_TIME_ASSERT(LZMA_PROPS_SIZE == 5)
|
||||
|
||||
int r = UPX_E_ERROR;
|
||||
int rh;
|
||||
|
||||
unsigned dst_avail = *dst_len;
|
||||
*dst_len = 0;
|
||||
|
||||
ISzAlloc cba; cba.Alloc = cb_alloc; cba.Free = cb_free;
|
||||
upx_ICompressProgress progress;
|
||||
progress.Progress = cb_progress; progress.cb = cb;
|
||||
|
||||
const lzma_compress_config_t *lcconf = cconf_parm ? &cconf_parm->conf_lzma : NULL;
|
||||
lzma_compress_result_t *res = &cresult->result_lzma;
|
||||
if (prepare(res, src_len, method, level, lcconf) != 0)
|
||||
goto error;
|
||||
|
||||
CLzmaEncProps props; memset(&props, 0, sizeof(props));
|
||||
props.level = level;
|
||||
LzmaEncProps_Init(&props);
|
||||
props.pb = res->pos_bits;
|
||||
props.lp = res->lit_pos_bits;
|
||||
props.lc = res->lit_context_bits;
|
||||
props.dictSize = res->dict_size;
|
||||
props.algo = res->fast_mode ? 1 : 0;
|
||||
props.fb = res->num_fast_bytes;
|
||||
props.mc = res->match_finder_cycles;
|
||||
|
||||
unsigned char props_buf[LZMA_PROPS_SIZE];
|
||||
SizeT props_buf_size; props_buf_size = LZMA_PROPS_SIZE;
|
||||
|
||||
#if (USE_LZMA_PROPERTIES)
|
||||
if (dst_avail < 1)
|
||||
goto error;
|
||||
dst[0] = 0; // filled below
|
||||
dst += 1; *dst_len += 1; dst_avail -= 1;
|
||||
#else
|
||||
if (dst_avail < 2)
|
||||
goto error;
|
||||
// extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||
unsigned tt; tt = res->lit_context_bits + res->lit_pos_bits;
|
||||
dst[0] = ((tt << 3) | res->pos_bits);
|
||||
dst[1] = ((res->lit_pos_bits << 4) | (res->lit_context_bits));
|
||||
dst += 2; *dst_len += 2; dst_avail -= 2;
|
||||
#endif
|
||||
SizeT x_len; x_len = dst_avail;
|
||||
rh = LzmaEncode(dst, &x_len, src, src_len,
|
||||
&props, props_buf, &props_buf_size, 0,
|
||||
(ICompressProgress *) (void *) &progress, &cba, &cba);
|
||||
assert(x_len <= dst_avail);
|
||||
*dst_len += x_len;
|
||||
if (rh == SZ_OK) {
|
||||
#if (USE_LZMA_PROPERTIES)
|
||||
dst[-1] = props_buf[0];
|
||||
#endif
|
||||
r = UPX_E_OK;
|
||||
}
|
||||
|
||||
error:
|
||||
//printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif /* (WITH_LZMA >= 0x461) */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// compress - cruft because of pseudo-COM layer
|
||||
**************************************************************************/
|
||||
|
||||
#if (WITH_LZMA < 0x461)
|
||||
|
||||
#undef MSDOS
|
||||
#undef OS2
|
||||
#undef _WIN32
|
||||
#undef _WIN32_WCE
|
||||
#undef COMPRESS_MF_MT
|
||||
#undef _NO_EXCEPTIONS
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# define INITGUID 1
|
||||
//# include "CPP/7zip/Compress/LZMA/LZMADecoder.h"
|
||||
# include "CPP/7zip/Compress/LZMA/LZMAEncoder.h"
|
||||
#else
|
||||
# include "C/Common/MyInitGuid.h"
|
||||
//# include "C/7zip/Compress/LZMA/LZMADecoder.h"
|
||||
# include "C/7zip/Compress/LZMA/LZMAEncoder.h"
|
||||
#endif
|
||||
#include "C/Common/MyInitGuid.h"
|
||||
//#include "C/7zip/Compress/LZMA/LZMADecoder.h"
|
||||
#include "C/7zip/Compress/LZMA/LZMAEncoder.h"
|
||||
|
||||
namespace MyLzma {
|
||||
|
||||
|
@ -380,7 +241,7 @@ STDMETHODIMP InStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
|||
{
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain) size = (UInt32) remain;
|
||||
memcpy(data, b_buf + b_pos, size);
|
||||
memmove(data, b_buf + b_pos, size);
|
||||
b_pos += size;
|
||||
if (processedSize != NULL) *processedSize = size;
|
||||
return S_OK;
|
||||
|
@ -406,7 +267,7 @@ STDMETHODIMP OutStream::Write(const void *data, UInt32 size, UInt32 *processedSi
|
|||
{
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain) size = (UInt32) remain, overflow = true;
|
||||
memcpy(b_buf + b_pos, data, size);
|
||||
memmove(b_buf + b_pos, data, size);
|
||||
b_pos += size;
|
||||
if (processedSize != NULL) *processedSize = size;
|
||||
return overflow ? E_FAIL : S_OK;
|
||||
|
@ -429,35 +290,16 @@ STDMETHODIMP ProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outS
|
|||
|
||||
} // namespace
|
||||
|
||||
|
||||
#if (ACC_CC_INTELC_GNUC)
|
||||
//# pragma warning(disable: 424) // #424: extra ";" ignored
|
||||
# pragma warning(error: 424) // #424: extra ";" ignored
|
||||
#endif
|
||||
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# include "C/Alloc.c"
|
||||
# include "C/7zCrc.c"
|
||||
# include "C/Compress/Lz/MatchFinder.c"
|
||||
//# include "CPP/7zip/Common/InBuffer.cpp"
|
||||
# include "CPP/7zip/Common/OutBuffer.cpp"
|
||||
# include "CPP/7zip/Common/StreamUtils.cpp"
|
||||
//# include "CPP/7zip/Compress/LZ/LZOutWindow.cpp"
|
||||
//# include "CPP/7zip/Compress/LZMA/LZMADecoder.cpp"
|
||||
# include "CPP/7zip/Compress/LZMA/LZMAEncoder.cpp"
|
||||
# include "CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp"
|
||||
#else
|
||||
# include "C/Common/Alloc.cpp"
|
||||
# include "C/Common/CRC.cpp"
|
||||
//# include "C/7zip/Common/InBuffer.cpp"
|
||||
# include "C/7zip/Common/OutBuffer.cpp"
|
||||
# include "C/7zip/Common/StreamUtils.cpp"
|
||||
# include "C/7zip/Compress/LZ/LZInWindow.cpp"
|
||||
//# include "C/7zip/Compress/LZ/LZOutWindow.cpp"
|
||||
//# include "C/7zip/Compress/LZMA/LZMADecoder.cpp"
|
||||
# include "C/7zip/Compress/LZMA/LZMAEncoder.cpp"
|
||||
# include "C/7zip/Compress/RangeCoder/RangeCoderBit.cpp"
|
||||
#endif
|
||||
#include "C/Common/Alloc.cpp"
|
||||
#include "C/Common/CRC.cpp"
|
||||
//#include "C/7zip/Common/InBuffer.cpp"
|
||||
#include "C/7zip/Common/OutBuffer.cpp"
|
||||
#include "C/7zip/Common/StreamUtils.cpp"
|
||||
#include "C/7zip/Compress/LZ/LZInWindow.cpp"
|
||||
//#include "C/7zip/Compress/LZ/LZOutWindow.cpp"
|
||||
//#include "C/7zip/Compress/LZMA/LZMADecoder.cpp"
|
||||
#include "C/7zip/Compress/LZMA/LZMAEncoder.cpp"
|
||||
#include "C/7zip/Compress/RangeCoder/RangeCoderBit.cpp"
|
||||
#undef RC_NORMALIZE
|
||||
|
||||
|
||||
|
@ -496,14 +338,10 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
|||
NCoderPropID::kMatchFinder // 7 mf
|
||||
};
|
||||
PROPVARIANT pr[8];
|
||||
#ifdef COMPRESS_MF_BT4
|
||||
const unsigned nprops = 8;
|
||||
static wchar_t matchfinder[] = L"BT4";
|
||||
assert(NCompress::NLZMA::FindMatchFinder(matchfinder) >= 0);
|
||||
pr[7].vt = VT_BSTR; pr[7].bstrVal = matchfinder;
|
||||
#else
|
||||
const unsigned nprops = 7;
|
||||
#endif
|
||||
pr[0].vt = pr[1].vt = pr[2].vt = pr[3].vt = VT_UI4;
|
||||
pr[4].vt = pr[5].vt = pr[6].vt = VT_UI4;
|
||||
if (prepare(res, src_len, method, level, lcconf) != 0)
|
||||
|
@ -516,11 +354,7 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
|||
pr[5].uintVal = res->num_fast_bytes;
|
||||
pr[6].uintVal = res->match_finder_cycles;
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
try {
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
if (enc.SetCoderProperties(propIDs, pr, nprops) != S_OK)
|
||||
goto error;
|
||||
|
@ -532,21 +366,17 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
|||
goto error;
|
||||
}
|
||||
assert(os.b_pos == 5);
|
||||
#if (USE_LZMA_PROPERTIES)
|
||||
os.b_pos = 1;
|
||||
#else
|
||||
os.b_pos = 0;
|
||||
// extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||
unsigned t = res->lit_context_bits + res->lit_pos_bits;
|
||||
os.WriteByte(Byte((t << 3) | res->pos_bits));
|
||||
os.WriteByte(Byte((res->lit_pos_bits << 4) | (res->lit_context_bits)));
|
||||
#endif
|
||||
|
||||
rh = enc.Code(&is, &os, NULL, NULL, &progress);
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
} catch (...) { rh = E_OUTOFMEMORY; }
|
||||
#endif
|
||||
} catch (...) {
|
||||
rh = E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
assert(is.b_pos <= src_len);
|
||||
assert(os.b_pos <= *dst_len);
|
||||
|
@ -571,121 +401,17 @@ error:
|
|||
return r;
|
||||
}
|
||||
|
||||
#endif /* (WITH_LZMA < 0x461) */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// decompress
|
||||
**************************************************************************/
|
||||
|
||||
#if (WITH_LZMA >= 0x461)
|
||||
|
||||
#undef _LZMA_PROB32
|
||||
#include "C/LzmaDec.h"
|
||||
#include "C/LzmaDec.c"
|
||||
|
||||
|
||||
int upx_lzma_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
#define Properties prop
|
||||
assert(M_IS_LZMA(method));
|
||||
// see res->num_probs above
|
||||
COMPILE_TIME_ASSERT(sizeof(CLzmaProb) == 2)
|
||||
COMPILE_TIME_ASSERT(LZMA_PROPS_SIZE == 5)
|
||||
COMPILE_TIME_ASSERT(LZMA_BASE_SIZE == 1846)
|
||||
COMPILE_TIME_ASSERT(LZMA_LIT_SIZE == 768)
|
||||
|
||||
ISzAlloc cba; cba.Alloc = cb_alloc; cba.Free = cb_free;
|
||||
CLzmaDec s; memset(&s, 0, sizeof(s));
|
||||
SizeT srcLen = 0;
|
||||
int r = UPX_E_ERROR;
|
||||
SRes rh;
|
||||
ELzmaStatus status;
|
||||
|
||||
#if (USE_LZMA_PROPERTIES)
|
||||
rh = LzmaProps_Decode(&s.Properties, src, src_len);
|
||||
if (rh != 0)
|
||||
goto error;
|
||||
src += 1; src_len -= 1;
|
||||
#else
|
||||
if (src_len < 3)
|
||||
goto error;
|
||||
s.Properties.pb = src[0] & 7;
|
||||
s.Properties.lp = (src[1] >> 4);
|
||||
s.Properties.lc = src[1] & 15;
|
||||
if (s.Properties.pb >= 5) goto error;
|
||||
if (s.Properties.lp >= 5) goto error;
|
||||
if (s.Properties.lc >= 9) goto error;
|
||||
// extra
|
||||
if ((src[0] >> 3) != (int)(s.Properties.lc + s.Properties.lp)) goto error;
|
||||
src += 2; src_len -= 2;
|
||||
#endif
|
||||
s.Properties.dicSize = 0;
|
||||
|
||||
if (cresult)
|
||||
{
|
||||
assert(cresult->method == method);
|
||||
assert(cresult->result_lzma.pos_bits == (unsigned) s.Properties.pb);
|
||||
assert(cresult->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp);
|
||||
assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc);
|
||||
assert(cresult->result_lzma.num_probs == (unsigned) LzmaProps_GetNumProbs(&s.Properties));
|
||||
const lzma_compress_result_t *res = &cresult->result_lzma;
|
||||
UNUSED(res);
|
||||
//printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs);
|
||||
}
|
||||
|
||||
rh = LzmaDec_AllocateProbs2(&s, &s.Properties, &cba);
|
||||
if (rh != SZ_OK)
|
||||
{
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
s.dic = dst; s.dicPos = 0; s.dicBufSize = *dst_len;
|
||||
LzmaDec_Init(&s);
|
||||
srcLen = src_len;
|
||||
rh = LzmaDec_DecodeToDic(&s, *dst_len, src, &srcLen, LZMA_FINISH_ANY, &status);
|
||||
assert(srcLen <= src_len);
|
||||
assert(s.dicPos <= *dst_len);
|
||||
if (rh == SZ_OK && status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
rh = SZ_ERROR_INPUT_EOF;
|
||||
if (rh == SZ_OK && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
{
|
||||
r = UPX_E_OK;
|
||||
if (srcLen != src_len)
|
||||
r = UPX_E_INPUT_NOT_CONSUMED;
|
||||
}
|
||||
error:
|
||||
*dst_len = s.dicPos;
|
||||
LzmaDec_FreeProbs(&s, &cba);
|
||||
return r;
|
||||
#undef Properties
|
||||
}
|
||||
|
||||
|
||||
#endif /* (WITH_LZMA >= 0x461) */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// decompress
|
||||
**************************************************************************/
|
||||
|
||||
#if (WITH_LZMA < 0x461)
|
||||
|
||||
#undef _LZMA_IN_CB
|
||||
#undef _LZMA_OUT_READ
|
||||
#undef _LZMA_PROB32
|
||||
#undef _LZMA_LOC_OPT
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# include "C/Compress/Lzma/LzmaDecode.h"
|
||||
# include "C/Compress/Lzma/LzmaDecode.c"
|
||||
#else
|
||||
# include "C/7zip/Compress/LZMA_C/LzmaDecode.h"
|
||||
# include "C/7zip/Compress/LZMA_C/LzmaDecode.c"
|
||||
#endif
|
||||
#include "C/7zip/Compress/LZMA_C/LzmaDecode.h"
|
||||
#include "C/7zip/Compress/LZMA_C/LzmaDecode.c"
|
||||
|
||||
int upx_lzma_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
|
@ -703,14 +429,6 @@ int upx_lzma_decompress ( const upx_bytep src, unsigned src_len,
|
|||
int r = UPX_E_ERROR;
|
||||
int rh;
|
||||
|
||||
#if (USE_LZMA_PROPERTIES)
|
||||
if (src_len < 2)
|
||||
goto error;
|
||||
rh = LzmaDecodeProperties(&s.Properties, src, src_len);
|
||||
if (rh != 0)
|
||||
goto error;
|
||||
src += 1; src_len -= 1;
|
||||
#else
|
||||
if (src_len < 3)
|
||||
goto error;
|
||||
s.Properties.pb = src[0] & 7;
|
||||
|
@ -722,7 +440,6 @@ int upx_lzma_decompress ( const upx_bytep src, unsigned src_len,
|
|||
// extra
|
||||
if ((src[0] >> 3) != s.Properties.lc + s.Properties.lp) goto error;
|
||||
src += 2; src_len -= 2;
|
||||
#endif
|
||||
|
||||
if (cresult)
|
||||
{
|
||||
|
@ -757,8 +474,6 @@ error:
|
|||
return r;
|
||||
}
|
||||
|
||||
#endif /* (WITH_LZMA < 0x461) */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
|
@ -801,16 +516,7 @@ int upx_lzma_init(void)
|
|||
|
||||
const char *upx_lzma_version_string(void)
|
||||
{
|
||||
#if (WITH_LZMA >= 0x461)
|
||||
# error "invalid WITH_LZMA version"
|
||||
return MY_VERSION;
|
||||
#elif (WITH_LZMA + 0 == 0x457)
|
||||
# error "invalid WITH_LZMA version"
|
||||
return "4.57";
|
||||
#elif (WITH_LZMA + 0 == 0x449)
|
||||
# error "invalid WITH_LZMA version"
|
||||
return "4.49";
|
||||
#elif (WITH_LZMA + 0 == 0x443)
|
||||
#if (WITH_LZMA == 0x443)
|
||||
return "4.43";
|
||||
#else
|
||||
# error "unknown WITH_LZMA version"
|
||||
|
@ -819,6 +525,4 @@ const char *upx_lzma_version_string(void)
|
|||
}
|
||||
|
||||
|
||||
#endif /* WITH_LZMA */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
|
|
@ -55,8 +55,13 @@
|
|||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((1u << 31) << 1 == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(((int)(1u << 31)) >> 31 == -1) // arithmetic right shift
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) > 0) // -funsigned-char
|
||||
|
||||
#if (ACC_CC_MSC)
|
||||
# pragma warning(error: 4319)
|
||||
#endif
|
||||
|
||||
// FIXME - quick hack for arm-wince-gcc-3.4 (Debian pocketpc-*.deb packages)
|
||||
#if 1 && (ACC_ARCH_ARM) && defined(__pe__) && !defined(__CEGCC__) && !defined(_WIN32)
|
||||
# undef HAVE_CHMOD
|
||||
|
|
509
src/linker.cpp
509
src/linker.cpp
|
@ -25,17 +25,12 @@
|
|||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "linker.h"
|
||||
|
||||
static unsigned hex(unsigned char c)
|
||||
{
|
||||
return (c & 0xf) + (c > '9' ? 9 : 0);
|
||||
}
|
||||
static unsigned hex(unsigned char c) { return (c & 0xf) + (c > '9' ? 9 : 0); }
|
||||
|
||||
static bool update_capacity(unsigned size, unsigned *capacity)
|
||||
{
|
||||
static bool update_capacity(unsigned size, unsigned *capacity) {
|
||||
if (size < *capacity)
|
||||
return false;
|
||||
if (*capacity == 0)
|
||||
|
@ -45,8 +40,7 @@ static bool update_capacity(unsigned size, unsigned *capacity)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void __acc_cdecl_va internal_error(const char *format, ...)
|
||||
{
|
||||
static void __acc_cdecl_va internal_error(const char *format, ...) {
|
||||
static char buf[1024];
|
||||
va_list ap;
|
||||
|
||||
|
@ -57,79 +51,62 @@ static void __acc_cdecl_va internal_error(const char *format, ...)
|
|||
throwInternalError(buf);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// Section
|
||||
**************************************************************************/
|
||||
|
||||
ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a) :
|
||||
name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL)
|
||||
{
|
||||
ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a)
|
||||
: name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL) {
|
||||
name = strdup(n);
|
||||
assert(name != NULL);
|
||||
input = malloc(s + 1);
|
||||
assert(input != NULL);
|
||||
if (s != 0)
|
||||
memcpy(input, i, s);
|
||||
((char *)input)[s] = 0;
|
||||
((char *) input)[s] = 0;
|
||||
}
|
||||
|
||||
ElfLinker::Section::~Section()
|
||||
{
|
||||
ElfLinker::Section::~Section() {
|
||||
free(name);
|
||||
free(input);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// Symbol
|
||||
**************************************************************************/
|
||||
|
||||
ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o) :
|
||||
name(NULL), section(s), offset(o)
|
||||
{
|
||||
ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
|
||||
: name(NULL), section(s), offset(o) {
|
||||
name = strdup(n);
|
||||
assert(name != NULL);
|
||||
assert(section != NULL);
|
||||
}
|
||||
|
||||
ElfLinker::Symbol::~Symbol()
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
|
||||
ElfLinker::Symbol::~Symbol() { free(name); }
|
||||
|
||||
/*************************************************************************
|
||||
// Relocation
|
||||
**************************************************************************/
|
||||
|
||||
ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t,
|
||||
const Symbol *v, upx_uint64_t a) :
|
||||
section(s), offset(o), type(t), value(v), add(a)
|
||||
{
|
||||
ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, const Symbol *v,
|
||||
upx_uint64_t a)
|
||||
: section(s), offset(o), type(t), value(v), add(a) {
|
||||
assert(section != NULL);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// ElfLinker
|
||||
**************************************************************************/
|
||||
|
||||
ElfLinker::ElfLinker() :
|
||||
bele(&N_BELE_RTP::le_policy),
|
||||
input(NULL), output(NULL), head(NULL), tail(NULL),
|
||||
sections(NULL), symbols(NULL), relocations(NULL),
|
||||
nsections(0), nsections_capacity(0),
|
||||
nsymbols(0), nsymbols_capacity(0),
|
||||
nrelocations(0), nrelocations_capacity(0),
|
||||
reloc_done(false)
|
||||
{
|
||||
}
|
||||
ElfLinker::ElfLinker()
|
||||
: bele(&N_BELE_RTP::le_policy), input(NULL), output(NULL), head(NULL), tail(NULL),
|
||||
sections(NULL), symbols(NULL), relocations(NULL), nsections(0), nsections_capacity(0),
|
||||
nsymbols(0), nsymbols_capacity(0), nrelocations(0), nrelocations_capacity(0),
|
||||
reloc_done(false) {}
|
||||
|
||||
ElfLinker::~ElfLinker()
|
||||
{
|
||||
delete [] input;
|
||||
delete [] output;
|
||||
ElfLinker::~ElfLinker() {
|
||||
delete[] input;
|
||||
delete[] output;
|
||||
|
||||
unsigned ic;
|
||||
for (ic = 0; ic < nsections; ic++)
|
||||
|
@ -143,24 +120,19 @@ ElfLinker::~ElfLinker()
|
|||
free(relocations);
|
||||
}
|
||||
|
||||
void ElfLinker::init(const void *pdata_v, int plen)
|
||||
{
|
||||
void ElfLinker::init(const void *pdata_v, int plen) {
|
||||
const upx_byte *pdata = (const upx_byte *) pdata_v;
|
||||
if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0)
|
||||
{
|
||||
if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0) {
|
||||
// decompress pre-compressed stub-loader
|
||||
int method;
|
||||
unsigned u_len, c_len;
|
||||
if (pdata[4])
|
||||
{
|
||||
if (pdata[4]) {
|
||||
method = pdata[4];
|
||||
u_len = get_le16(pdata + 5);
|
||||
c_len = get_le16(pdata + 7);
|
||||
pdata += 9;
|
||||
assert(9 + c_len == (unsigned) plen);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
method = pdata[5];
|
||||
u_len = get_le32(pdata + 6);
|
||||
c_len = get_le32(pdata + 10);
|
||||
|
@ -176,9 +148,7 @@ void ElfLinker::init(const void *pdata_v, int plen)
|
|||
throwOutOfMemoryException();
|
||||
if (r != UPX_E_OK || new_len != u_len)
|
||||
throwBadLoader();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
inputlen = plen;
|
||||
input = new upx_byte[inputlen + 1];
|
||||
if (inputlen)
|
||||
|
@ -189,7 +159,9 @@ void ElfLinker::init(const void *pdata_v, int plen)
|
|||
output = new upx_byte[inputlen ? inputlen : 0x4000];
|
||||
outputlen = 0;
|
||||
|
||||
if ((int)strlen("Sections:\n" "SYMBOL TABLE:\n" "RELOCATION RECORDS FOR ") < inputlen) {
|
||||
if ((int) strlen("Sections:\n"
|
||||
"SYMBOL TABLE:\n"
|
||||
"RELOCATION RECORDS FOR ") < inputlen) {
|
||||
int pos = find(input, inputlen, "Sections:\n", 10);
|
||||
assert(pos != -1);
|
||||
char *psections = (char *) input + pos;
|
||||
|
@ -202,16 +174,14 @@ void ElfLinker::init(const void *pdata_v, int plen)
|
|||
|
||||
preprocessSections(psections, psymbols);
|
||||
preprocessSymbols(psymbols, prelocs);
|
||||
preprocessRelocations(prelocs, (char*) input + inputlen);
|
||||
preprocessRelocations(prelocs, (char *) input + inputlen);
|
||||
addLoader("*UND*");
|
||||
}
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessSections(char *start, char const *end)
|
||||
{
|
||||
void ElfLinker::preprocessSections(char *start, char *end) {
|
||||
char *nextl;
|
||||
for (nsections = 0; start < end; start = 1+ nextl)
|
||||
{
|
||||
for (nsections = 0; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != NULL);
|
||||
*nextl = '\0'; // a record is a line
|
||||
|
@ -219,25 +189,21 @@ void ElfLinker::preprocessSections(char *start, char const *end)
|
|||
unsigned offset, size, align;
|
||||
char name[1024];
|
||||
|
||||
if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d",
|
||||
name, &size, &offset, &align) == 4)
|
||||
{
|
||||
if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d", name, &size, &offset, &align) == 4) {
|
||||
char *n = strstr(start, name);
|
||||
n[strlen(name)] = 0;
|
||||
addSection(n, input + offset, size, align);
|
||||
|
||||
//printf("section %s preprocessed\n", n);
|
||||
// printf("section %s preprocessed\n", n);
|
||||
}
|
||||
}
|
||||
addSection("*ABS*", NULL, 0, 0);
|
||||
addSection("*UND*", NULL, 0, 0);
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessSymbols(char *start, char const *end)
|
||||
{
|
||||
void ElfLinker::preprocessSymbols(char *start, char *end) {
|
||||
char *nextl;
|
||||
for (nsymbols = 0; start < end; start = 1+ nextl)
|
||||
{
|
||||
for (nsymbols = 0; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != NULL);
|
||||
*nextl = '\0'; // a record is a line
|
||||
|
@ -246,9 +212,7 @@ void ElfLinker::preprocessSymbols(char *start, char const *end)
|
|||
char section[1024];
|
||||
char symbol[1024];
|
||||
|
||||
if (sscanf(start, "%x g *ABS* %x %1023s",
|
||||
&value, &offset, symbol) == 3)
|
||||
{
|
||||
if (sscanf(start, "%x g *ABS* %x %1023s", &value, &offset, symbol) == 3) {
|
||||
char *s = strstr(start, symbol);
|
||||
s[strlen(symbol)] = 0;
|
||||
addSymbol(s, "*ABS*", value);
|
||||
|
@ -273,12 +237,10 @@ void ElfLinker::preprocessSymbols(char *start, char const *end)
|
|||
}
|
||||
}
|
||||
|
||||
void ElfLinker::preprocessRelocations(char *start, char const *end)
|
||||
{
|
||||
void ElfLinker::preprocessRelocations(char *start, char *end) {
|
||||
Section *section = NULL;
|
||||
char *nextl;
|
||||
for (nrelocations = 0; start < end; start = 1+ nextl)
|
||||
{
|
||||
for (nrelocations = 0; start < end; start = 1 + nextl) {
|
||||
nextl = strchr(start, '\n');
|
||||
assert(nextl != NULL);
|
||||
*nextl = '\0'; // a record is a line
|
||||
|
@ -293,9 +255,7 @@ void ElfLinker::preprocessRelocations(char *start, char const *end)
|
|||
char type[100];
|
||||
char symbol[1024];
|
||||
|
||||
if (sscanf(start, "%x %99s %1023s",
|
||||
&offset, type, symbol) == 3)
|
||||
{
|
||||
if (sscanf(start, "%x %99s %1023s", &offset, type, symbol) == 3) {
|
||||
char *t = strstr(start, type);
|
||||
t[strlen(type)] = 0;
|
||||
|
||||
|
@ -303,8 +263,7 @@ void ElfLinker::preprocessRelocations(char *start, char const *end)
|
|||
char *p = strstr(symbol, "+0x");
|
||||
if (p == NULL)
|
||||
p = strstr(symbol, "-0x");
|
||||
if (p)
|
||||
{
|
||||
if (p) {
|
||||
char sign = *p;
|
||||
*p = 0; // terminate the symbol name
|
||||
p += 3;
|
||||
|
@ -312,7 +271,7 @@ void ElfLinker::preprocessRelocations(char *start, char const *end)
|
|||
#if (ACC_CC_MSC && (_MSC_VER < 1800))
|
||||
unsigned a = 0, b = 0;
|
||||
if (sscanf(p, "%08x%08x", &a, &b) == 2)
|
||||
add = ((upx_uint64_t)a << 32) | b;
|
||||
add = ((upx_uint64_t) a << 32) | b;
|
||||
else
|
||||
add = a;
|
||||
#else
|
||||
|
@ -326,14 +285,14 @@ void ElfLinker::preprocessRelocations(char *start, char const *end)
|
|||
|
||||
if (section) {
|
||||
addRelocation(section->name, offset, t, symbol, add);
|
||||
//printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset, (unsigned long long) add);
|
||||
// printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset,
|
||||
// (unsigned long long) add);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const
|
||||
{
|
||||
ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const {
|
||||
for (unsigned ic = 0; ic < nsections; ic++)
|
||||
if (strcmp(sections[ic]->name, name) == 0)
|
||||
return sections[ic];
|
||||
|
@ -342,8 +301,7 @@ ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const
|
||||
{
|
||||
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const {
|
||||
for (unsigned ic = 0; ic < nsymbols; ic++)
|
||||
if (strcmp(symbols[ic]->name, name) == 0)
|
||||
return symbols[ic];
|
||||
|
@ -352,13 +310,16 @@ ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen, unsigned p2align)
|
||||
{
|
||||
//printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);
|
||||
ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen,
|
||||
unsigned p2align) {
|
||||
// printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);
|
||||
if (update_capacity(nsections, &nsections_capacity))
|
||||
sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
|
||||
sections =
|
||||
static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
|
||||
assert(sections);
|
||||
assert(sname); assert(sname[0]); assert(sname[strlen(sname)-1] != ':');
|
||||
assert(sname);
|
||||
assert(sname[0]);
|
||||
assert(sname[strlen(sname) - 1] != ':');
|
||||
assert(findSection(sname, false) == NULL);
|
||||
Section *sec = new Section(sname, sdata, slen, p2align);
|
||||
sections[nsections++] = sec;
|
||||
|
@ -366,28 +327,27 @@ ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata,
|
|||
}
|
||||
|
||||
ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
|
||||
upx_uint64_t offset)
|
||||
{
|
||||
//printf("addSymbol: %s %s 0x%x\n", name, section, offset);
|
||||
upx_uint64_t offset) {
|
||||
// printf("addSymbol: %s %s 0x%x\n", name, section, offset);
|
||||
if (update_capacity(nsymbols, &nsymbols_capacity))
|
||||
symbols = static_cast<Symbol **>(realloc(symbols, nsymbols_capacity * sizeof(Symbol *)));
|
||||
assert(symbols != NULL);
|
||||
assert(name); assert(name[0]); assert(name[strlen(name)-1] != ':');
|
||||
assert(name);
|
||||
assert(name[0]);
|
||||
assert(name[strlen(name) - 1] != ':');
|
||||
assert(findSymbol(name, false) == NULL);
|
||||
Symbol *sym = new Symbol(name, findSection(section), offset);
|
||||
symbols[nsymbols++] = sym;
|
||||
return sym;
|
||||
}
|
||||
|
||||
ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off,
|
||||
const char *type, const char *symbol,
|
||||
upx_uint64_t add)
|
||||
{
|
||||
ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, const char *type,
|
||||
const char *symbol, upx_uint64_t add) {
|
||||
if (update_capacity(nrelocations, &nrelocations_capacity))
|
||||
relocations = static_cast<Relocation **>(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));
|
||||
relocations = static_cast<Relocation **>(
|
||||
realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));
|
||||
assert(relocations != NULL);
|
||||
Relocation *rel = new Relocation(findSection(section), off,
|
||||
type, findSymbol(symbol), add);
|
||||
Relocation *rel = new Relocation(findSection(section), off, type, findSymbol(symbol), add);
|
||||
relocations[nrelocations++] = rel;
|
||||
return rel;
|
||||
}
|
||||
|
@ -400,19 +360,16 @@ void ElfLinker::setLoaderAlignOffset(int phase)
|
|||
}
|
||||
#endif
|
||||
|
||||
int ElfLinker::addLoader(const char *sname)
|
||||
{
|
||||
int ElfLinker::addLoader(const char *sname) {
|
||||
assert(sname != NULL);
|
||||
if (!sname[0])
|
||||
return outputlen;
|
||||
|
||||
char *begin = strdup(sname);
|
||||
char *end = begin + strlen(begin);
|
||||
for (char *sect = begin; sect < end; )
|
||||
{
|
||||
for (char *sect = begin; sect < end;) {
|
||||
for (char *tokend = sect; *tokend; tokend++)
|
||||
if (*tokend == ' ' || *tokend == ',')
|
||||
{
|
||||
if (*tokend == ' ' || *tokend == ',') {
|
||||
*tokend = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -425,39 +382,34 @@ int ElfLinker::addLoader(const char *sname)
|
|||
if (m) {
|
||||
l %= hex(sect[1]);
|
||||
}
|
||||
if (l)
|
||||
{
|
||||
if (l) {
|
||||
if (sect[3] == 'D')
|
||||
alignData(l);
|
||||
else
|
||||
alignCode(l);
|
||||
tail->size += l;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Section *section = findSection(sect);
|
||||
if (section->p2align) {
|
||||
assert(tail);
|
||||
assert(tail != section);
|
||||
// .p2align must be < 32
|
||||
unsigned const v = ~0u << section->p2align;
|
||||
if (unsigned const l = ~v & (0u-(unsigned)(tail->offset + tail->size))) {
|
||||
if (unsigned const l = ~v & (0u - (unsigned) (tail->offset + tail->size))) {
|
||||
alignCode(l);
|
||||
tail->size += l;
|
||||
}
|
||||
}
|
||||
memcpy(output + outputlen, section->input, section->size);
|
||||
section->output = output + outputlen;
|
||||
//printf("section added: 0x%04x %3d %s\n", outputlen, section->size, section->name);
|
||||
// printf("section added: 0x%04x %3d %s\n", outputlen, section->size, section->name);
|
||||
outputlen += section->size;
|
||||
|
||||
if (head)
|
||||
{
|
||||
if (head) {
|
||||
tail->next = section;
|
||||
section->offset = tail->offset + tail->size;
|
||||
}
|
||||
else
|
||||
} else
|
||||
head = section;
|
||||
tail = section;
|
||||
}
|
||||
|
@ -467,80 +419,68 @@ int ElfLinker::addLoader(const char *sname)
|
|||
return outputlen;
|
||||
}
|
||||
|
||||
void ElfLinker::addLoader(const char *s, va_list ap)
|
||||
{
|
||||
while (s != NULL)
|
||||
{
|
||||
void ElfLinker::addLoader(const char *s, va_list ap) {
|
||||
while (s != NULL) {
|
||||
addLoader(s);
|
||||
s = va_arg(ap, const char *);
|
||||
}
|
||||
}
|
||||
|
||||
void __acc_cdecl_va ElfLinker::addLoaderVA(const char *s, ...)
|
||||
{
|
||||
void __acc_cdecl_va ElfLinker::addLoaderVA(const char *s, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
addLoader(s, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int ElfLinker::getSection(const char *sname, int *slen) const
|
||||
{
|
||||
int ElfLinker::getSection(const char *sname, int *slen) const {
|
||||
const Section *section = findSection(sname);
|
||||
if (slen)
|
||||
*slen = section->size;
|
||||
return (int) (section->output - output);
|
||||
}
|
||||
|
||||
int ElfLinker::getSectionSize(const char *sname) const
|
||||
{
|
||||
int ElfLinker::getSectionSize(const char *sname) const {
|
||||
const Section *section = findSection(sname);
|
||||
return section->size;
|
||||
}
|
||||
|
||||
upx_byte *ElfLinker::getLoader(int *llen) const
|
||||
{
|
||||
upx_byte *ElfLinker::getLoader(int *llen) const {
|
||||
if (llen)
|
||||
*llen = outputlen;
|
||||
return output;
|
||||
}
|
||||
|
||||
void ElfLinker::relocate()
|
||||
{
|
||||
void ElfLinker::relocate() {
|
||||
assert(!reloc_done);
|
||||
reloc_done = true;
|
||||
for (unsigned ic = 0; ic < nrelocations; ic++)
|
||||
{
|
||||
for (unsigned ic = 0; ic < nrelocations; ic++) {
|
||||
const Relocation *rel = relocations[ic];
|
||||
upx_uint64_t value = 0;
|
||||
|
||||
if (rel->section->output == NULL)
|
||||
continue;
|
||||
if (strcmp(rel->value->section->name, "*ABS*") == 0)
|
||||
{
|
||||
if (strcmp(rel->value->section->name, "*ABS*") == 0) {
|
||||
value = rel->value->offset;
|
||||
}
|
||||
else if (strcmp(rel->value->section->name, "*UND*") == 0 &&
|
||||
} else if (strcmp(rel->value->section->name, "*UND*") == 0 &&
|
||||
rel->value->offset == 0xdeaddead)
|
||||
internal_error("undefined symbol '%s' referenced\n", rel->value->name);
|
||||
else if (rel->value->section->output == NULL)
|
||||
internal_error("can not apply reloc '%s:%x' without section '%s'\n",
|
||||
rel->section->name, rel->offset,
|
||||
rel->value->section->name);
|
||||
else
|
||||
{
|
||||
value = rel->value->section->offset +
|
||||
rel->value->offset + rel->add;
|
||||
internal_error("can not apply reloc '%s:%x' without section '%s'\n", rel->section->name,
|
||||
rel->offset, rel->value->section->name);
|
||||
else {
|
||||
value = rel->value->section->offset + rel->value->offset + rel->add;
|
||||
}
|
||||
upx_byte *location = rel->section->output + rel->offset;
|
||||
//printf("%-28s %-28s %-10s 0x%16llx 0x%16llx\n", rel->section->name, rel->value->name, rel->type, (long long) value, (long long) value - rel->section->offset - rel->offset);
|
||||
//printf(" %llx %d %llx %d %llx : %d\n", (long long) value, rel->value->section->offset, rel->value->offset, rel->offset, (long long) rel->add, *location);
|
||||
// printf("%-28s %-28s %-10s 0x%16llx 0x%16llx\n", rel->section->name, rel->value->name,
|
||||
// rel->type, (long long) value, (long long) value - rel->section->offset - rel->offset);
|
||||
// printf(" %llx %d %llx %d %llx : %d\n", (long long) value, rel->value->section->offset,
|
||||
// rel->value->offset, rel->offset, (long long) rel->add, *location);
|
||||
relocate1(rel, location, value, rel->type);
|
||||
}
|
||||
}
|
||||
|
||||
void ElfLinker::defineSymbol(const char *name, upx_uint64_t value)
|
||||
{
|
||||
void ElfLinker::defineSymbol(const char *name, upx_uint64_t value) {
|
||||
Symbol *symbol = findSymbol(name);
|
||||
if (strcmp(symbol->section->name, "*ABS*") == 0)
|
||||
internal_error("defineSymbol: symbol '%s' is *ABS*\n", name);
|
||||
|
@ -548,77 +488,62 @@ void ElfLinker::defineSymbol(const char *name, upx_uint64_t value)
|
|||
symbol->offset = value;
|
||||
else if (strcmp(symbol->section->name, name) == 0) // for sections
|
||||
{
|
||||
for (Section *section = symbol->section; section; section = section->next)
|
||||
{
|
||||
for (Section *section = symbol->section; section; section = section->next) {
|
||||
assert(section->offset < value);
|
||||
section->offset = value;
|
||||
value += section->size;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
internal_error("defineSymbol: symbol '%s' already defined\n", name);
|
||||
}
|
||||
|
||||
// debugging support
|
||||
void ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const
|
||||
{
|
||||
void ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const {
|
||||
if ((flags & 1) && symbol->section->output == NULL)
|
||||
return;
|
||||
char d0[16+1], d1[16+1];
|
||||
char d0[16 + 1], d1[16 + 1];
|
||||
upx_snprintf(d0, sizeof(d0), "%016llx", (upx_uint64_t) symbol->offset);
|
||||
upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) symbol->section->offset);
|
||||
fprintf(fp, "%-28s 0x%-16s | %-28s 0x%-16s\n",
|
||||
symbol->name, d0, symbol->section->name, d1);
|
||||
fprintf(fp, "%-28s 0x%-16s | %-28s 0x%-16s\n", symbol->name, d0, symbol->section->name, d1);
|
||||
}
|
||||
void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const
|
||||
{
|
||||
void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const {
|
||||
if (fp == NULL)
|
||||
fp = stdout;
|
||||
if ((flags & 2) == 0)
|
||||
{
|
||||
if ((flags & 2) == 0) {
|
||||
// default: dump symbols in used section order
|
||||
for (const Section *section = head; section; section = section->next)
|
||||
{
|
||||
char d1[16+1];
|
||||
for (const Section *section = head; section; section = section->next) {
|
||||
char d1[16 + 1];
|
||||
upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) section->offset);
|
||||
fprintf(fp, "%-42s%-28s 0x%-16s\n", "", section->name, d1);
|
||||
for (unsigned ic = 0; ic < nsymbols; ic++)
|
||||
{
|
||||
for (unsigned ic = 0; ic < nsymbols; ic++) {
|
||||
const Symbol *symbol = symbols[ic];
|
||||
if (symbol->section == section && strcmp(symbol->name, section->name) != 0)
|
||||
dumpSymbol(symbol, flags, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// dump all symbols
|
||||
for (unsigned ic = 0; ic < nsymbols; ic++)
|
||||
dumpSymbol(symbols[ic], flags, fp);
|
||||
}
|
||||
}
|
||||
|
||||
upx_uint64_t ElfLinker::getSymbolOffset(const char *name) const
|
||||
{
|
||||
upx_uint64_t ElfLinker::getSymbolOffset(const char *name) const {
|
||||
const Symbol *symbol = findSymbol(name);
|
||||
if (symbol->section->output == NULL)
|
||||
return 0xdeaddead;
|
||||
return symbol->section->offset + symbol->offset;
|
||||
}
|
||||
|
||||
void ElfLinker::alignWithByte(unsigned len, unsigned char b)
|
||||
{
|
||||
void ElfLinker::alignWithByte(unsigned len, unsigned char b) {
|
||||
memset(output + outputlen, b, len);
|
||||
outputlen += len;
|
||||
}
|
||||
|
||||
void ElfLinker::relocate1(const Relocation *rel, upx_byte *,
|
||||
upx_uint64_t, const char *)
|
||||
{
|
||||
void ElfLinker::relocate1(const Relocation *rel, upx_byte *, upx_uint64_t, const char *) {
|
||||
internal_error("unknown relocation type '%s\n", rel->type);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// ElfLinker arch subclasses
|
||||
// FIXME: add more displacment overflow checks
|
||||
|
@ -637,31 +562,26 @@ static void check8(const Relocation *rel, const upx_byte *location, int v, int d
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strncmp(type, "R_X86_64_", 9))
|
||||
return super::relocate1(rel, location, value, type);
|
||||
type += 9;
|
||||
|
||||
bool range_check = false;
|
||||
if (strncmp(type, "PC", 2) == 0)
|
||||
{
|
||||
if (strncmp(type, "PC", 2) == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
type += 2;
|
||||
range_check = true;
|
||||
}
|
||||
|
||||
if (strcmp(type, "8") == 0)
|
||||
{
|
||||
if (strcmp(type, "8") == 0) {
|
||||
int displ = (signed char) *location + (int) value;
|
||||
if (range_check && (displ < -128 || displ > 127))
|
||||
internal_error("target out of range (%d) in reloc %s:%x\n",
|
||||
displ, rel->section->name, rel->offset);
|
||||
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
|
||||
rel->offset);
|
||||
*location += value;
|
||||
}
|
||||
else if (strcmp(type, "16") == 0)
|
||||
} else if (strcmp(type, "16") == 0)
|
||||
set_le16(location, get_le16(location) + value);
|
||||
else if (strncmp(type, "32", 2) == 0) // for "32" and "32S"
|
||||
set_le32(location, get_le32(location) + value);
|
||||
|
@ -671,24 +591,15 @@ void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
|
|||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
if (strcmp(type, "R_ARM_PC24") == 0)
|
||||
{
|
||||
void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strcmp(type, "R_ARM_PC24") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
set_be24(1+ location, get_be24(1+ location) + value / 4);
|
||||
}
|
||||
else if (strcmp(type, "R_ARM_ABS32") == 0)
|
||||
{
|
||||
set_be24(1 + location, get_be24(1 + location) + value / 4);
|
||||
} else if (strcmp(type, "R_ARM_ABS32") == 0) {
|
||||
set_be32(location, get_be32(location) + value);
|
||||
}
|
||||
else if (strcmp(type, "R_ARM_THM_CALL") == 0
|
||||
|| strcmp(type, "R_ARM_THM_XPC22") == 0
|
||||
|| strcmp(type, "R_ARM_THM_PC22") == 0
|
||||
)
|
||||
{
|
||||
} else if (strcmp(type, "R_ARM_THM_CALL") == 0 || strcmp(type, "R_ARM_THM_XPC22") == 0 ||
|
||||
strcmp(type, "R_ARM_THM_PC22") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
value += ((get_be16(location) & 0x7ff) << 12);
|
||||
value += (get_be16(location + 2) & 0x7ff) << 1;
|
||||
|
@ -697,33 +608,22 @@ void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location,
|
|||
set_be16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
|
||||
|
||||
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
|
||||
//set_be32(location, get_be32(location) + value / 4);
|
||||
}
|
||||
else if (0==strcmp("R_ARM_ABS8", type)) {
|
||||
// set_be32(location, get_be32(location) + value / 4);
|
||||
} else if (0 == strcmp("R_ARM_ABS8", type)) {
|
||||
*location += value;
|
||||
}
|
||||
else
|
||||
} else
|
||||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
if (strcmp(type, "R_ARM_PC24") == 0)
|
||||
{
|
||||
void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strcmp(type, "R_ARM_PC24") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
set_le24(location, get_le24(location) + value / 4);
|
||||
}
|
||||
else if (strcmp(type, "R_ARM_ABS32") == 0)
|
||||
{
|
||||
} else if (strcmp(type, "R_ARM_ABS32") == 0) {
|
||||
set_le32(location, get_le32(location) + value);
|
||||
}
|
||||
else if (strcmp(type, "R_ARM_THM_CALL") == 0
|
||||
|| strcmp(type, "R_ARM_THM_XPC22") == 0
|
||||
|| strcmp(type, "R_ARM_THM_PC22") == 0
|
||||
)
|
||||
{
|
||||
} else if (strcmp(type, "R_ARM_THM_CALL") == 0 || strcmp(type, "R_ARM_THM_XPC22") == 0 ||
|
||||
strcmp(type, "R_ARM_THM_PC22") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
value += ((get_le16(location) & 0x7ff) << 12);
|
||||
value += (get_le16(location + 2) & 0x7ff) << 1;
|
||||
|
@ -732,34 +632,25 @@ void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location,
|
|||
set_le16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
|
||||
|
||||
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
|
||||
//set_le32(location, get_le32(location) + value / 4);
|
||||
}
|
||||
else if (0==strcmp("R_ARM_ABS8", type)) {
|
||||
// set_le32(location, get_le32(location) + value / 4);
|
||||
} else if (0 == strcmp("R_ARM_ABS8", type)) {
|
||||
*location += value;
|
||||
}
|
||||
else
|
||||
} else
|
||||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
void ElfLinkerArm64LE::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
if (strcmp(type, "R_AARCH64_CALL26") == 0)
|
||||
{
|
||||
void ElfLinkerArm64LE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strcmp(type, "R_AARCH64_CALL26") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
set_le24(location, get_le24(location) + value / 4); // FIXME set_le26
|
||||
}
|
||||
else if (strcmp(type, "R_AARCH64_ABS32") == 0)
|
||||
{
|
||||
} else if (strcmp(type, "R_AARCH64_ABS32") == 0) {
|
||||
set_le32(location, get_le32(location) + value);
|
||||
}
|
||||
else
|
||||
} else
|
||||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerM68k::alignCode(unsigned len)
|
||||
{
|
||||
void ElfLinkerM68k::alignCode(unsigned len) {
|
||||
assert((len & 1) == 0);
|
||||
assert((outputlen & 1) == 0);
|
||||
for (unsigned i = 0; i < len; i += 2)
|
||||
|
@ -767,50 +658,41 @@ void ElfLinkerM68k::alignCode(unsigned len)
|
|||
outputlen += len;
|
||||
}
|
||||
|
||||
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strncmp(type, "R_68K_", 6))
|
||||
return super::relocate1(rel, location, value, type);
|
||||
type += 6;
|
||||
|
||||
if (strncmp(type, "PC", 2) == 0)
|
||||
{
|
||||
if (strncmp(type, "PC", 2) == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
type += 2;
|
||||
}
|
||||
if (strcmp(type, "8") == 0) {
|
||||
*location += value;
|
||||
}
|
||||
else if (strcmp(type, "16") == 0) {
|
||||
} else if (strcmp(type, "16") == 0) {
|
||||
set_be16(location, get_be16(location) + value);
|
||||
}
|
||||
else if (strcmp(type, "32") == 0) {
|
||||
} else if (strcmp(type, "32") == 0) {
|
||||
set_be32(location, get_be32(location) + value);
|
||||
}
|
||||
else
|
||||
} else
|
||||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
#define MIPS_HI(a) (((a) >> 16) + (((a) & 0x8000) >> 15))
|
||||
#define MIPS_LO(a) ((a) & 0xffff)
|
||||
void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
#define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15))
|
||||
#define MIPS_LO(a) ((a) &0xffff)
|
||||
#define MIPS_PC16(a) ((a) >> 2)
|
||||
#define MIPS_PC26(a) (((a) & 0x0fffffff) >> 2)
|
||||
#define MIPS_PC26(a) (((a) &0x0fffffff) >> 2)
|
||||
|
||||
if (strcmp(type, "R_MIPS_HI16") == 0)
|
||||
set_be16(2+location, get_be16(2+location) + MIPS_HI(value));
|
||||
set_be16(2 + location, get_be16(2 + location) + MIPS_HI(value));
|
||||
else if (strcmp(type, "R_MIPS_LO16") == 0)
|
||||
set_be16(2+location, get_be16(2+location) + MIPS_LO(value));
|
||||
else if (strcmp(type, "R_MIPS_PC16") == 0)
|
||||
{
|
||||
set_be16(2 + location, get_be16(2 + location) + MIPS_LO(value));
|
||||
else if (strcmp(type, "R_MIPS_PC16") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
set_be16(2+location, get_be16(2+location) + MIPS_PC16(value));
|
||||
}
|
||||
else if (strcmp(type, "R_MIPS_26") == 0)
|
||||
set_be16(2 + location, get_be16(2 + location) + MIPS_PC16(value));
|
||||
} else if (strcmp(type, "R_MIPS_26") == 0)
|
||||
set_be32(location, get_be32(location) + MIPS_PC26(value));
|
||||
else if (strcmp(type, "R_MIPS_32") == 0)
|
||||
set_be32(location, get_be32(location) + value);
|
||||
|
@ -823,25 +705,21 @@ void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location,
|
|||
#undef MIPS_PC26
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
#define MIPS_HI(a) (((a) >> 16) + (((a) & 0x8000) >> 15))
|
||||
#define MIPS_LO(a) ((a) & 0xffff)
|
||||
void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
#define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15))
|
||||
#define MIPS_LO(a) ((a) &0xffff)
|
||||
#define MIPS_PC16(a) ((a) >> 2)
|
||||
#define MIPS_PC26(a) (((a) & 0x0fffffff) >> 2)
|
||||
#define MIPS_PC26(a) (((a) &0x0fffffff) >> 2)
|
||||
|
||||
if (strcmp(type, "R_MIPS_HI16") == 0)
|
||||
set_le16(location, get_le16(location) + MIPS_HI(value));
|
||||
else if (strcmp(type, "R_MIPS_LO16") == 0)
|
||||
set_le16(location, get_le16(location) + MIPS_LO(value));
|
||||
else if (strcmp(type, "R_MIPS_PC16") == 0)
|
||||
{
|
||||
else if (strcmp(type, "R_MIPS_PC16") == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
set_le16(location, get_le16(location) + MIPS_PC16(value));
|
||||
}
|
||||
else if (strcmp(type, "R_MIPS_26") == 0)
|
||||
} else if (strcmp(type, "R_MIPS_26") == 0)
|
||||
set_le32(location, get_le32(location) + MIPS_PC26(value));
|
||||
else if (strcmp(type, "R_MIPS_32") == 0)
|
||||
set_le32(location, get_le32(location) + value);
|
||||
|
@ -854,22 +732,18 @@ void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location,
|
|||
#undef MIPS_PC26
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strncmp(type, "R_PPC_", 6))
|
||||
return super::relocate1(rel, location, value, type);
|
||||
type += 6;
|
||||
|
||||
if (strcmp(type, "ADDR32") == 0)
|
||||
{
|
||||
if (strcmp(type, "ADDR32") == 0) {
|
||||
set_be32(location, get_be32(location) + value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(type, "REL", 3) == 0)
|
||||
{
|
||||
if (strncmp(type, "REL", 3) == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
type += 3;
|
||||
}
|
||||
|
@ -878,33 +752,27 @@ void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location,
|
|||
|
||||
// Note that original (*location).displ is ignored.
|
||||
if (strcmp(type, "24") == 0) {
|
||||
if (3& value)
|
||||
if (3 & value)
|
||||
internal_error("unaligned word diplacement");
|
||||
// FIXME: displacment overflow?
|
||||
set_be32(location, (0xfc000003 & get_be32(location)) +
|
||||
(0x03fffffc & value));
|
||||
}
|
||||
else if (strcmp(type, "14") == 0) {
|
||||
if (3& value)
|
||||
set_be32(location, (0xfc000003 & get_be32(location)) + (0x03fffffc & value));
|
||||
} else if (strcmp(type, "14") == 0) {
|
||||
if (3 & value)
|
||||
internal_error("unaligned word diplacement");
|
||||
// FIXME: displacment overflow?
|
||||
set_be32(location, (0xffff0003 & get_be32(location)) +
|
||||
(0x0000fffc & value));
|
||||
}
|
||||
else
|
||||
set_be32(location, (0xffff0003 & get_be32(location)) + (0x0000fffc & value));
|
||||
} else
|
||||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strncmp(type, "R_PPC64_REL", 11))
|
||||
return super::relocate1(rel, location, value, type);
|
||||
type += 11;
|
||||
|
||||
bool range_check = false;
|
||||
if (strncmp(type, "PC", 2) == 0)
|
||||
{
|
||||
if (strncmp(type, "PC", 2) == 0) {
|
||||
type += 2;
|
||||
range_check = true;
|
||||
}
|
||||
|
@ -912,15 +780,13 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location,
|
|||
/* value will hold relative displacement */
|
||||
value -= rel->section->offset + rel->offset;
|
||||
|
||||
if (strcmp(type, "8") == 0)
|
||||
{
|
||||
if (strcmp(type, "8") == 0) {
|
||||
int displ = (signed char) *location + (int) value;
|
||||
if (range_check && (displ < -128 || displ > 127))
|
||||
internal_error("target out of range (%d) in reloc %s:%x\n",
|
||||
displ, rel->section->name, rel->offset);
|
||||
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
|
||||
rel->offset);
|
||||
*location += value;
|
||||
}
|
||||
else if (strncmp(type, "14", 2) == 0) // for "32" and "32S"
|
||||
} else if (strncmp(type, "14", 2) == 0) // for "32" and "32S"
|
||||
set_le16(location, get_le16(location) + value);
|
||||
else if (strcmp(type, "16") == 0)
|
||||
set_le16(location, get_le16(location) + value);
|
||||
|
@ -934,31 +800,26 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location,
|
|||
super::relocate1(rel, location, value, type);
|
||||
}
|
||||
|
||||
|
||||
void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location,
|
||||
upx_uint64_t value, const char *type)
|
||||
{
|
||||
void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
|
||||
const char *type) {
|
||||
if (strncmp(type, "R_386_", 6))
|
||||
return super::relocate1(rel, location, value, type);
|
||||
type += 6;
|
||||
|
||||
bool range_check = false;
|
||||
if (strncmp(type, "PC", 2) == 0)
|
||||
{
|
||||
if (strncmp(type, "PC", 2) == 0) {
|
||||
value -= rel->section->offset + rel->offset;
|
||||
type += 2;
|
||||
range_check = true;
|
||||
}
|
||||
|
||||
if (strcmp(type, "8") == 0)
|
||||
{
|
||||
if (strcmp(type, "8") == 0) {
|
||||
int displ = (signed char) *location + (int) value;
|
||||
if (range_check && (displ < -128 || displ > 127))
|
||||
internal_error("target out of range (%d,%d,%d) in reloc %s:%x\n",
|
||||
displ, *location, value, rel->section->name, rel->offset);
|
||||
internal_error("target out of range (%d,%d,%d) in reloc %s:%x\n", displ, *location,
|
||||
value, rel->section->name, rel->offset);
|
||||
*location += value;
|
||||
}
|
||||
else if (strcmp(type, "16") == 0)
|
||||
} else if (strcmp(type, "16") == 0)
|
||||
set_le16(location, get_le16(location) + value);
|
||||
else if (strcmp(type, "32") == 0)
|
||||
set_le32(location, get_le32(location) + value);
|
||||
|
|
139
src/linker.h
139
src/linker.h
|
@ -25,18 +25,16 @@
|
|||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_LINKER_H
|
||||
#define __UPX_LINKER_H 1
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// ElfLinker
|
||||
**************************************************************************/
|
||||
|
||||
class ElfLinker : private noncopyable
|
||||
{
|
||||
class ElfLinker : private noncopyable {
|
||||
friend class Packer;
|
||||
|
||||
public:
|
||||
const N_BELE_RTP::AbstractPolicy *bele; // target endianness
|
||||
protected:
|
||||
|
@ -66,11 +64,11 @@ protected:
|
|||
bool reloc_done;
|
||||
|
||||
protected:
|
||||
void preprocessSections(char *start, char const *end);
|
||||
void preprocessSymbols(char *start, char const *end);
|
||||
void preprocessRelocations(char *start, char const *end);
|
||||
Section *findSection(const char *name, bool fatal=true) const;
|
||||
Symbol *findSymbol(const char *name, bool fatal=true) const;
|
||||
void preprocessSections(char *start, char *end);
|
||||
void preprocessSymbols(char *start, char *end);
|
||||
void preprocessRelocations(char *start, char *end);
|
||||
Section *findSection(const char *name, bool fatal = true) const;
|
||||
Symbol *findSymbol(const char *name, bool fatal = true) const;
|
||||
|
||||
Symbol *addSymbol(const char *name, const char *section, upx_uint64_t offset);
|
||||
Relocation *addRelocation(const char *section, unsigned off, const char *type,
|
||||
|
@ -81,7 +79,7 @@ public:
|
|||
virtual ~ElfLinker();
|
||||
|
||||
virtual void init(const void *pdata, int plen);
|
||||
//virtual void setLoaderAlignOffset(int phase);
|
||||
// virtual void setLoaderAlignOffset(int phase);
|
||||
virtual int addLoader(const char *sname);
|
||||
void addLoader(const char *s, va_list ap);
|
||||
#if 1 && (ACC_CC_CLANG || (ACC_CC_GNUC >= 0x040100))
|
||||
|
@ -90,14 +88,14 @@ public:
|
|||
void __acc_cdecl_va addLoaderVA(const char *s, ...);
|
||||
#endif
|
||||
virtual Section *addSection(const char *sname, const void *sdata, int slen, unsigned p2align);
|
||||
virtual int getSection(const char *sname, int *slen=NULL) const;
|
||||
virtual int getSection(const char *sname, int *slen = NULL) const;
|
||||
virtual int getSectionSize(const char *sname) const;
|
||||
virtual upx_byte *getLoader(int *llen=NULL) const;
|
||||
virtual upx_byte *getLoader(int *llen = NULL) const;
|
||||
virtual void defineSymbol(const char *name, upx_uint64_t value);
|
||||
virtual upx_uint64_t getSymbolOffset(const char *) const;
|
||||
|
||||
virtual void dumpSymbol(const Symbol *, unsigned flags, FILE *fp) const;
|
||||
virtual void dumpSymbols(unsigned flags=0, FILE *fp=NULL) const;
|
||||
virtual void dumpSymbols(unsigned flags = 0, FILE *fp = NULL) const;
|
||||
|
||||
void alignWithByte(unsigned len, unsigned char b);
|
||||
virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
|
||||
|
@ -105,8 +103,8 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void relocate();
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
|
||||
// target endianness abstraction
|
||||
unsigned get_te16(const void *p) const { return bele->get16(p); }
|
||||
|
@ -117,9 +115,7 @@ protected:
|
|||
void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
|
||||
};
|
||||
|
||||
|
||||
struct ElfLinker::Section : private noncopyable
|
||||
{
|
||||
struct ElfLinker::Section : private noncopyable {
|
||||
char *name;
|
||||
void *input;
|
||||
upx_byte *output;
|
||||
|
@ -128,13 +124,11 @@ struct ElfLinker::Section : private noncopyable
|
|||
unsigned p2align; // log2
|
||||
Section *next;
|
||||
|
||||
Section(const char *n, const void *i, unsigned s, unsigned a=0);
|
||||
Section(const char *n, const void *i, unsigned s, unsigned a = 0);
|
||||
~Section();
|
||||
};
|
||||
|
||||
|
||||
struct ElfLinker::Symbol : private noncopyable
|
||||
{
|
||||
struct ElfLinker::Symbol : private noncopyable {
|
||||
char *name;
|
||||
Section *section;
|
||||
upx_uint64_t offset;
|
||||
|
@ -143,124 +137,115 @@ struct ElfLinker::Symbol : private noncopyable
|
|||
~Symbol();
|
||||
};
|
||||
|
||||
|
||||
struct ElfLinker::Relocation : private noncopyable
|
||||
{
|
||||
struct ElfLinker::Relocation : private noncopyable {
|
||||
const Section *section;
|
||||
unsigned offset;
|
||||
const char *type;
|
||||
const Symbol *value;
|
||||
upx_uint64_t add; // used in .rela relocations
|
||||
|
||||
Relocation(const Section *s, unsigned o, const char *t,
|
||||
const Symbol *v, upx_uint64_t a);
|
||||
Relocation(const Section *s, unsigned o, const char *t, const Symbol *v, upx_uint64_t a);
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// ElfLinker arch subclasses
|
||||
**************************************************************************/
|
||||
|
||||
class ElfLinkerAMD64 : public ElfLinker
|
||||
{
|
||||
class ElfLinkerAMD64 : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerArmBE : public ElfLinker
|
||||
{
|
||||
class ElfLinkerArmBE : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
public:
|
||||
ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; }
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerArmLE : public ElfLinker
|
||||
{
|
||||
class ElfLinkerArmLE : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
class ElfLinkerArm64LE : public ElfLinker
|
||||
{
|
||||
class ElfLinkerArm64LE : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerM68k : public ElfLinker
|
||||
{
|
||||
class ElfLinkerM68k : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
public:
|
||||
ElfLinkerM68k() { bele = &N_BELE_RTP::be_policy; }
|
||||
|
||||
protected:
|
||||
virtual void alignCode(unsigned len);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerMipsBE : public ElfLinker
|
||||
{
|
||||
class ElfLinkerMipsBE : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
public:
|
||||
ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; }
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerMipsLE : public ElfLinker
|
||||
{
|
||||
class ElfLinkerMipsLE : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerPpc32 : public ElfLinker
|
||||
{
|
||||
class ElfLinkerPpc32 : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
public:
|
||||
ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; }
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
class ElfLinkerPpc64le : public ElfLinker
|
||||
{
|
||||
class ElfLinkerPpc64le : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
class ElfLinkerX86 : public ElfLinker
|
||||
{
|
||||
class ElfLinkerX86 : public ElfLinker {
|
||||
typedef ElfLinker super;
|
||||
|
||||
protected:
|
||||
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
|
||||
virtual void relocate1(const Relocation *, upx_byte *location,
|
||||
upx_uint64_t value, const char *type);
|
||||
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
|
||||
const char *type);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 33fb09d29159f9dde2ddae9fe6875f8614d28ca3
|
||||
Subproject commit 426fe82d122e2cf140a86751055ee523378fe2ef
|
|
@ -1666,7 +1666,7 @@ int PackMachBase<T>::canUnpack()
|
|||
}
|
||||
if (!strcmp("__LINKEDIT", segptr->segname)) {
|
||||
offLINK = segptr->fileoff;
|
||||
if (offLINK < pos_next) {
|
||||
if (offLINK < (off_t) pos_next) {
|
||||
offLINK = pos_next;
|
||||
}
|
||||
}
|
||||
|
|
0
src/stub/powerpc-darwin.macho-upxmain.exe
Executable file → Normal file
0
src/stub/powerpc-darwin.macho-upxmain.exe
Executable file → Normal file
|
@ -178,8 +178,7 @@ def do_file(fn):
|
|||
# FIXME / TODO
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
#assert pos == len(odata), ("unexpected strip_with_dump", pos, len(odata))
|
||||
assert pos == len(odata), ("unexpected strip_with_dump", pos, len(odata))
|
||||
else:
|
||||
if pos >= 0:
|
||||
odata = idata[:pos]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#define UPX_VERSION_HEX 0x035c00 /* 03.92.00 */
|
||||
#define UPX_VERSION_STRING "3.92-BETA"
|
||||
#define UPX_VERSION_STRING "3.92"
|
||||
#define UPX_VERSION_STRING4 "3.92"
|
||||
#define UPX_VERSION_DATE "Sep 25th 2016"
|
||||
#define UPX_VERSION_DATE_ISO "2016-09-25"
|
||||
#define UPX_VERSION_DATE "Nov 27th 2016"
|
||||
#define UPX_VERSION_DATE_ISO "2016-11-25"
|
||||
#define UPX_VERSION_YEAR "2016"
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
|
Loading…
Reference in New Issue
Block a user