src/pefile.cpp: cleanup reloc handling and add more checks

This commit is contained in:
Markus F.X.J. Oberhumer 2023-10-14 19:24:44 +02:00
parent 2b371e99bd
commit d8be2ed276
6 changed files with 209 additions and 109 deletions

View File

@ -1246,8 +1246,12 @@ void Packer::compressWithFilters(Filter *ft, const unsigned overlap_range,
byte *i_ptr = ibuf + ibuf_off;
unsigned i_len = ph.u_len;
byte *o_ptr = obuf + obuf_off;
byte *f_ptr = ibuf + filter_off;
unsigned f_len = ft->buf_len ? ft->buf_len : i_len;
if (filter_strategy == -3) {
filter_off = 0;
f_len = 0;
}
byte *f_ptr = ibuf + filter_off;
assert(f_ptr + f_len <= i_ptr + i_len);

View File

@ -51,6 +51,12 @@ unsigned Packer::optimizeReloc(unsigned relocnum, SPAN_P(byte) relocs, SPAN_S(by
if (relocnum == 0)
return 0;
upx_qsort(raw_bytes(relocs, 4 * relocnum), relocnum, 4, le32_compare);
if (0) {
printf("optimizeReloc: u_reloc %9u checksum=0x%08x\n", 4 * relocnum,
upx_adler32(relocs, 4 * relocnum));
printf("optimizeReloc: u_image %9u checksum=0x%08x\n", image_size,
upx_adler32(image, image_size));
}
unsigned pc = (unsigned) -4;
for (unsigned i = 0; i < relocnum; i++) {
@ -84,7 +90,13 @@ unsigned Packer::optimizeReloc(unsigned relocnum, SPAN_P(byte) relocs, SPAN_S(by
}
}
*fix++ = 0; // end marker
return ptr_udiff_bytes(fix, out);
const unsigned bytes = ptr_udiff_bytes(fix, out);
if (0) {
printf("optimizeReloc: c_reloc %9u checksum=0x%08x\n", bytes, upx_adler32(out, bytes));
printf("optimizeReloc: c_image %9u checksum=0x%08x\n", image_size,
upx_adler32(image, image_size));
}
return bytes;
}
/*************************************************************************
@ -113,6 +125,12 @@ unsigned Packer::unoptimizeReloc(SPAN_S(const byte) & in, MemBuffer &out, SPAN_P
}
}
NO_fprintf(stderr, "relocnum=%x\n", relocnum);
if (0) {
const unsigned bytes = ptr_udiff_bytes(fix + 1, in);
printf("unoptimizeReloc: c_reloc %9u checksum=0x%08x\n", bytes, upx_adler32(in, bytes));
printf("unoptimizeReloc: c_image %9u checksum=0x%08x\n", image_size,
upx_adler32(image, image_size));
}
out.alloc(4 * (relocnum + 1)); // one extra entry
SPAN_S_VAR(LE32, relocs, out);
@ -146,6 +164,12 @@ unsigned Packer::unoptimizeReloc(SPAN_S(const byte) & in, MemBuffer &out, SPAN_P
}
in = fix + 1; // advance
assert(relocnum == ptr_udiff_bytes(relocs, raw_bytes(out, 0)) / 4);
if (0) {
printf("unoptimizeReloc: u_reloc %9u checksum=0x%08x\n", 4 * relocnum,
upx_adler32(out, 4 * relocnum));
printf("unoptimizeReloc: u_image %9u checksum=0x%08x\n", image_size,
upx_adler32(image, image_size));
}
return relocnum;
}

View File

@ -295,73 +295,129 @@ struct FixDeleter { // don't leak memory on exceptions
};
} // namespace
struct alignas(1) PeFile::Reloc::reloc {
LE32 pagestart;
LE32 size;
};
static constexpr unsigned RELOC_BUF_OFFSET = 64 * 1024;
void PeFile::Reloc::newRelocPos(void *p) {
rel = (reloc *) p;
rel1 = (LE16 *) ((char *) p + sizeof(reloc));
PeFile::Reloc::~Reloc() noexcept {
COMPILE_TIME_ASSERT(sizeof(BaseReloc) == 8)
COMPILE_TIME_ASSERT_ALIGNED1(BaseReloc)
// prevent leak on exceptions
if (start_did_alloc)
delete[] start;
}
PeFile::Reloc::Reloc(byte *s, unsigned si) : start(s), size(si), rel(nullptr), rel1(nullptr) {
COMPILE_TIME_ASSERT(sizeof(reloc) == 8)
COMPILE_TIME_ASSERT_ALIGNED1(reloc)
memset(counts, 0, sizeof(counts));
// constructor for compression only
PeFile::Reloc::Reloc(byte *s, unsigned si) : start(s), start_size_in_bytes(si) {
assert(opt->cmd == CMD_COMPRESS);
initSpans();
// check size
constexpr unsigned BRS = sizeof(BaseReloc); // 8
if (si == 0) // empty
return;
if (si == BRS) {
unsigned x = get_le32(start_buf + 4); // size_of_block
if (x == 0 || x == BRS) // ignore strange empty relocs
return;
}
if (si < BRS + sizeof(LE16)) // 10
throwCantPack("bad reloc size %d", si);
// fill counts
unsigned pos, type;
while (next(pos, type))
counts[type]++;
}
PeFile::Reloc::Reloc(unsigned relocnum) : start(nullptr), size(0), rel(nullptr), rel1(nullptr) {
start = new byte[mem_size(4, relocnum, 8192)]; // => oxrelocs
counts[0] = 0;
PeFile::Reloc::Reloc(unsigned relocnum) {
start_size_in_bytes = mem_size(4, relocnum, RELOC_BUF_OFFSET, 8192);
start = new byte[start_size_in_bytes]; // => transfer to oxrelocs[] in finish()
start_did_alloc = true;
initSpans();
}
bool PeFile::Reloc::next(unsigned &pos, unsigned &type) {
if (!rel)
newRelocPos(start);
if (ptr_diff_bytes(rel, start) >= (int) size) {
rel = nullptr; // rewind
return false;
}
void PeFile::Reloc::initSpans() {
start_buf = SPAN_S_MAKE(byte, start, start_size_in_bytes);
rel = SPAN_S_CAST(BaseReloc, start_buf);
rel1 = SPAN_S_CAST(LE16, start_buf);
rel = nullptr;
rel1 = nullptr;
}
pos = rel->pagestart + (*rel1 & 0xfff);
type = *rel1++ >> 12;
NO_printf("%x %d\n", pos, type);
if (ptr_diff_bytes(rel1, rel) >= (int) rel->size)
newRelocPos(rel1);
return type == 0 ? next(pos, type) : true;
void PeFile::Reloc::advanceBaseRelocPos(void *p) {
unsigned off = ptr_udiff_bytes(p, start);
if (!start_did_alloc && off == start_size_in_bytes) { // final entry
rel = (BaseReloc *) p;
rel1 = nullptr;
} else {
rel = (BaseReloc *) p;
rel1 = (LE16 *) ((byte *) p + sizeof(BaseReloc));
}
}
bool PeFile::Reloc::next(unsigned &result_pos, unsigned &result_type) {
assert(!start_did_alloc);
unsigned pos, type;
do {
if (rel == nullptr)
advanceBaseRelocPos(start);
if (ptr_udiff_bytes(rel, start) >= start_size_in_bytes) {
rel = nullptr; // rewind
rel1 = nullptr; // rewind
return false;
}
pos = rel->pagestart + (*rel1 & 0xfff);
type = *rel1++ >> 12;
NO_printf("%x %d\n", pos, type);
if (ptr_udiff_bytes(raw_bytes(rel1, 0), rel) >= rel->size_of_block)
advanceBaseRelocPos(raw_bytes(rel1, 0));
} while (type == 0);
result_pos = pos;
result_type = type;
return true;
}
void PeFile::Reloc::add(unsigned pos, unsigned type) {
set_le32(start + 1024 + 4 * counts[0]++, (pos << 4) + type);
assert(start_did_alloc);
set_le32(start_buf + (RELOC_BUF_OFFSET + 4 * counts[0]), (pos << 4) + type);
counts[0] += 1;
}
void PeFile::Reloc::finish(byte *&p, unsigned &siz) {
unsigned prev = 0xffffffff;
set_le32(start + 1024 + 4 * counts[0]++, 0xf0000000);
upx_qsort(start + 1024, counts[0], 4, le32_compare);
void PeFile::Reloc::finish(byte *&result_ptr, unsigned &result_size) {
assert(start_did_alloc);
// sentinel to force final advanceBaseRelocPos()
set_le32(start_buf + (RELOC_BUF_OFFSET + 4 * counts[0]), 0xfff00000);
counts[0] += 1;
upx_qsort(raw_index_bytes(start_buf, RELOC_BUF_OFFSET, 4 * counts[0]), counts[0], 4,
le32_compare);
rel = (reloc *) start;
rel1 = (LE16 *) start;
rel = nullptr;
rel1 = nullptr;
unsigned prev = 0xffffffff;
for (unsigned ic = 0; ic < counts[0]; ic++) {
unsigned pos = get_le32(start + 1024 + 4 * ic);
if ((pos ^ prev) >= 0x10000) {
unsigned pos = get_le32(start_buf + (RELOC_BUF_OFFSET + 4 * ic));
if (ic == 0) {
prev = pos;
*rel1 = 0;
rel->size = ALIGN_UP(ptr_diff_bytes(rel1, rel), 4);
newRelocPos((char *) rel + rel->size);
advanceBaseRelocPos(start);
rel->pagestart = (pos >> 4) & ~0xfff;
rel->size_of_block = 0; // to be filled later
} else if ((pos ^ prev) >= 0x10000) {
prev = pos;
*rel1 = 0; // clear align-up memory
rel->size_of_block = ALIGN_UP(ptr_udiff_bytes(raw_bytes(rel1, 0), rel), 4u);
advanceBaseRelocPos((char *) raw_bytes(rel, rel->size_of_block) + rel->size_of_block);
rel->pagestart = (pos >> 4) & ~0xfff;
rel->size_of_block = 0;
}
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
}
p = start;
siz = ptr_udiff_bytes(rel1, start) & ~3;
siz -= 8;
// siz can be 0 in 64-bit mode // assert(siz > 0);
start = nullptr; // safety
assert(ptr_udiff_bytes(raw_bytes(rel1, 0), rel) == 10); // sentinel
result_size = ptr_udiff_bytes(rel, start);
assert((result_size & 3) == 0);
// assert(result_size > 0); // result_size can be 0 in 64-bit mode
// transfer ownership
assert(start_did_alloc);
result_ptr = start;
start = nullptr; // safety
start_buf = nullptr; // safety
start_did_alloc = false;
}
void PeFile::processRelocs(Reloc *rel) // pass2
@ -375,20 +431,22 @@ void PeFile32::processRelocs() // pass1
{
big_relocs = 0;
const unsigned skip1 = IDADDR(PEDIR_RELOC);
const unsigned take1 = IDSIZE(PEDIR_RELOC);
const unsigned skip1 = IDADDR(PEDIR_BASERELOC);
const unsigned take1 = IDSIZE(PEDIR_BASERELOC);
Reloc rel(ibuf.subref("bad reloc %#x", skip1, take1), take1);
const unsigned *counts = rel.getcounts();
const unsigned *const counts = rel.getcounts();
unsigned relocnum = 0;
unsigned ic;
for (ic = 1; ic < 16; ic++)
relocnum += counts[ic];
for (ic = 0; ic < 16; ic++)
NO_printf("reloc counts[%u] %u\n", ic, counts[ic]);
if (opt->win32_pe.strip_relocs || relocnum == 0) {
if (IDSIZE(PEDIR_RELOC)) {
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
if (IDSIZE(PEDIR_BASERELOC)) {
ibuf.fill(IDADDR(PEDIR_BASERELOC), IDSIZE(PEDIR_BASERELOC), FILLVAL);
ih.objects = tryremove(IDADDR(PEDIR_BASERELOC), ih.objects);
}
mb_orelocs.alloc(1);
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
@ -429,7 +487,7 @@ void PeFile32::processRelocs() // pass1
if (fix[ic][kc] != prev)
prev = fix[ic][jc++] = fix[ic][kc];
NO_printf("xcounts[%u] %u->%u\n", ic, xcounts[ic], jc);
NO_printf("reloc xcounts[%u] %u->%u\n", ic, xcounts[ic], jc);
xcounts[ic] = jc;
}
@ -440,7 +498,7 @@ void PeFile32::processRelocs() // pass1
set_le32(ibuf + pos, w - ih.imagebase - rvamin);
}
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
ibuf.fill(IDADDR(PEDIR_BASERELOC), IDSIZE(PEDIR_BASERELOC), FILLVAL);
mb_orelocs.alloc(mem_size(4, relocnum, 8192)); // 8192 - safety
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
sorelocs = optimizeReloc(xcounts[3], (byte *) fix[3], orelocs, ibuf + rvamin, ibufgood - rvamin,
@ -465,7 +523,7 @@ void PeFile32::processRelocs() // pass1
}
}
info("Relocations: original size: %u bytes, preprocessed size: %u bytes",
(unsigned) IDSIZE(PEDIR_RELOC), sorelocs);
(unsigned) IDSIZE(PEDIR_BASERELOC), sorelocs);
}
// FIXME - this is too similar to PeFile32::processRelocs
@ -473,8 +531,8 @@ void PeFile64::processRelocs() // pass1
{
big_relocs = 0;
const unsigned skip = IDADDR(PEDIR_RELOC);
const unsigned take = IDSIZE(PEDIR_RELOC);
const unsigned skip = IDADDR(PEDIR_BASERELOC);
const unsigned take = IDSIZE(PEDIR_BASERELOC);
Reloc rel(ibuf.subref("bad reloc %#x", skip, take), take);
const unsigned *counts = rel.getcounts();
unsigned relocnum = 0;
@ -484,9 +542,9 @@ void PeFile64::processRelocs() // pass1
relocnum += counts[ic];
if (opt->win32_pe.strip_relocs || relocnum == 0) {
if (IDSIZE(PEDIR_RELOC)) {
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
ih.objects = tryremove(IDADDR(PEDIR_RELOC), ih.objects);
if (IDSIZE(PEDIR_BASERELOC)) {
ibuf.fill(IDADDR(PEDIR_BASERELOC), IDSIZE(PEDIR_BASERELOC), FILLVAL);
ih.objects = tryremove(IDADDR(PEDIR_BASERELOC), ih.objects);
}
mb_orelocs.alloc(1);
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
@ -513,7 +571,6 @@ void PeFile64::processRelocs() // pass1
while (rel.next(pos, type)) {
// FIXME add check for relocations which try to modify the
// PE header or other relocation records
if (pos >= ih.imagesize)
continue; // skip out-of-bounds record
if (type < 16)
@ -540,7 +597,7 @@ void PeFile64::processRelocs() // pass1
set_le64(ibuf + pos, w - ih.imagebase - rvamin);
}
ibuf.fill(IDADDR(PEDIR_RELOC), IDSIZE(PEDIR_RELOC), FILLVAL);
ibuf.fill(IDADDR(PEDIR_BASERELOC), IDSIZE(PEDIR_BASERELOC), FILLVAL);
mb_orelocs.alloc(mem_size(4, relocnum, 8192)); // 8192 - safety
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
sorelocs = optimizeReloc(xcounts[10], (byte *) fix[10], orelocs, ibuf + rvamin,
@ -567,7 +624,7 @@ void PeFile64::processRelocs() // pass1
}
#endif
info("Relocations: original size: %u bytes, preprocessed size: %u bytes",
(unsigned) IDSIZE(PEDIR_RELOC), sorelocs);
(unsigned) IDSIZE(PEDIR_BASERELOC), sorelocs);
}
/*************************************************************************
@ -1305,8 +1362,8 @@ void PeFile::processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t ima
const unsigned tlsdataend = tlsp->dataend - imagebase;
// now some ugly stuff: find the relocation entries in the tls data area
const unsigned skip2 = IDADDR(PEDIR_RELOC);
const unsigned take2 = IDSIZE(PEDIR_RELOC);
const unsigned skip2 = IDADDR(PEDIR_BASERELOC);
const unsigned take2 = IDSIZE(PEDIR_BASERELOC);
Reloc rel(ibuf.subref("bad tls reloc %#x", skip2, take2), take2);
unsigned pos, type;
while (rel.next(pos, type))
@ -1341,7 +1398,7 @@ void PeFile::processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t ima
}
template <typename LEXX>
void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
void PeFile::processTls2(Reloc *const rel, const Interval *const iv, unsigned newaddr,
typename tls_traits<LEXX>::cb_value_t imagebase) // pass 2
{
typedef typename tls_traits<LEXX>::tls tls;
@ -1365,7 +1422,7 @@ void PeFile::processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
SPAN_S_VAR(tls, const tlsp, mb_otls);
// now the relocation entries in the tls data area
for (ic = 0; ic < iv->ivnum; ic += 4) {
SPAN_S_VAR(byte, pp,
SPAN_S_VAR(byte, const pp,
otls + (iv->ivarr[ic].start - (tlsp->datastart - imagebase) + sizeof(tls)));
LEXX *const p = (LEXX *) raw_bytes(pp, sizeof(LEXX));
cb_value_t kc = *p;
@ -1417,8 +1474,8 @@ void PeFile::processLoadConf(Interval *iv) // pass 1
// if there were relocation entries referring to the load config table
// then we need them for the copy of the table too
const unsigned skip = IDADDR(PEDIR_RELOC);
const unsigned take = IDSIZE(PEDIR_RELOC);
const unsigned skip = IDADDR(PEDIR_BASERELOC);
const unsigned take = IDSIZE(PEDIR_BASERELOC);
Reloc rel(ibuf.subref("bad reloc %#x", skip, take), take);
unsigned pos, type;
while (rel.next(pos, type))
@ -2084,7 +2141,7 @@ unsigned PeFile::readSections(unsigned objs, unsigned usize, unsigned ih_fileali
unsigned ih_datasize) {
const unsigned xtrasize = UPX_MAX(ih_datasize, 65536u) + IDSIZE(PEDIR_IMPORT) +
IDSIZE(PEDIR_BOUND_IMPORT) + IDSIZE(PEDIR_IAT) +
IDSIZE(PEDIR_DELAY_IMPORT) + IDSIZE(PEDIR_RELOC);
IDSIZE(PEDIR_DELAY_IMPORT) + IDSIZE(PEDIR_BASERELOC);
ibuf.alloc(usize + xtrasize);
// BOUND IMPORT support. FIXME: is this ok?
@ -2136,8 +2193,8 @@ void PeFile::callCompressWithFilters(Filter &ft, int filter_strategy, unsigned i
void PeFile::callProcessRelocs(Reloc &rel, unsigned &ic) {
// WinCE wants relocation data at the beginning of a section
PeFile::processRelocs(&rel);
ODADDR(PEDIR_RELOC) = soxrelocs ? ic : 0;
ODSIZE(PEDIR_RELOC) = soxrelocs;
ODADDR(PEDIR_BASERELOC) = soxrelocs ? ic : 0;
ODSIZE(PEDIR_BASERELOC) = soxrelocs;
ic += soxrelocs;
}
@ -2498,7 +2555,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
oh.imagesize = (osection[3].vaddr + osection[3].vsize + oam1) & ~oam1;
if (soresources == 0) {
oh.objects = 3;
memset(&osection[3], 0, sizeof(osection[3]));
mem_clear(&osection[3]);
}
}
@ -2508,8 +2565,10 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
oh.codesize = osection[1].vsize;
oh.codebase = osection[1].vaddr;
setOhHeaderSize(osection);
if (rvamin < osection[0].rawdataptr)
throwCantPack("object alignment too small");
if (rvamin < osection[0].rawdataptr) {
throwCantPack("object alignment too small rvamin=%#x oraw=%#x", rvamin,
unsigned(osection[0].rawdataptr));
}
if (opt->win32_pe.strip_relocs)
oh.flags |= IMAGE_FILE_RELOCS_STRIPPED;
@ -2574,6 +2633,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
printf("%-13s: exports : %8d bytes\n", getName(), (int) soexport);
printf("%-13s: relocs : %8d bytes\n", getName(), (int) soxrelocs);
printf("%-13s: loadconf : %8d bytes\n", getName(), (int) soloadconf);
// linker->dumpSymbols();
#endif
// verify
@ -2594,12 +2654,13 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned flags,
upx_uint64_t imagebase) {
assert(bits == 32 || bits == 64);
if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (flags & IMAGE_FILE_RELOCS_STRIPPED))
if (!ODADDR(PEDIR_BASERELOC) || !ODSIZE(PEDIR_BASERELOC) ||
(flags & IMAGE_FILE_RELOCS_STRIPPED))
return;
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
if (ODSIZE(PEDIR_BASERELOC) == 8) // some tricky dlls use this
{
omemcpy(obuf + (ODADDR(PEDIR_RELOC) - rvamin), "\x0\x0\x0\x0\x8\x0\x0\x0", 8);
omemcpy(obuf + (ODADDR(PEDIR_BASERELOC) - rvamin), "\x0\x0\x0\x0\x8\x0\x0\x0", 8);
return;
}
@ -2611,9 +2672,8 @@ void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned fl
MemBuffer mb_wrkmem;
unsigned relocnum = unoptimizeReloc(rdata, mb_wrkmem, obuf, orig_crelocs, bits, true);
unsigned r16 = 0;
if (big & 6) // 16 bit relocations
{
SPAN_S_VAR(const LE32, q, (const LE32 *) raw_bytes(rdata, 0), obuf);
if (big & 6) { // count 16 bit relocations
SPAN_S_VAR(const LE32, q, SPAN_S_CAST(const LE32, rdata));
while (*q++)
r16++;
if ((big & 6) == 6)
@ -2621,14 +2681,14 @@ void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned fl
r16++;
}
Reloc rel(relocnum + r16);
if (big & 6) {
SPAN_S_VAR(const LE32, q, (const LE32 *) raw_bytes(rdata, 0), obuf);
if (big & 6) { // add 16 bit relocations
SPAN_S_VAR(const LE32, q, SPAN_S_CAST(const LE32, rdata));
while (*q)
rel.add(*q++ + rvamin, (big & 4) ? 2 : 1);
if ((big & 6) == 6)
while (*++q)
rel.add(*q + rvamin, 1);
// rdata = (byte *) raw_bytes(q, 0); // ???
// rdata = (const byte *) raw_bytes(q, 0); // advance rdata
}
SPAN_S_VAR(byte, const wrkmem, mb_wrkmem);
@ -2642,12 +2702,12 @@ void PeFile::rebuildRelocs(SPAN_S(byte) & extra_info, unsigned bits, unsigned fl
}
rel.finish(oxrelocs, soxrelocs);
omemcpy(obuf + (ODADDR(PEDIR_RELOC) - rvamin), oxrelocs, soxrelocs);
omemcpy(obuf + (ODADDR(PEDIR_BASERELOC) - rvamin), oxrelocs, soxrelocs);
delete[] oxrelocs;
oxrelocs = nullptr;
mb_wrkmem.dealloc();
ODSIZE(PEDIR_RELOC) = soxrelocs;
ODSIZE(PEDIR_BASERELOC) = soxrelocs;
}
void PeFile::rebuildExports() {
@ -2866,8 +2926,8 @@ void PeFile::unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask,
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
if (ih.flags & IMAGE_FILE_RELOCS_STRIPPED) {
oh.flags |= IMAGE_FILE_RELOCS_STRIPPED;
ODADDR(PEDIR_RELOC) = 0;
ODSIZE(PEDIR_RELOC) = 0;
ODADDR(PEDIR_BASERELOC) = 0;
ODSIZE(PEDIR_BASERELOC) = 0;
}
rebuildImports<LEXX>(extra_info, ord_mask, set_oft);

View File

@ -233,7 +233,6 @@ protected:
PEDIR_EXCEPTION = 3, // Exception table
PEDIR_SECURITY = 4, // Certificate table (file pointer)
PEDIR_BASERELOC = 5,
PEDIR_RELOC = PEDIR_BASERELOC,
PEDIR_DEBUG = 6,
PEDIR_ARCHITECTURE = 7, // Architecture-specific data
PEDIR_GLOBALPTR = 8, // Global pointer
@ -359,14 +358,14 @@ protected:
};
class Interval : private noncopyable {
unsigned capacity;
void *base;
unsigned capacity = 0;
void *base = nullptr;
public:
struct interval {
unsigned start, len;
} *ivarr;
unsigned ivnum;
};
struct interval *ivarr = nullptr;
unsigned ivnum = 0;
explicit Interval(void *b);
~Interval() noexcept;
@ -385,25 +384,33 @@ protected:
};
class Reloc : private noncopyable {
byte *start;
unsigned size;
// these are set in constructor
byte *start = nullptr;
unsigned start_size_in_bytes = 0;
bool start_did_alloc = false;
SPAN_0(byte) start_buf = nullptr;
void newRelocPos(void *p);
struct alignas(1) BaseReloc {
LE32 pagestart;
LE32 size_of_block;
};
SPAN_0(BaseReloc) rel = nullptr;
SPAN_0(LE16) rel1 = nullptr;
void advanceBaseRelocPos(void *p);
struct reloc;
reloc *rel;
LE16 *rel1;
unsigned counts[16];
unsigned counts[16] = {};
public:
explicit Reloc(byte *, unsigned);
explicit Reloc(unsigned relocnum);
void initSpans();
~Reloc() noexcept;
//
bool next(unsigned &pos, unsigned &type);
bool next(unsigned &result_pos, unsigned &result_type);
const unsigned *getcounts() const { return counts; }
//
void add(unsigned pos, unsigned type);
void finish(byte *&p, unsigned &size);
void finish(byte *&result_ptr, unsigned &result_size); // => transfer ownership
};
class Resource : private noncopyable {

View File

@ -35,11 +35,9 @@
// default: for any regular pointer, raw_bytes() is just the pointer itself
template <class T>
inline typename std::enable_if<std::is_pointer<T>::value && !upx::is_bounded_array<T>::value &&
(upx_is_integral<typename std::remove_pointer<T>::type>::value ||
std::is_void<typename std::remove_pointer<T>::type>::value),
T>::type
raw_bytes(T ptr, size_t size_in_bytes) {
inline
typename std::enable_if<std::is_pointer<T>::value && !upx::is_bounded_array<T>::value, T>::type
raw_bytes(T ptr, size_t size_in_bytes) {
if (size_in_bytes > 0) {
if very_unlikely (ptr == nullptr)
throwCantPack("raw_bytes unexpected NULL ptr");
@ -53,7 +51,7 @@ raw_bytes(T ptr, size_t size_in_bytes) {
// NOTE: index == number of elements, *NOT* size in bytes!
template <class T>
inline typename std::enable_if<std::is_pointer<T>::value && !upx::is_bounded_array<T>::value &&
upx_is_integral<typename std::remove_pointer<T>::type>::value,
!std::is_void<typename std::remove_pointer<T>::type>::value,
T>::type
raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) {
typedef typename std::remove_pointer<T>::type element_type;

View File

@ -125,6 +125,13 @@ public:
return assign(Self(other));
}
template <class U>
CSelf<U> type_cast() const {
assertInvariants();
typedef CSelf<U> R;
return R(reinterpret_cast<typename R::pointer>(ptr));
}
// comparison
bool operator==(pointer other) const { return ptr == other; }