diff --git a/src/linker.cpp b/src/linker.cpp index 618fa04c..34463a92 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -84,7 +84,7 @@ ElfLinker::Section::~Section() // Symbol **************************************************************************/ -ElfLinker::Symbol::Symbol(const char *n, Section *s, unsigned o) : +ElfLinker::Symbol::Symbol(const char *n, Section *s, u64 o) : name(NULL), section(s), offset(o) { name = strdup(n); @@ -103,7 +103,7 @@ ElfLinker::Symbol::~Symbol() **************************************************************************/ ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, - const Symbol *v, unsigned a) : + const Symbol *v, u64 a) : section(s), offset(o), type(t), value(v), add(a) { assert(section != NULL); @@ -294,29 +294,28 @@ void ElfLinker::preprocessRelocations(char *start, char *end) char *t = strstr(start, type); t[strlen(type)] = 0; - unsigned add = 0; - if (char *p = strstr(symbol, "+0x")) + u64 add = 0; + char *p = strstr(symbol, "+0x"); + if (p == NULL) + p = strstr(symbol, "-0x"); + if (p) { + char sign = *p; *p = 0; // terminate the symbol name p += 3; - if (strlen(p) == 16) { - // skip 8 leading chars if sign of char 9 matches - if (memcmp(p, "000000000", 9)) - p += 8; - else if (memcmp(p, "fffffffff", 9)) - p += 8; - } - assert(strlen(p) == 8); + assert(strlen(p) == 8 || strlen(p) == 16); char *endptr = NULL; - unsigned long ul = strtoul(p, &endptr, 16); - add = (unsigned) ul; - assert(add == ul); + unsigned long long ull = strtoull(p, &endptr, 16); + add = (u64) ull; + assert(add == ull); assert(endptr && *endptr == '\0'); + if (sign == '-') + add = -add; } addRelocation(section->name, offset, t, symbol, add); - //printf("relocation %s %s %x %d preprocessed\n", section->name, symbol, offset, add); + //printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset, (unsigned long long) add); } start = nextl + 1; @@ -372,7 +371,7 @@ ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section, ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, const char *type, const char *symbol, - unsigned add) + u64 add) { if (update_capacity(nrelocations, &nrelocations_capacity)) relocations = static_cast(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *))); @@ -498,7 +497,7 @@ void ElfLinker::relocate() for (unsigned ic = 0; ic < nrelocations; ic++) { const Relocation *rel = relocations[ic]; - unsigned value = 0; + u64 value = 0; if (rel->section->output == NULL) continue; @@ -519,13 +518,13 @@ void ElfLinker::relocate() rel->value->offset + rel->add; } upx_byte *location = rel->section->output + rel->offset; - //printf("%-28s %-28s %-10s 0x%08x 0x%08x\n", rel->section->name, rel->value->name, rel->type, value, value - rel->section->offset - rel->offset); - //printf(" %d %d %d %d %d : %d\n", value, rel->value->section->offset, rel->value->offset, rel->offset, rel->add, *location); + //printf("%-28s %-28s %-10s 0x%16llx 0x%16llx\n", rel->section->name, rel->value->name, rel->type, (long long) value, (long long) value - rel->section->offset - rel->offset); + //printf(" %llx %d %llx %d %llx : %d\n", (long long) value, rel->value->section->offset, rel->value->offset, rel->offset, (long long) rel->add, *location); relocate1(rel, location, value, rel->type); } } -void ElfLinker::defineSymbol(const char *name, unsigned value) +void ElfLinker::defineSymbol(const char *name, u64 value) { Symbol *symbol = findSymbol(name); if (strcmp(symbol->section->name, "*ABS*") == 0) @@ -550,8 +549,8 @@ void ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const { if ((flags & 1) && symbol->section->output == NULL) return; - fprintf(fp, "%-28s 0x%08x | %-28s 0x%08x\n", - symbol->name, symbol->offset, symbol->section->name, symbol->section->offset); + fprintf(fp, "%-28s 0x%16llx | %-28s 0x%08x\n", + symbol->name, (unsigned long long) symbol->offset, symbol->section->name, symbol->section->offset); } void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const { @@ -594,7 +593,7 @@ void ElfLinker::alignWithByte(unsigned len, unsigned char b) } void ElfLinker::relocate1(const Relocation *rel, upx_byte *, - unsigned, const char *) + u64, const char *) { internal_error("unknown relocation type '%s\n", rel->type); } @@ -620,7 +619,7 @@ static void check8(const Relocation *rel, const upx_byte *location, int v, int d void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strncmp(type, "R_X86_64_", 9)) return super::relocate1(rel, location, value, type); @@ -646,15 +645,17 @@ void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, } else if (strcmp(type, "16") == 0) set_le16(location, get_le16(location) + value); - else if (strcmp(type, "32") == 0) + else if (strncmp(type, "32", 2) == 0) // for "32" and "32S" set_le32(location, get_le32(location) + value); + else if (strcmp(type, "64") == 0) + set_le64(location, get_le64(location) + value); else super::relocate1(rel, location, value, type); } void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strcmp(type, "R_ARM_PC24") == 0) { @@ -689,7 +690,7 @@ void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strcmp(type, "R_ARM_PC24") == 0) { @@ -733,7 +734,7 @@ void ElfLinkerM68k::alignCode(unsigned len) } void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strncmp(type, "R_68K_", 6)) return super::relocate1(rel, location, value, type); @@ -759,7 +760,7 @@ void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { #define MIPS_HI(a) (((a) >> 16) + (((a) & 0x8000) >> 15)) #define MIPS_LO(a) ((a) & 0xffff) @@ -790,7 +791,7 @@ void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { #define MIPS_HI(a) (((a) >> 16) + (((a) & 0x8000) >> 15)) #define MIPS_LO(a) ((a) & 0xffff) @@ -821,7 +822,7 @@ void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strncmp(type, "R_PPC_", 6)) return super::relocate1(rel, location, value, type); @@ -862,7 +863,7 @@ void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location, - unsigned value, const char *type) + u64 value, const char *type) { if (strncmp(type, "R_386_", 6)) return super::relocate1(rel, location, value, type); diff --git a/src/linker.h b/src/linker.h index 32269db9..673b9f3c 100644 --- a/src/linker.h +++ b/src/linker.h @@ -40,6 +40,7 @@ class ElfLinker : private noncopyable public: const N_BELE_RTP::AbstractPolicy *bele; // target endianness protected: + typedef acc_uint64l_t u64; struct Section; struct Symbol; struct Relocation; @@ -74,7 +75,7 @@ protected: 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); + const char *symbol, u64 add); public: ElfLinker(); @@ -93,7 +94,7 @@ public: virtual int getSection(const char *sname, int *slen=NULL) const; virtual int getSectionSize(const char *sname) const; virtual upx_byte *getLoader(int *llen=NULL) const; - virtual void defineSymbol(const char *name, unsigned value); + virtual void defineSymbol(const char *name, u64 value); virtual unsigned getSymbolOffset(const char *) const; virtual void dumpSymbol(const Symbol *, unsigned flags, FILE *fp) const; @@ -106,15 +107,15 @@ public: protected: virtual void relocate(); virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); // target endianness abstraction unsigned get_te16(const void *p) const { return bele->get16(p); } unsigned get_te32(const void *p) const { return bele->get32(p); } - acc_uint64l_t get_te64(const void *p) const { return bele->get64(p); } + u64 get_te64(const void *p) const { return bele->get64(p); } void set_te16(void *p, unsigned v) const { bele->set16(p, v); } void set_te32(void *p, unsigned v) const { bele->set32(p, v); } - void set_te64(void *p, acc_uint64l_t v) const { bele->set64(p, v); } + void set_te64(void *p, u64 v) const { bele->set64(p, v); } }; @@ -137,9 +138,9 @@ struct ElfLinker::Symbol : private noncopyable { char *name; Section *section; - unsigned offset; + u64 offset; - Symbol(const char *n, Section *s, unsigned o); + Symbol(const char *n, Section *s, u64 o); ~Symbol(); }; @@ -150,10 +151,10 @@ struct ElfLinker::Relocation : private noncopyable unsigned offset; const char *type; const Symbol *value; - unsigned add; // used in .rela relocations + u64 add; // used in .rela relocations Relocation(const Section *s, unsigned o, const char *t, - const Symbol *v, unsigned a); + const Symbol *v, u64 a); }; @@ -167,7 +168,7 @@ class ElfLinkerAMD64 : public ElfLinker protected: virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); } virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -178,7 +179,7 @@ public: ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; } protected: virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -187,7 +188,7 @@ class ElfLinkerArmLE : public ElfLinker typedef ElfLinker super; protected: virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -199,7 +200,7 @@ public: protected: virtual void alignCode(unsigned len); virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -210,7 +211,7 @@ public: ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; } protected: virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -219,7 +220,7 @@ class ElfLinkerMipsLE : public ElfLinker typedef ElfLinker super; protected: virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -230,7 +231,7 @@ public: ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; } protected: virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); }; @@ -240,7 +241,7 @@ class ElfLinkerX86 : public ElfLinker protected: virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); } virtual void relocate1(const Relocation *, upx_byte *location, - unsigned value, const char *type); + u64 value, const char *type); };