added full support for 64-bit relocations
This commit is contained in:
+34
-33
@@ -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<Relocation **>(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);
|
||||
|
||||
Reference in New Issue
Block a user