From 996a99ad756b5d2195211b03ce7b7b0a3d45b226 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 20 Aug 2006 11:15:36 +0200 Subject: [PATCH] Some linker.cpp cleanups. --- src/linker.cpp | 281 ++++++++++++++++++++++++++-------------------- src/linker.h | 109 ++++++++++-------- src/p_tos.cpp | 27 ----- src/p_w32pe.cpp | 2 +- src/packer.cpp | 10 +- src/packer.h | 2 +- src/stub/Makefile | 4 +- 7 files changed, 224 insertions(+), 211 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index b91bea66..dfc98f4f 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -34,6 +34,16 @@ static int hex(unsigned char c) return (c & 0xf) + (c > '9' ? 9 : 0); } +static bool update_capacity(unsigned size, unsigned *capacity) +{ + if (size < *capacity) + return false; + if (*capacity == 0) + *capacity = 16; + while (size >= *capacity) + *capacity *= 2; + return true; +} /************************************************************************* // @@ -65,8 +75,8 @@ ElfLinker::Symbol::~Symbol() free(name); } -ElfLinker::Relocation::Relocation(Section *s, unsigned o, const char *t, - Symbol *v, unsigned a) : +ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, + const Symbol *v, unsigned a) : section(s), offset(o), type(t), value(v), add(a) {} @@ -175,7 +185,7 @@ void ElfLinker::preprocessRelocations(char *start, const char *end) } } -ElfLinker::Section *ElfLinker::findSection(const char *name) +ElfLinker::Section *ElfLinker::findSection(const char *name) const { for (unsigned ic = 0; ic < nsections; ic++) if (strcmp(sections[ic]->name, name) == 0) @@ -186,45 +196,51 @@ ElfLinker::Section *ElfLinker::findSection(const char *name) return NULL; } -ElfLinker::Symbol *ElfLinker::findSymbol(const char *name) +ElfLinker::Symbol *ElfLinker::findSymbol(const char *name) /*const*/ { for (unsigned ic = 0; ic < nsymbols; ic++) if (strcmp(symbols[ic]->name, name) == 0) return symbols[ic]; - if ('*'==name[0]) { // *ABS* - addSymbol(name, name, 0); - return symbols[nsymbols -1]; - } + // FIXME: this should be a const method ! + if ('*' == name[0]) // *ABS* + return addSymbol(name, name, 0); + printf("unknown symbol %s\n", name); abort(); return NULL; } -void ElfLinker::addSymbol(const char *name, const char *section, +ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section, unsigned offset) { - symbols = static_cast(realloc(symbols, (nsymbols + 1) - * sizeof(Symbol *))); - assert(symbols); - symbols[nsymbols++] = new Symbol(name, findSection(section), offset); + if (update_capacity(nsymbols, &nsymbols_capacity)) + symbols = static_cast(realloc(symbols, nsymbols_capacity * sizeof(Symbol *))); + assert(symbols != NULL); + Symbol *sym = new Symbol(name, findSection(section), offset); + symbols[nsymbols++] = sym; + return sym; } -void ElfLinker::addRelocation(const char *section, unsigned off, - const char *type, const char *symbol, - unsigned add) +ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, + const char *type, const char *symbol, + unsigned add) { - relocations = static_cast(realloc(relocations, - (nrelocations + 1) - * sizeof(Relocation *))); - assert(relocations); - relocations[nrelocations++] = new Relocation(findSection(section), off, - type, findSymbol(symbol), add); + if (update_capacity(nrelocations, &nrelocations_capacity)) + relocations = static_cast(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *))); + assert(relocations != NULL); + Relocation *rel = new Relocation(findSection(section), off, + type, findSymbol(symbol), add); + relocations[nrelocations++] = rel; + return rel; } ElfLinker::ElfLinker() : frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL), - sections(NULL), symbols(NULL), relocations(NULL) + sections(NULL), symbols(NULL), relocations(NULL), + nsections(0), nsections_capacity(0), + nsymbols(0), nsymbols_capacity(0), + nrelocations(0), nrelocations_capacity(0) { } @@ -245,7 +261,7 @@ ElfLinker::~ElfLinker() free(relocations); } -void ElfLinker::init(const void *pdata, int plen, int) +void ElfLinker::init(const void *pdata, int plen) { upx_byte *i = new upx_byte[plen + 1]; memcpy(i, pdata, plen); @@ -341,10 +357,12 @@ int ElfLinker::addSection(const char *sname) void ElfLinker::addSection(const char *sname, const void *sdata, int slen, int align) { assert(!frozen); - sections = static_cast
(realloc(sections, (nsections + 1) - * sizeof(Section *))); + if (update_capacity(nsections, &nsections_capacity)) + sections = static_cast
(realloc(sections, nsections_capacity * sizeof(Section *))); assert(sections); - sections[nsections++] = new Section(sname, sdata, slen, align); + Section *sec = new Section(sname, sdata, slen, align); + sections[nsections++] = sec; + //return sec; } void ElfLinker::freeze() @@ -444,62 +462,20 @@ void ElfLinker::align(unsigned len) alignWithByte(len, 0); } -void ElfLinker::relocate1(Relocation *rel, upx_byte *, +void ElfLinker::relocate1(const Relocation *rel, upx_byte *, unsigned, const char *) { printf("unknown relocation type '%s\n", rel->type); abort(); } -void ElfLinkerX86::align(unsigned len) -{ - alignWithByte(len, 0x90); -} -void ElfLinkerAMD64::align(unsigned len) -{ - alignWithByte(len, 0x90); -} +/************************************************************************* +// ElfLinker arch subclasses +**************************************************************************/ -void ElfLinkerPpc32::align(unsigned len) -{ - alignWithByte(len, 0); -} - -void ElfLinkerX86::relocate1(Relocation *rel, upx_byte *location, - unsigned value, const char *type) -{ - if (strncmp(type, "R_386_", 6)) - return super::relocate1(rel, location, value, type); - type += 6; - - if (strncmp(type, "PC", 2) == 0) - { - value -= rel->section->offset + rel->offset; - type += 2; - } - - if (strcmp(type, "8") == 0) - { - int displ = (signed char) *location + (int) value; - if (displ < -127 || displ > 128) - { - printf("target out of range (%d) in reloc %s:%x\n", - displ, rel->section->name, rel->offset); - abort(); - } - *location += value; - } - 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); - else - super::relocate1(rel, location, value, type); -} - -void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location, - unsigned value, const char *type) +void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, + unsigned value, const char *type) { if (strncmp(type, "R_X86_64_", 9)) return super::relocate1(rel, location, value, type); @@ -530,8 +506,90 @@ void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location, super::relocate1(rel, location, value, type); } -void ElfLinkerPpc32::relocate1(Relocation *rel, upx_byte *location, - unsigned value, const char *type) + +void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, + unsigned 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_be32(location, get_be32(location) + value); + } + else if (strcmp(type, "R_ARM_THM_CALL") == 0) + { + value -= rel->section->offset + rel->offset; + value += ((get_be16(location) & 0x7ff) << 12); + value += (get_be16(location + 2) & 0x7ff) << 1; + + set_be16(location, 0xf000 + ((value >> 12) & 0x7ff)); + set_be16(location + 2, 0xf800 + ((value >> 1) & 0x7ff)); + + //(b, 0xF000 + ((v - 1) / 2) * 0x10000); + //set_be32(location, get_be32(location) + value / 4); + } + else + super::relocate1(rel, location, value, type); +} + + +void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, + unsigned 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) + { + set_le32(location, get_le32(location) + value); + } + else if (strcmp(type, "R_ARM_THM_CALL") == 0) + { + value -= rel->section->offset + rel->offset; + value += ((get_le16(location) & 0x7ff) << 12); + value += (get_le16(location + 2) & 0x7ff) << 1; + + set_le16(location, 0xf000 + ((value >> 12) & 0x7ff)); + set_le16(location + 2, 0xf800 + ((value >> 1) & 0x7ff)); + + //(b, 0xF000 + ((v - 1) / 2) * 0x10000); + //set_le32(location, get_le32(location) + value / 4); + } + else + super::relocate1(rel, location, value, type); +} + + +void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, + unsigned 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) + { + value -= rel->section->offset + rel->offset; + type += 2; + } + if (strcmp(type, "8") == 0) + *location += value; + else if (strcmp(type, "16") == 0) + set_be16(location, get_be16(location) + value); + else if (strcmp(type, "32") == 0) + set_be32(location, get_be32(location) + value); + else + super::relocate1(rel, location, value, type); +} + + +void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, + unsigned value, const char *type) { if (strncmp(type, "R_PPC_", 6)) return super::relocate1(rel, location, value, type); @@ -568,58 +626,35 @@ void ElfLinkerPpc32::relocate1(Relocation *rel, upx_byte *location, super::relocate1(rel, location, value, type); } -void ElfLinkerArmLE::relocate1(Relocation *rel, upx_byte *location, - unsigned value, const char *type) + +void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location, + unsigned value, const char *type) { - if (strcmp(type, "R_ARM_PC24") == 0) + if (strncmp(type, "R_386_", 6)) + return super::relocate1(rel, location, value, type); + type += 6; + + if (strncmp(type, "PC", 2) == 0) { value -= rel->section->offset + rel->offset; - set_le24(location, get_le24(location) + value / 4); + type += 2; } - else if (strcmp(type, "R_ARM_ABS32") == 0) + + if (strcmp(type, "8") == 0) { + int displ = (signed char) *location + (int) value; + if (displ < -127 || displ > 128) + { + printf("target out of range (%d) in reloc %s:%x\n", + displ, rel->section->name, rel->offset); + abort(); + } + *location += value; + } + 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); - } - else if (strcmp(type, "R_ARM_THM_CALL") == 0) - { - value -= rel->section->offset + rel->offset; - value += ((get_le16(location) & 0x7ff) << 12); - value += (get_le16(location + 2) & 0x7ff) << 1; - - set_le16(location, 0xf000 + ((value >> 12) & 0x7ff)); - set_le16(location + 2, 0xf800 + ((value >> 1) & 0x7ff)); - - //(b, 0xF000 + ((v - 1) / 2) * 0x10000); - //set_le32(location, get_le32(location) + value / 4); - } - else - super::relocate1(rel, location, value, type); -} - -void ElfLinkerArmBE::relocate1(Relocation *rel, upx_byte *location, - unsigned 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_be32(location, get_be32(location) + value); - } - else if (strcmp(type, "R_ARM_THM_CALL") == 0) - { - value -= rel->section->offset + rel->offset; - value += ((get_be16(location) & 0x7ff) << 12); - value += (get_be16(location + 2) & 0x7ff) << 1; - - set_be16(location, 0xf000 + ((value >> 12) & 0x7ff)); - set_be16(location + 2, 0xf800 + ((value >> 1) & 0x7ff)); - - //(b, 0xF000 + ((v - 1) / 2) * 0x10000); - //set_be32(location, get_be32(location) + value / 4); - } else super::relocate1(rel, location, value, type); } diff --git a/src/linker.h b/src/linker.h index bf37e381..e06f6d32 100644 --- a/src/linker.h +++ b/src/linker.h @@ -37,12 +37,12 @@ class ElfLinker : private nocopy { protected: - bool frozen; // FIXME: can we remove this ? - struct Section; struct Symbol; struct Relocation; + bool frozen; // FIXME: can we remove this ? + upx_byte *input; int inputlen; upx_byte *output; @@ -56,24 +56,27 @@ protected: Relocation **relocations; unsigned nsections; + unsigned nsections_capacity; unsigned nsymbols; + unsigned nsymbols_capacity; unsigned nrelocations; + unsigned nrelocations_capacity; void preprocessSections(char *start, const char *end); void preprocessSymbols(char *start, const char *end); void preprocessRelocations(char *start, const char *end); - Section *findSection(const char *name); - Symbol *findSymbol(const char *name); + Section *findSection(const char *name) const; + Symbol *findSymbol(const char *name) /*const*/; - void addSymbol(const char *name, const char *section, unsigned offset); - void addRelocation(const char *section, unsigned off, const char *type, - const char *symbol, unsigned add); + Symbol *addSymbol(const char *name, const char *section, unsigned offset); + Relocation *addRelocation(const char *section, unsigned off, const char *type, + const char *symbol, unsigned add); public: ElfLinker(); virtual ~ElfLinker(); - virtual void init(const void *pdata, int plen, int); + virtual void init(const void *pdata, int plen); virtual void setLoaderAlignOffset(int phase); virtual int addSection(const char *sname); virtual void addSection(const char *sname, const void *sdata, int slen, int align); @@ -86,7 +89,7 @@ public: void alignWithByte(unsigned len, upx_byte b); virtual void align(unsigned len); - virtual void relocate1(Relocation *, upx_byte *location, + virtual void relocate1(const Relocation *, upx_byte *location, unsigned value, const char *type); }; @@ -119,56 +122,27 @@ struct ElfLinker::Symbol : private nocopy struct ElfLinker::Relocation : private nocopy { - Section *section; + const Section *section; unsigned offset; const char *type; - Symbol *value; + const Symbol *value; unsigned add; // used in .rela relocations - Relocation(Section *s, unsigned o, const char *t, - Symbol *v, unsigned a); + Relocation(const Section *s, unsigned o, const char *t, + const Symbol *v, unsigned a); }; -class ElfLinkerX86 : public ElfLinker -{ - typedef ElfLinker super; - -protected: - virtual void align(unsigned len); - virtual void relocate1(Relocation *, upx_byte *location, - unsigned value, const char *type); -}; - +/************************************************************************* +// ElfLinker arch subclasses +**************************************************************************/ class ElfLinkerAMD64 : public ElfLinker { typedef ElfLinker super; - protected: - virtual void align(unsigned len); - virtual void relocate1(Relocation *, upx_byte *location, - unsigned value, const char *type); -}; - - -class ElfLinkerPpc32 : public ElfLinker -{ - typedef ElfLinker super; - -protected: - virtual void align(unsigned len); - virtual void relocate1(Relocation *, upx_byte *location, - unsigned value, const char *type); -}; - - -class ElfLinkerArmLE : public ElfLinker -{ - typedef ElfLinker super; - -protected: - virtual void relocate1(Relocation *, upx_byte *location, + virtual void align(unsigned len) { alignWithByte(len, 0x90); } + virtual void relocate1(const Relocation *, upx_byte *location, unsigned value, const char *type); }; @@ -176,13 +150,50 @@ protected: class ElfLinkerArmBE : public ElfLinker { typedef ElfLinker super; - protected: - virtual void relocate1(Relocation *, upx_byte *location, + virtual void relocate1(const Relocation *, upx_byte *location, unsigned value, const char *type); }; +class ElfLinkerArmLE : public ElfLinker +{ + typedef ElfLinker super; +protected: + virtual void relocate1(const Relocation *, upx_byte *location, + unsigned value, const char *type); +}; + + +class ElfLinkerM68k : public ElfLinker +{ + typedef ElfLinker super; +protected: + virtual void relocate1(const Relocation *, upx_byte *location, + unsigned value, const char *type); +}; + + +class ElfLinkerPpc32 : public ElfLinker +{ + typedef ElfLinker super; +protected: + virtual void relocate1(const Relocation *, upx_byte *location, + unsigned value, const char *type); +}; + + +class ElfLinkerX86 : public ElfLinker +{ + typedef ElfLinker super; +protected: + virtual void align(unsigned len) { alignWithByte(len, 0x90); } + virtual void relocate1(const Relocation *, upx_byte *location, + unsigned value, const char *type); +}; + + + #endif /* already included */ diff --git a/src/p_tos.cpp b/src/p_tos.cpp index 155a1a81..cc025a91 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -78,33 +78,6 @@ const int *PackTos::getFilters() const Linker* PackTos::newLinker() const { - class ElfLinkerM68k : public ElfLinker - { - typedef ElfLinker super; - - virtual void relocate1(Relocation *rel, upx_byte *location, - unsigned 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) - { - value -= rel->section->offset + rel->offset; - type += 2; - } - if (strcmp(type, "8") == 0) - *location += value; - else if (strcmp(type, "16") == 0) - set_be16(location, get_be16(location) + value); - else if (strcmp(type, "32") == 0) - set_be32(location, get_be32(location) + value); - else - super::relocate1(rel, location, value, type); - } - }; - return new ElfLinkerM68k; } diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index 32ae42d8..1d788a77 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -545,7 +545,7 @@ int PackW32Pe::buildLoader(const Filter *ft) tmp_tlsindex = 0; // prepare loader - initLoader(nrv_loader, sizeof(nrv_loader), -1, 2); + initLoader(nrv_loader, sizeof(nrv_loader), 2); addLoader(isdll ? "PEISDLL1" : "", "PEMAIN01", icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "", diff --git a/src/packer.cpp b/src/packer.cpp index 5a157f11..85ecb701 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -1046,17 +1046,11 @@ char const *Packer::getIdentstr(unsigned *size, int small) const } -void Packer::initLoader(const void *pdata, int plen, int pinfo, int small) +void Packer::initLoader(const void *pdata, int plen, int small) { - if (pinfo < 0) - { - pinfo = get_le16((const unsigned char *)pdata + plen - 2); - pinfo = (pinfo + 3) &~ 3; - } - delete linker; linker = newLinker(); - linker->init(pdata, plen, pinfo); + linker->init(pdata, plen); unsigned size; char const * const ident = getIdentstr(&size, small); diff --git a/src/packer.h b/src/packer.h index dd408c33..699b5033 100644 --- a/src/packer.h +++ b/src/packer.h @@ -210,7 +210,7 @@ protected: virtual upx_byte *getLoader() const; virtual int getLoaderSize() 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); + virtual void initLoader(const void *pdata, int plen, int small=-1); #if 1 && (ACC_CC_GNUC >= 0x040100) virtual void __acc_cdecl_va addLoader(const char *s, ...) __attribute__((__sentinel__)); #else diff --git a/src/stub/Makefile b/src/stub/Makefile index d75c3396..b4454167 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -153,8 +153,8 @@ define tc.default.embed_objinfo $(call tc,m-objcopy) --strip-unneeded $2 $(call tc,m-objcopy) -R .text -R .data -R .bss $2 $(call tc,m-objcopy) -R .comment -R .note -R .reginfo $2 - $(call tc,m-objdump) -trwh $2 > $2.dump - sed -e 's/[ ]*$$//' < $2.dump >> $2 + $(call tc,m-objdump) -trwh $2 | sed -e 's/[ ]*$$//' > $2.dump + cat $2.dump >> $2 endef # some common settings for $(tc_list)