diff --git a/src/packer.cpp b/src/packer.cpp index 2e058f3c..0291da4e 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -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); diff --git a/src/packer_r.cpp b/src/packer_r.cpp index 095931dc..61ba0e07 100644 --- a/src/packer_r.cpp +++ b/src/packer_r.cpp @@ -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; } diff --git a/src/pefile.cpp b/src/pefile.cpp index 1e0b9382..fa2850ec 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -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::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::cb_value_t ima } template -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::cb_value_t imagebase) // pass 2 { typedef typename tls_traits::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(extra_info, ord_mask, set_oft); diff --git a/src/pefile.h b/src/pefile.h index 377d0ab4..9314e381 100644 --- a/src/pefile.h +++ b/src/pefile.h @@ -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 { diff --git a/src/util/raw_bytes.h b/src/util/raw_bytes.h index a0d07d43..6d5592c5 100644 --- a/src/util/raw_bytes.h +++ b/src/util/raw_bytes.h @@ -35,11 +35,9 @@ // default: for any regular pointer, raw_bytes() is just the pointer itself template -inline typename std::enable_if::value && !upx::is_bounded_array::value && - (upx_is_integral::type>::value || - std::is_void::type>::value), - T>::type -raw_bytes(T ptr, size_t size_in_bytes) { +inline + typename std::enable_if::value && !upx::is_bounded_array::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 inline typename std::enable_if::value && !upx::is_bounded_array::value && - upx_is_integral::type>::value, + !std::is_void::type>::value, T>::type raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) { typedef typename std::remove_pointer::type element_type; diff --git a/src/util/xspan_impl_ptr.h b/src/util/xspan_impl_ptr.h index 1abcd3f2..0450c83b 100644 --- a/src/util/xspan_impl_ptr.h +++ b/src/util/xspan_impl_ptr.h @@ -125,6 +125,13 @@ public: return assign(Self(other)); } + template + CSelf type_cast() const { + assertInvariants(); + typedef CSelf R; + return R(reinterpret_cast(ptr)); + } + // comparison bool operator==(pointer other) const { return ptr == other; }