all: assorted cleanups and updates

Changes include:
  - add a bunch of "noexcept", mostly to operators and forceinline
  - use "uchar"
  - use "charptr"
  - rename options_t to Options
  - add ptr_check_no_overlap()
  - rewrite p_exe.cpp, NFCI
  - clang-format help.cpp
  - spelling fixes
This commit is contained in:
Markus F.X.J. Oberhumer
2023-03-15 00:19:55 +01:00
parent 127fd095e7
commit a627648249
65 changed files with 1492 additions and 1138 deletions
+70 -47
View File
@@ -140,7 +140,7 @@ bool PeFile::testUnpackVersion(int version) const {
if (cpu >= IMAGE_FILE_MACHINE_I386 && cpu <= 0x150) // what is this 0x150 ???
return UPX_F_W32PE_I386;
// other or unkown (alpha, mips, etc.)
// other or unknown (alpha, mips, etc.)
throwCantPack("pefile: unsupported machine %#x", cpu);
return 0; // pacify msvc
}
@@ -274,6 +274,19 @@ void PeFile::Interval::dump() const {
// relocation handling
**************************************************************************/
namespace {
struct FixDeleter { // don't leak memory on exceptions
LE32 **fix;
size_t n;
~FixDeleter() noexcept {
for (size_t i = 0; i < n; i++) {
delete[] fix[i];
fix[i] = nullptr;
}
}
};
} // namespace
struct alignas(1) PeFile::Reloc::reloc {
LE32 pagestart;
LE32 size;
@@ -371,17 +384,21 @@ void PeFile32::processRelocs() // pass1
}
mb_orelocs.alloc(1);
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
orelocs[0] = 0; // clear
sorelocs = 0;
return;
}
for (ic = 15; ic > 3; ic--)
for (ic = 4; ic < 16; ic++)
if (counts[ic])
infoWarning("skipping unsupported relocation type %d (%d)", ic, counts[ic]);
LE32 *fix[4];
for (; ic; ic--)
FixDeleter fixdel{fix, 0}; // don't leak memory
for (ic = 0; ic < 4; ic++) {
fix[ic] = New(LE32, counts[ic]);
fixdel.n += 1;
}
unsigned xcounts[4];
memset(xcounts, 0, sizeof(xcounts));
@@ -420,7 +437,6 @@ void PeFile32::processRelocs() // pass1
orelocs = mb_orelocs; // => orelocs now is a SPAN_S
sorelocs = optimizeReloc(xcounts[3], (byte *) fix[3], orelocs, ibuf + rvamin, ibufgood - rvamin,
32, true, &big_relocs);
delete[] fix[3];
// Malware that hides behind UPX often has PE header info that is
// deliberately corrupt. Sometimes it is even tuned to cause us trouble!
@@ -433,7 +449,6 @@ void PeFile32::processRelocs() // pass1
for (ic = 2; ic; ic--) {
memcpy(orelocs + sorelocs, fix[ic], 4 * xcounts[ic]);
sorelocs += 4 * xcounts[ic];
delete[] fix[ic];
set_le32(orelocs + sorelocs, 0);
if (xcounts[ic]) {
@@ -471,13 +486,16 @@ void PeFile64::processRelocs() // pass1
return;
}
for (ic = 15; ic; ic--)
for (ic = 0; ic < 16; ic++)
if (ic != 10 && counts[ic])
infoWarning("skipping unsupported relocation type %d (%d)", ic, counts[ic]);
LE32 *fix[16];
for (ic = 15; ic; ic--)
FixDeleter fixdel{fix, 0}; // don't leak memory
for (ic = 0; ic < 16; ic++) {
fix[ic] = New(LE32, counts[ic]);
fixdel.n += 1;
}
unsigned xcounts[16];
memset(xcounts, 0, sizeof(xcounts));
@@ -495,7 +513,7 @@ void PeFile64::processRelocs() // pass1
}
// remove duplicated records
for (ic = 1; ic <= 15; ic++) {
for (ic = 1; ic < 16; ic++) {
qsort(fix[ic], xcounts[ic], 4, le32_compare);
unsigned prev = ~0u;
unsigned jc = 0;
@@ -520,9 +538,6 @@ void PeFile64::processRelocs() // pass1
sorelocs = optimizeReloc(xcounts[10], (byte *) fix[10], orelocs, ibuf + rvamin,
ibufgood - rvamin, 64, true, &big_relocs);
for (ic = 15; ic; ic--)
delete[] fix[ic];
#if 0
// Malware that hides behind UPX often has PE header info that is
// deliberately corrupt. Sometimes it is even tuned to cause us trouble!
@@ -536,7 +551,6 @@ void PeFile64::processRelocs() // pass1
{
memcpy(orelocs + sorelocs,fix[ic],4 * xcounts[ic]);
sorelocs += 4 * xcounts[ic];
delete [] fix[ic];
set_le32(orelocs + sorelocs,0);
if (xcounts[ic])
@@ -574,7 +588,7 @@ const LE32 &PeFile::IDADDR(unsigned x) const { return iddirs[x].vaddr; }
in the sorted order.
*/
class PeFile::ImportLinker : public ElfLinkerAMD64 {
class PeFile::ImportLinker final : public ElfLinkerAMD64 {
struct tstr : private ::noncopyable {
char *s = nullptr;
explicit tstr(char *str) : s(str) {}
@@ -833,7 +847,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
import_desc *const im_save = im;
if (IDADDR(PEDIR_IMPORT)) {
for (;; ++dllnum, ++im) {
unsigned const skip2 = ptr_diff_bytes(im, ibuf);
unsigned const skip2 = ptr_udiff_bytes(im, ibuf);
(void) ibuf.subref("bad import %#x", skip2, sizeof(*im));
if (!im->dllname)
break;
@@ -853,25 +867,17 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
static int __acc_cdecl_qsort compare(const void *p1, const void *p2) {
const udll *u1 = *(const udll *const *) p1;
const udll *u2 = *(const udll *const *) p2;
if (u1->isk32)
return -1;
if (u2->isk32)
return 1;
if (!*u1->lookupt)
return 1;
if (!*u2->lookupt)
return -1;
if (u1->isk32 != u2->isk32)
return u1->isk32 ? -1 : 1;
if ((*u1->lookupt != 0) != (*u2->lookupt != 0))
return (*u1->lookupt != 0) ? -1 : 1;
int rc = strcasecmp(u1->name, u2->name);
if (rc)
return rc;
if (u1->ordinal)
return -1;
if (u2->ordinal)
return 1;
if (!u1->shname)
return 1;
if (!u2->shname)
return -1;
if ((u1->ordinal != 0) != (u2->ordinal != 0))
return (u1->ordinal != 0) ? -1 : 1;
if ((u1->shname != nullptr) != (u2->shname != nullptr))
return (u1->shname != nullptr) ? -1 : 1;
rc = (int) (upx_safe_strlen(u1->shname) - upx_safe_strlen(u2->shname));
if (rc)
return rc;
@@ -904,8 +910,8 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff;
} else // it's an import by name
{
} else {
// it's an import by name
IPTR_VAR(const byte, const name, ibuf + *tarr + 2);
unsigned len = strlen(name);
soimport += len + 1;
@@ -919,9 +925,12 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
mb_oimport.clear();
oimport = mb_oimport;
qsort(idlls, dllnum, sizeof(udll *), udll::compare);
qsort(idlls, dllnum, sizeof(*idlls), udll::compare);
info("Processing imports: %d DLLs", dllnum);
for (ic = 0; ic < dllnum; ic++) {
info(" DLL %3d %s %s", ic, idlls[ic]->name, idlls[ic]->shname);
}
ilinker = new ImportLinker(sizeof(LEXX));
// create the new import table
@@ -981,7 +990,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
}
ppi++;
unsigned esize = ptr_diff_bytes(tarr, idlls[ic]->lookupt);
unsigned esize = ptr_udiff_bytes(tarr, idlls[ic]->lookupt);
lookups.add(idlls[ic]->lookupt, esize);
if (ptr_diff_bytes(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1),
(char *) idlls[ic]->lookupt) != 0) {
@@ -1299,7 +1308,7 @@ void PeFile::processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t ima
unsigned const take1 = sizeof(tls);
unsigned const skip1 = IDADDR(PEDIR_TLS);
memcpy(otls, ibuf.subref("bad tls %#x", skip1, take1), take1);
// WARNING: this can acces data in BSS
// WARNING: this can access data in BSS
unsigned const take3 = sotls - sizeof(tls);
memcpy(otls + sizeof(tls), ibuf.subref("bad tls %#x", tlsdatastart, take3), take3);
tlsindex = tlsp->tlsindex - imagebase;
@@ -1887,6 +1896,7 @@ void PeFile::processResources(Resource *res) {
soresources = ptr_diff_bytes(ores, oresources);
delete[] keep_icons;
keep_icons = nullptr;
if (!res->clear()) {
// The area occupied by the resource directory is not continuous
// so to still support uncompression, I can't zero this area.
@@ -2637,6 +2647,16 @@ void PeFile::rebuildTls() {
// this is an easy one : just do nothing ;-)
}
namespace {
template <class T>
struct VPtr {
static_assert(sizeof(T) == 1);
SPAN_S(T) ptr;
size_t vaddr;
auto operator+(size_t n) const { return ptr + mem_size(sizeof(T), n - vaddr); }
};
} // namespace
void PeFile::rebuildResources(SPAN_S(byte) & extra_info, unsigned lastvaddr) {
if (ODSIZE(PEDIR_RESOURCE) == 0 || IDSIZE(PEDIR_RESOURCE) == 0)
return;
@@ -2646,12 +2666,13 @@ void PeFile::rebuildResources(SPAN_S(byte) & extra_info, unsigned lastvaddr) {
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
if (lastvaddr > vaddr || (vaddr - lastvaddr) > ibuf.getSize())
if (vaddr < lastvaddr || (vaddr - lastvaddr) > ibuf.getSize())
throwCantUnpack("corrupted PE header");
// TODO: introduce WildPtr for "virtual pointer" pointing before a buffer
const byte *r = ibuf.raw_bytes(0) - lastvaddr;
Resource res(r + vaddr, ibuf, ibuf + ibuf.getSize());
// INFO: use VPtr for "virtual pointer" pointing before a buffer
//// const byte *const r = ibuf.raw_bytes(0) - lastvaddr;
VPtr<const byte> const r{ibuf, lastvaddr};
Resource res(raw_bytes(r + vaddr, 0), ibuf, ibuf + ibuf.getSize());
while (res.next())
if (res.offs() > vaddr) {
ICHECK(r + (res.offs() - 4), 4);
@@ -2702,8 +2723,9 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool
}
sdllnames = ALIGN_UP(sdllnames, 2u);
// TODO: introduce WildPtr for "virtual pointer" pointing before a buffer
byte *const Obuf = obuf.raw_bytes(0) - rvamin;
// INFO: use VPtr for "virtual pointer" pointing before a buffer
//// byte *const Obuf = obuf.raw_bytes(0) - rvamin;
VPtr<byte> const Obuf{obuf, rvamin};
#if 0
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
import_desc *im = im0;
@@ -2711,9 +2733,10 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool
byte *importednames = dllnames + sdllnames;
byte * const importednames_start = importednames;
#else
SPAN_S_VAR(import_desc, const im0, (import_desc *) (Obuf + ODADDR(PEDIR_IMPORT)), obuf);
SPAN_S_VAR(import_desc, const im0, (import_desc *) raw_bytes(Obuf + ODADDR(PEDIR_IMPORT), 0),
obuf);
SPAN_S_VAR(import_desc, im, im0);
SPAN_0_VAR(byte, dllnames, inamespos ? Obuf + inamespos : nullptr, obuf);
SPAN_0_VAR(byte, dllnames, inamespos ? raw_bytes(Obuf + inamespos, 0) : nullptr, obuf);
SPAN_0_VAR(byte, importednames, inamespos ? dllnames + sdllnames : nullptr);
SPAN_0_VAR(byte, const importednames_start, importednames);
#endif
@@ -2728,7 +2751,7 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool
if (inamespos) {
// now I rebuild the dll names
omemcpy(dllnames, dname, dlen + 1);
im->dllname = ptr_udiff_bytes(dllnames, Obuf);
im->dllname = ptr_udiff_bytes(dllnames, obuf) + rvamin;
//;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1;
} else {
@@ -2738,7 +2761,7 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool
if (set_oft)
im->oft = iatoffs;
OPTR_VAR(LEXX, newiat, (LEXX *) (Obuf + iatoffs));
OPTR_VAR(LEXX, newiat, (LEXX *) raw_bytes(Obuf + iatoffs, 0));
// restore the imported names+ordinals
for (p += 8; *p; ++newiat)
@@ -2749,7 +2772,7 @@ void PeFile::rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool
importednames -= 1;
omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2);
*newiat = ptr_udiff_bytes(importednames, Obuf);
*newiat = ptr_udiff_bytes(importednames, obuf) + rvamin;
importednames += 2 + ilen;
} else {
// Beware overlap!
@@ -2986,7 +3009,7 @@ void PeFile32::readPeHeader() {
void PeFile32::pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase,
bool last_section_rsrc_only) {
super::pack0<LE32>(fo, ih, oh, subsystem_mask, default_imagebase, last_section_rsrc_only);
infoWarning("End of PeFile32::pack0");
// infoWarning("End of PeFile32::pack0");
}
void PeFile32::unpack(OutputFile *fo) {