diff --git a/src/conf.h b/src/conf.h index cbf92680..4dc4f9d3 100644 --- a/src/conf.h +++ b/src/conf.h @@ -578,6 +578,11 @@ inline void operator delete[](void *p) #include "console.h" +// classes +class ElfLinker; +typedef ElfLinker Linker; + + // main.cpp extern const char *progname; void init_options(struct options_t *o); diff --git a/src/linker.cpp b/src/linker.cpp index 34abca96..b91bea66 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -29,325 +29,12 @@ #include "conf.h" #include "linker.h" -static int hex(char c) +static int hex(unsigned char c) { return (c & 0xf) + (c > '9' ? 9 : 0); } -/************************************************************************* -// -**************************************************************************/ - -#define NJUMPS 200 -#define NSECTIONS 550 - -class DefaultLinker::Label -{ - char label[31 + 1]; -public: - unsigned set(const char *s) - { - size_t len = strlen(s); - assert(len > 0); assert(len <= 31); - strcpy(label, s); - return len + 1; - } - unsigned set(const unsigned char *s) { return set((const char *)s); } - operator const char *() const { return label; } -}; - - -struct DefaultLinker::Jump -{ - int pos; - int len; - int toffs; - DefaultLinker::Label tsect; -}; - -struct DefaultLinker::Section -{ - int istart; - int ostart; - int len; - unsigned char align; - DefaultLinker::Label name; -}; - - -DefaultLinker::DefaultLinker() : - iloader(NULL), oloader(NULL), jumps(NULL), sections(NULL) -{ -} - - -void DefaultLinker::init(const void *pdata, int plen, int pinfo) -{ - assert(!frozen); - ilen = plen; - iloader = new unsigned char[plen + 8192]; - memcpy(iloader, pdata, plen); - oloader = new unsigned char[plen]; - olen = 0; - align_hack = 0; - align_offset = 0; - info = pinfo; - njumps = nsections = frozen = 0; - jumps = new Jump[NJUMPS]; - sections = new Section[NSECTIONS]; - - unsigned char *p = iloader + info; - while (get32(p) != (unsigned)(-1)) - { - if (get32(p)) - { - p += sections[nsections].name.set(p); - sections[nsections].istart = get32(p); - sections[nsections++].ostart = -1; - p += 4; - assert(nsections < NSECTIONS); - } - else - { - int l; - for (l = get32(p+4) - 1; iloader[l] == 0; l--) - ; - - jumps[njumps].pos = l+1; - jumps[njumps].len = get32(p+4)-jumps[njumps].pos; - p += 8 + jumps[njumps].tsect.set(p + 8); - jumps[njumps++].toffs = get32(p); - p += 4; - assert(njumps < NJUMPS); - } - } - - int ic; - for (ic = 0; ic < nsections - 1; ic++) - sections[ic].len = sections[ic+1].istart - sections[ic].istart; - sections[ic].len = 0; -} - - -DefaultLinker::~DefaultLinker() -{ - delete [] iloader; - delete [] oloader; - delete [] jumps; - delete [] sections; -} - - -void DefaultLinker::setLoaderAlignOffset(int offset) -{ - assert(!frozen); - align_offset = offset; -} - - -int DefaultLinker::addSection(const char *sname) -{ - assert(!frozen); - if (sname[0] == 0) - return olen; - char *begin = strdup(sname); - char *end = begin + strlen(begin); - for (char *sect = begin; sect < end; ) - { - for (char *tokend = sect; *tokend; tokend++) - if (*tokend == ' ' || *tokend == ',') - { - *tokend = 0; - break; - } - - if (*sect == '+') // alignment - { - if (sect[1] == '0') - align_hack = olen + align_offset; - else - { - unsigned j = hex(sect[1]); - j = (hex(sect[2]) - ((olen + align_offset) - align_hack) ) % j; - memset(oloader+olen, (sect[3] == 'C' ? 0x90 : 0), j); - olen += j; - } - } - else - { - int ic; - for (ic = 0; ic < nsections; ic++) - if (strcmp(sect, sections[ic].name) == 0) - { - memcpy(oloader+olen,iloader+sections[ic].istart,sections[ic].len); - sections[ic].ostart = olen; - olen += sections[ic].len; - break; - } - if (ic == nsections) { - printf("%s", sect); - assert(ic != nsections); - } - } - sect += strlen(sect) + 1; - } - free(begin); - return olen; -} - - -void DefaultLinker::addSection(const char *sname, const void *sdata, int slen, int align) -{ - assert(!frozen); - // add a new section - can be used for adding stuff like ident or header - sections[nsections].name.set(sname); - sections[nsections].istart = ilen; - sections[nsections].len = slen; - sections[nsections].align = align; - sections[nsections++].ostart = olen; - assert(nsections < NSECTIONS); - memcpy(iloader+ilen, sdata, slen); - ilen += slen; -} - - -void DefaultLinker::freeze() -{ - if (frozen) - return; - - int ic,jc,kc; - for (ic = 0; ic < njumps; ic++) - { - for (jc = 0; jc < nsections-1; jc++) - if (jumps[ic].pos >= sections[jc].istart - && jumps[ic].pos < sections[jc+1].istart) - break; - assert(jc!=nsections-1); - if (sections[jc].ostart < 0) - continue; - - for (kc = 0; kc < nsections-1; kc++) - if (strcmp(jumps[ic].tsect,sections[kc].name) == 0) - break; - assert(kc!=nsections-1); - - int offs = sections[kc].ostart+jumps[ic].toffs - - (jumps[ic].pos+jumps[ic].len - - sections[jc].istart+sections[jc].ostart); - - if (jumps[ic].len == 1) - assert(-128 <= offs && offs <= 127); - - set32(&offs,offs); - memcpy(oloader+sections[jc].ostart+jumps[ic].pos-sections[jc].istart,&offs,jumps[ic].len); - } - - frozen = true; -} - - -int DefaultLinker::getSection(const char *sname, int *slen) -{ - assert(frozen); - - for (int ic = 0; ic < nsections; ic++) - if (strcmp(sname, sections[ic].name) == 0) - { - if (slen) - *slen = sections[ic].len; - return sections[ic].ostart; - } - return -1; -} - - -unsigned char *DefaultLinker::getLoader(int *llen) -{ - assert(frozen); - - if (llen) - *llen = olen; - return oloader; -} - - -/************************************************************************* -// -**************************************************************************/ - -SimpleLinker::SimpleLinker() : - oloader(NULL) -{ -} - - -void SimpleLinker::init(const void *pdata, int plen, int pinfo) -{ - assert(!frozen); - UNUSED(pinfo); - oloader = new unsigned char[plen]; - olen = plen; - memcpy(oloader, pdata, plen); -} - - -SimpleLinker::~SimpleLinker() -{ - delete [] oloader; -} - - -void SimpleLinker::setLoaderAlignOffset(int offset) -{ - assert(!frozen); - UNUSED(offset); - assert(0); -} - - -int SimpleLinker::addSection(const char *sname) -{ - assert(!frozen); - UNUSED(sname); - assert(0); - return -1; -} - - -void SimpleLinker::addSection(const char *sname, const void *sdata, int slen, int align) -{ - assert(!frozen); - UNUSED(sname); UNUSED(sdata); UNUSED(slen); UNUSED(align); - assert(0); -} - - -void SimpleLinker::freeze() -{ - frozen = true; -} - - -int SimpleLinker::getSection(const char *sname, int *slen) -{ - assert(frozen); - UNUSED(sname); UNUSED(slen); - assert(0); - return -1; -} - - -unsigned char *SimpleLinker::getLoader(int *llen) -{ - assert(frozen); - if (llen) - *llen = olen; - return oloader; -} - - /************************************************************************* // **************************************************************************/ @@ -535,9 +222,11 @@ void ElfLinker::addRelocation(const char *section, unsigned off, type, findSymbol(symbol), add); } -ElfLinker::ElfLinker() : input(NULL), output(NULL), head(NULL), tail(NULL), +ElfLinker::ElfLinker() : + frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL), sections(NULL), symbols(NULL), relocations(NULL) -{} +{ +} ElfLinker::~ElfLinker() { @@ -792,7 +481,7 @@ void ElfLinkerX86::relocate1(Relocation *rel, upx_byte *location, if (strcmp(type, "8") == 0) { - int displ = (char) *location + (int) value; + int displ = (signed char) *location + (int) value; if (displ < -127 || displ > 128) { printf("target out of range (%d) in reloc %s:%x\n", @@ -824,7 +513,7 @@ void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location, if (strcmp(type, "8") == 0) { - int displ = (char) *location + (int) value; + int displ = (signed char) *location + (int) value; if (displ < -127 || displ > 128) { printf("target out of range (%d) in reloc %s:%x\n", diff --git a/src/linker.h b/src/linker.h index 3a94599d..bf37e381 100644 --- a/src/linker.h +++ b/src/linker.h @@ -30,136 +30,15 @@ #define __UPX_LINKER_H -/************************************************************************* -// -**************************************************************************/ - -class Linker -{ -protected: - Linker() : frozen(false) { } -public: - virtual ~Linker() { } - // endian abstraction - virtual unsigned get32(const void *b) const = 0; - virtual void set32(void *b, unsigned v) const = 0; - // - virtual bool isFrozen() const { return frozen; } - // - virtual void init(const void *pdata, int plen, int pinfo) = 0; - virtual void setLoaderAlignOffset(int phase) = 0; - virtual int addSection(const char *sname) = 0; - virtual void addSection(const char *sname, const void *sdata, int slen, int align) = 0; - virtual void freeze() = 0; - virtual int getSection(const char *sname, int *slen=NULL) = 0; - virtual unsigned char *getLoader(int *llen=NULL) = 0; - - // for ElfLinker descendants - virtual void defineSymbol(const char *, unsigned) {} - virtual void relocate() {} - virtual unsigned getSymbolOffset(const char *) const { return 0; } - -protected: - bool frozen; - -private: - // disable copy and assignment - Linker(const Linker &); // {} - Linker& operator= (const Linker &); // { return *this; } -}; - - -/************************************************************************* -// DefaultLinker -**************************************************************************/ - -class DefaultLinker : public Linker -{ -protected: - DefaultLinker(); -public: - virtual ~DefaultLinker(); - // - virtual void init(const void *pdata, int plen, int pinfo); - virtual void setLoaderAlignOffset(int phase); - virtual int addSection(const char *sname); - virtual void addSection(const char *sname, const void *sdata, int slen, int align); - virtual void freeze(); - virtual int getSection(const char *sname, int *slen=NULL); - virtual unsigned char *getLoader(int *llen=NULL); - -private: - struct Label; - struct Jump; - struct Section; - - unsigned char *iloader, *oloader; - int ilen, olen; - int info; - Jump *jumps; - int njumps; - Section *sections; - int nsections; - int align_hack; - int align_offset; -}; - - -template -struct TDefaultLinker : public DefaultLinker -{ - virtual unsigned get32(const void *b) const { return T::get32(b); } - virtual void set32(void *b, unsigned v) const { T::set32(b, v); } -}; - -typedef TDefaultLinker DefaultBELinker; -typedef TDefaultLinker DefaultLELinker; - - -/************************************************************************* -// SimpleLinker -**************************************************************************/ - -class SimpleLinker : public Linker -{ -protected: - SimpleLinker(); -public: - virtual ~SimpleLinker(); - // - virtual void init(const void *pdata, int plen, int pinfo); - virtual void setLoaderAlignOffset(int phase); - virtual int addSection(const char *sname); - virtual void addSection(const char *sname, const void *sdata, int slen, int align); - virtual void freeze(); - virtual int getSection(const char *sname, int *slen=NULL); - virtual unsigned char *getLoader(int *llen=NULL); -private: - unsigned char *oloader; - int olen; -}; - - -template -struct TSimpleLinker : public SimpleLinker -{ - virtual unsigned get32(const void *b) const { return T::get32(b); } - virtual void set32(void *b, unsigned v) const { T::set32(b, v); } -}; - -typedef TSimpleLinker SimpleBELinker; -typedef TSimpleLinker SimpleLELinker; - - /************************************************************************* // ElfLinker **************************************************************************/ -class ElfLinker : public Linker, private nocopy +class ElfLinker : private nocopy { - typedef Linker super; - protected: + bool frozen; // FIXME: can we remove this ? + struct Section; struct Symbol; struct Relocation; @@ -192,8 +71,6 @@ protected: public: ElfLinker(); - -protected: virtual ~ElfLinker(); virtual void init(const void *pdata, int plen, int); @@ -207,17 +84,13 @@ protected: virtual void defineSymbol(const char *name, unsigned value); virtual unsigned getSymbolOffset(const char *) const; - virtual unsigned get32(const void *) const { return 0; } - virtual void set32(void *, unsigned) const {} - - // - void alignWithByte(unsigned len, upx_byte b); virtual void align(unsigned len); virtual void relocate1(Relocation *, upx_byte *location, unsigned value, const char *type); }; + struct ElfLinker::Section : private nocopy { char *name; @@ -232,6 +105,7 @@ struct ElfLinker::Section : private nocopy ~Section(); }; + struct ElfLinker::Symbol : private nocopy { char *name; @@ -242,6 +116,7 @@ struct ElfLinker::Symbol : private nocopy ~Symbol(); }; + struct ElfLinker::Relocation : private nocopy { Section *section; @@ -265,6 +140,7 @@ protected: unsigned value, const char *type); }; + class ElfLinkerAMD64 : public ElfLinker { typedef ElfLinker super; @@ -275,6 +151,7 @@ protected: unsigned value, const char *type); }; + class ElfLinkerPpc32 : public ElfLinker { typedef ElfLinker super; @@ -285,6 +162,7 @@ protected: unsigned value, const char *type); }; + class ElfLinkerArmLE : public ElfLinker { typedef ElfLinker super; @@ -294,6 +172,7 @@ protected: unsigned value, const char *type); }; + class ElfLinkerArmBE : public ElfLinker { typedef ElfLinker super; diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 22446431..bdeac679 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -64,6 +64,11 @@ const int *PackMachPPC32::getFilters() const return filters; } +Linker *PackMachPPC32::newLinker() const +{ + return new ElfLinker; +} + int PackMachPPC32::buildMachLoader( upx_byte const *const proto, diff --git a/src/p_mach.h b/src/p_mach.h index eddfb6f9..d55276de 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -181,6 +181,7 @@ public: protected: virtual int buildLoader(const Filter *ft); + virtual Linker* newLinker() const; virtual void patchLoader(); virtual void patchLoaderChecksum(); virtual void updateLoader(OutputFile *); diff --git a/src/p_w16ne.cpp b/src/p_w16ne.cpp index 2a1f1db9..8ad58c48 100644 --- a/src/p_w16ne.cpp +++ b/src/p_w16ne.cpp @@ -31,6 +31,7 @@ #include "filter.h" #include "packer.h" #include "p_w16ne.h" +#include "linker.h" /************************************************************************* @@ -72,6 +73,12 @@ int PackW16Ne::buildLoader(const Filter *ft) } +Linker* PackW16Ne::newLinker() const +{ + return new ElfLinkerX86; +} + + /************************************************************************* // **************************************************************************/ diff --git a/src/p_w16ne.h b/src/p_w16ne.h index 5b7ad718..7ffaa1b5 100644 --- a/src/p_w16ne.h +++ b/src/p_w16ne.h @@ -55,6 +55,7 @@ protected: virtual int readFileHeader(void); virtual int buildLoader(const Filter *ft); + virtual Linker* newLinker() const; }; diff --git a/src/packer.cpp b/src/packer.cpp index 7f186698..5a157f11 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -986,15 +986,6 @@ int Packer::getLoaderSize() const // loader util **************************************************************************/ -Linker* Packer::newLinker() const -{ - if (getFormat() < 128) - return new DefaultLELinker; - else - return new DefaultBELinker; -} - - char const *Packer::getIdentstr(unsigned *size, int small) const { static char identbig[] = @@ -1141,7 +1132,7 @@ int Packer::getLoaderSectionStart(const char *name, int *slen) const // executable formats. // // It will replace the tryFilters() / compress() call sequence. - +// // 2006-02-15: hdr_buf and hdr_u_len are default empty input "header" array // to fix a 2-pass problem with Elf headers. As of today there can be // only one decompression method per executable output file, and that method diff --git a/src/packer.h b/src/packer.h index a73c2ad3..dd408c33 100644 --- a/src/packer.h +++ b/src/packer.h @@ -36,7 +36,6 @@ class OutputFile; class Packer; class PackMaster; class UiPacker; -class Linker; class Filter; @@ -205,12 +204,11 @@ protected: // loader core virtual int buildLoader(const Filter *ft) = 0; - // loader util for any linker + virtual Linker* newLinker() const = 0; + // loader util for linker virtual void freezeLoader(); virtual upx_byte *getLoader() const; virtual int getLoaderSize() const; - // loader util when using DefaultLinker - virtual Linker* newLinker() const; virtual const char *getIdentstr(unsigned *size, int small=-1) const; virtual void initLoader(const void *pdata, int plen, int pinfo=-1, int small=-1); #if 1 && (ACC_CC_GNUC >= 0x040100)