upx-clang-format -i linker.cpp linker.h

This commit is contained in:
Markus F.X.J. Oberhumer
2016-11-20 14:20:36 +01:00
parent 8d61e037f9
commit 4953e77161
3 changed files with 291 additions and 445 deletions
+1 -1
View File
@@ -162,7 +162,7 @@ endif
# automatically format some C++ source code files # automatically format some C++ source code files
ifeq ($(shell uname),Linux) ifeq ($(shell uname),Linux)
CLANG_FORMAT_FILES += packhead.cpp CLANG_FORMAT_FILES += linker.cpp linker.h packhead.cpp
CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h CLANG_FORMAT_FILES += s_djgpp2.cpp s_object.cpp s_vcsa.cpp s_win32.cpp screen.h
CLANG_FORMAT_FILES += snprintf.cpp CLANG_FORMAT_FILES += snprintf.cpp
CLANG_FORMAT_FILES += stdcxx.cpp stdcxx.h CLANG_FORMAT_FILES += stdcxx.cpp stdcxx.h
+159 -298
View File
@@ -25,17 +25,12 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "linker.h" #include "linker.h"
static unsigned hex(unsigned char c) static unsigned hex(unsigned char c) { return (c & 0xf) + (c > '9' ? 9 : 0); }
{
return (c & 0xf) + (c > '9' ? 9 : 0);
}
static bool update_capacity(unsigned size, unsigned *capacity) static bool update_capacity(unsigned size, unsigned *capacity) {
{
if (size < *capacity) if (size < *capacity)
return false; return false;
if (*capacity == 0) if (*capacity == 0)
@@ -45,8 +40,7 @@ static bool update_capacity(unsigned size, unsigned *capacity)
return true; return true;
} }
static void __acc_cdecl_va internal_error(const char *format, ...) static void __acc_cdecl_va internal_error(const char *format, ...) {
{
static char buf[1024]; static char buf[1024];
va_list ap; va_list ap;
@@ -57,14 +51,12 @@ static void __acc_cdecl_va internal_error(const char *format, ...)
throwInternalError(buf); throwInternalError(buf);
} }
/************************************************************************* /*************************************************************************
// Section // Section
**************************************************************************/ **************************************************************************/
ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a) : ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a)
name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL) : name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL) {
{
name = strdup(n); name = strdup(n);
assert(name != NULL); assert(name != NULL);
input = malloc(s + 1); input = malloc(s + 1);
@@ -74,60 +66,45 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
((char *) input)[s] = 0; ((char *) input)[s] = 0;
} }
ElfLinker::Section::~Section() ElfLinker::Section::~Section() {
{
free(name); free(name);
free(input); free(input);
} }
/************************************************************************* /*************************************************************************
// Symbol // Symbol
**************************************************************************/ **************************************************************************/
ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o) : ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
name(NULL), section(s), offset(o) : name(NULL), section(s), offset(o) {
{
name = strdup(n); name = strdup(n);
assert(name != NULL); assert(name != NULL);
assert(section != NULL); assert(section != NULL);
} }
ElfLinker::Symbol::~Symbol() ElfLinker::Symbol::~Symbol() { free(name); }
{
free(name);
}
/************************************************************************* /*************************************************************************
// Relocation // Relocation
**************************************************************************/ **************************************************************************/
ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t, const Symbol *v,
const Symbol *v, upx_uint64_t a) : upx_uint64_t a)
section(s), offset(o), type(t), value(v), add(a) : section(s), offset(o), type(t), value(v), add(a) {
{
assert(section != NULL); assert(section != NULL);
} }
/************************************************************************* /*************************************************************************
// ElfLinker // ElfLinker
**************************************************************************/ **************************************************************************/
ElfLinker::ElfLinker() : ElfLinker::ElfLinker()
bele(&N_BELE_RTP::le_policy), : bele(&N_BELE_RTP::le_policy), input(NULL), output(NULL), head(NULL), tail(NULL),
input(NULL), output(NULL), head(NULL), tail(NULL), sections(NULL), symbols(NULL), relocations(NULL), nsections(0), nsections_capacity(0),
sections(NULL), symbols(NULL), relocations(NULL), nsymbols(0), nsymbols_capacity(0), nrelocations(0), nrelocations_capacity(0),
nsections(0), nsections_capacity(0), reloc_done(false) {}
nsymbols(0), nsymbols_capacity(0),
nrelocations(0), nrelocations_capacity(0),
reloc_done(false)
{
}
ElfLinker::~ElfLinker() ElfLinker::~ElfLinker() {
{
delete[] input; delete[] input;
delete[] output; delete[] output;
@@ -143,24 +120,19 @@ ElfLinker::~ElfLinker()
free(relocations); free(relocations);
} }
void ElfLinker::init(const void *pdata_v, int plen) void ElfLinker::init(const void *pdata_v, int plen) {
{
const upx_byte *pdata = (const upx_byte *) pdata_v; const upx_byte *pdata = (const upx_byte *) pdata_v;
if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0) if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0) {
{
// decompress pre-compressed stub-loader // decompress pre-compressed stub-loader
int method; int method;
unsigned u_len, c_len; unsigned u_len, c_len;
if (pdata[4]) if (pdata[4]) {
{
method = pdata[4]; method = pdata[4];
u_len = get_le16(pdata + 5); u_len = get_le16(pdata + 5);
c_len = get_le16(pdata + 7); c_len = get_le16(pdata + 7);
pdata += 9; pdata += 9;
assert(9 + c_len == (unsigned) plen); assert(9 + c_len == (unsigned) plen);
} } else {
else
{
method = pdata[5]; method = pdata[5];
u_len = get_le32(pdata + 6); u_len = get_le32(pdata + 6);
c_len = get_le32(pdata + 10); c_len = get_le32(pdata + 10);
@@ -176,9 +148,7 @@ void ElfLinker::init(const void *pdata_v, int plen)
throwOutOfMemoryException(); throwOutOfMemoryException();
if (r != UPX_E_OK || new_len != u_len) if (r != UPX_E_OK || new_len != u_len)
throwBadLoader(); throwBadLoader();
} } else {
else
{
inputlen = plen; inputlen = plen;
input = new upx_byte[inputlen + 1]; input = new upx_byte[inputlen + 1];
if (inputlen) if (inputlen)
@@ -189,7 +159,9 @@ void ElfLinker::init(const void *pdata_v, int plen)
output = new upx_byte[inputlen ? inputlen : 0x4000]; output = new upx_byte[inputlen ? inputlen : 0x4000];
outputlen = 0; outputlen = 0;
if ((int)strlen("Sections:\n" "SYMBOL TABLE:\n" "RELOCATION RECORDS FOR ") < inputlen) { if ((int) strlen("Sections:\n"
"SYMBOL TABLE:\n"
"RELOCATION RECORDS FOR ") < inputlen) {
int pos = find(input, inputlen, "Sections:\n", 10); int pos = find(input, inputlen, "Sections:\n", 10);
assert(pos != -1); assert(pos != -1);
char *psections = (char *) input + pos; char *psections = (char *) input + pos;
@@ -207,11 +179,9 @@ void ElfLinker::init(const void *pdata_v, int plen)
} }
} }
void ElfLinker::preprocessSections(char *start, char *end) void ElfLinker::preprocessSections(char *start, char *end) {
{
char *nextl; char *nextl;
for (nsections = 0; start < end; start = 1+ nextl) for (nsections = 0; start < end; start = 1 + nextl) {
{
nextl = strchr(start, '\n'); nextl = strchr(start, '\n');
assert(nextl != NULL); assert(nextl != NULL);
*nextl = '\0'; // a record is a line *nextl = '\0'; // a record is a line
@@ -219,9 +189,7 @@ void ElfLinker::preprocessSections(char *start, char *end)
unsigned offset, size, align; unsigned offset, size, align;
char name[1024]; char name[1024];
if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d", if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d", name, &size, &offset, &align) == 4) {
name, &size, &offset, &align) == 4)
{
char *n = strstr(start, name); char *n = strstr(start, name);
n[strlen(name)] = 0; n[strlen(name)] = 0;
addSection(n, input + offset, size, align); addSection(n, input + offset, size, align);
@@ -233,11 +201,9 @@ void ElfLinker::preprocessSections(char *start, char *end)
addSection("*UND*", NULL, 0, 0); addSection("*UND*", NULL, 0, 0);
} }
void ElfLinker::preprocessSymbols(char *start, char *end) void ElfLinker::preprocessSymbols(char *start, char *end) {
{
char *nextl; char *nextl;
for (nsymbols = 0; start < end; start = 1+ nextl) for (nsymbols = 0; start < end; start = 1 + nextl) {
{
nextl = strchr(start, '\n'); nextl = strchr(start, '\n');
assert(nextl != NULL); assert(nextl != NULL);
*nextl = '\0'; // a record is a line *nextl = '\0'; // a record is a line
@@ -246,9 +212,7 @@ void ElfLinker::preprocessSymbols(char *start, char *end)
char section[1024]; char section[1024];
char symbol[1024]; char symbol[1024];
if (sscanf(start, "%x g *ABS* %x %1023s", if (sscanf(start, "%x g *ABS* %x %1023s", &value, &offset, symbol) == 3) {
&value, &offset, symbol) == 3)
{
char *s = strstr(start, symbol); char *s = strstr(start, symbol);
s[strlen(symbol)] = 0; s[strlen(symbol)] = 0;
addSymbol(s, "*ABS*", value); addSymbol(s, "*ABS*", value);
@@ -273,12 +237,10 @@ void ElfLinker::preprocessSymbols(char *start, char *end)
} }
} }
void ElfLinker::preprocessRelocations(char *start, char *end) void ElfLinker::preprocessRelocations(char *start, char *end) {
{
Section *section = NULL; Section *section = NULL;
char *nextl; char *nextl;
for (nrelocations = 0; start < end; start = 1+ nextl) for (nrelocations = 0; start < end; start = 1 + nextl) {
{
nextl = strchr(start, '\n'); nextl = strchr(start, '\n');
assert(nextl != NULL); assert(nextl != NULL);
*nextl = '\0'; // a record is a line *nextl = '\0'; // a record is a line
@@ -293,9 +255,7 @@ void ElfLinker::preprocessRelocations(char *start, char *end)
char type[100]; char type[100];
char symbol[1024]; char symbol[1024];
if (sscanf(start, "%x %99s %1023s", if (sscanf(start, "%x %99s %1023s", &offset, type, symbol) == 3) {
&offset, type, symbol) == 3)
{
char *t = strstr(start, type); char *t = strstr(start, type);
t[strlen(type)] = 0; t[strlen(type)] = 0;
@@ -303,8 +263,7 @@ void ElfLinker::preprocessRelocations(char *start, char *end)
char *p = strstr(symbol, "+0x"); char *p = strstr(symbol, "+0x");
if (p == NULL) if (p == NULL)
p = strstr(symbol, "-0x"); p = strstr(symbol, "-0x");
if (p) if (p) {
{
char sign = *p; char sign = *p;
*p = 0; // terminate the symbol name *p = 0; // terminate the symbol name
p += 3; p += 3;
@@ -326,14 +285,14 @@ void ElfLinker::preprocessRelocations(char *start, char *end)
if (section) { if (section) {
addRelocation(section->name, offset, t, symbol, add); addRelocation(section->name, offset, t, symbol, add);
//printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset, (unsigned long long) add); // printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset,
// (unsigned long long) add);
} }
} }
} }
} }
ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const {
{
for (unsigned ic = 0; ic < nsections; ic++) for (unsigned ic = 0; ic < nsections; ic++)
if (strcmp(sections[ic]->name, name) == 0) if (strcmp(sections[ic]->name, name) == 0)
return sections[ic]; return sections[ic];
@@ -342,8 +301,7 @@ ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const
return NULL; return NULL;
} }
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const {
{
for (unsigned ic = 0; ic < nsymbols; ic++) for (unsigned ic = 0; ic < nsymbols; ic++)
if (strcmp(symbols[ic]->name, name) == 0) if (strcmp(symbols[ic]->name, name) == 0)
return symbols[ic]; return symbols[ic];
@@ -352,13 +310,16 @@ ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const
return NULL; return NULL;
} }
ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen, unsigned p2align) ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen,
{ unsigned p2align) {
// printf("addSection: %s len=%d align=%d\n", sname, slen, p2align); // printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);
if (update_capacity(nsections, &nsections_capacity)) if (update_capacity(nsections, &nsections_capacity))
sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *))); sections =
static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
assert(sections); assert(sections);
assert(sname); assert(sname[0]); assert(sname[strlen(sname)-1] != ':'); assert(sname);
assert(sname[0]);
assert(sname[strlen(sname) - 1] != ':');
assert(findSection(sname, false) == NULL); assert(findSection(sname, false) == NULL);
Section *sec = new Section(sname, sdata, slen, p2align); Section *sec = new Section(sname, sdata, slen, p2align);
sections[nsections++] = sec; sections[nsections++] = sec;
@@ -366,28 +327,27 @@ ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata,
} }
ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section, ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
upx_uint64_t offset) upx_uint64_t offset) {
{
// printf("addSymbol: %s %s 0x%x\n", name, section, offset); // printf("addSymbol: %s %s 0x%x\n", name, section, offset);
if (update_capacity(nsymbols, &nsymbols_capacity)) if (update_capacity(nsymbols, &nsymbols_capacity))
symbols = static_cast<Symbol **>(realloc(symbols, nsymbols_capacity * sizeof(Symbol *))); symbols = static_cast<Symbol **>(realloc(symbols, nsymbols_capacity * sizeof(Symbol *)));
assert(symbols != NULL); assert(symbols != NULL);
assert(name); assert(name[0]); assert(name[strlen(name)-1] != ':'); assert(name);
assert(name[0]);
assert(name[strlen(name) - 1] != ':');
assert(findSymbol(name, false) == NULL); assert(findSymbol(name, false) == NULL);
Symbol *sym = new Symbol(name, findSection(section), offset); Symbol *sym = new Symbol(name, findSection(section), offset);
symbols[nsymbols++] = sym; symbols[nsymbols++] = sym;
return sym; return sym;
} }
ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, const char *type,
const char *type, const char *symbol, const char *symbol, upx_uint64_t add) {
upx_uint64_t add)
{
if (update_capacity(nrelocations, &nrelocations_capacity)) if (update_capacity(nrelocations, &nrelocations_capacity))
relocations = static_cast<Relocation **>(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *))); relocations = static_cast<Relocation **>(
realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));
assert(relocations != NULL); assert(relocations != NULL);
Relocation *rel = new Relocation(findSection(section), off, Relocation *rel = new Relocation(findSection(section), off, type, findSymbol(symbol), add);
type, findSymbol(symbol), add);
relocations[nrelocations++] = rel; relocations[nrelocations++] = rel;
return rel; return rel;
} }
@@ -400,19 +360,16 @@ void ElfLinker::setLoaderAlignOffset(int phase)
} }
#endif #endif
int ElfLinker::addLoader(const char *sname) int ElfLinker::addLoader(const char *sname) {
{
assert(sname != NULL); assert(sname != NULL);
if (!sname[0]) if (!sname[0])
return outputlen; return outputlen;
char *begin = strdup(sname); char *begin = strdup(sname);
char *end = begin + strlen(begin); char *end = begin + strlen(begin);
for (char *sect = begin; sect < end; ) for (char *sect = begin; sect < end;) {
{
for (char *tokend = sect; *tokend; tokend++) for (char *tokend = sect; *tokend; tokend++)
if (*tokend == ' ' || *tokend == ',') if (*tokend == ' ' || *tokend == ',') {
{
*tokend = 0; *tokend = 0;
break; break;
} }
@@ -425,17 +382,14 @@ int ElfLinker::addLoader(const char *sname)
if (m) { if (m) {
l %= hex(sect[1]); l %= hex(sect[1]);
} }
if (l) if (l) {
{
if (sect[3] == 'D') if (sect[3] == 'D')
alignData(l); alignData(l);
else else
alignCode(l); alignCode(l);
tail->size += l; tail->size += l;
} }
} } else {
else
{
Section *section = findSection(sect); Section *section = findSection(sect);
if (section->p2align) { if (section->p2align) {
assert(tail); assert(tail);
@@ -452,12 +406,10 @@ int ElfLinker::addLoader(const char *sname)
// printf("section added: 0x%04x %3d %s\n", outputlen, section->size, section->name); // printf("section added: 0x%04x %3d %s\n", outputlen, section->size, section->name);
outputlen += section->size; outputlen += section->size;
if (head) if (head) {
{
tail->next = section; tail->next = section;
section->offset = tail->offset + tail->size; section->offset = tail->offset + tail->size;
} } else
else
head = section; head = section;
tail = section; tail = section;
} }
@@ -467,80 +419,68 @@ int ElfLinker::addLoader(const char *sname)
return outputlen; return outputlen;
} }
void ElfLinker::addLoader(const char *s, va_list ap) void ElfLinker::addLoader(const char *s, va_list ap) {
{ while (s != NULL) {
while (s != NULL)
{
addLoader(s); addLoader(s);
s = va_arg(ap, const char *); s = va_arg(ap, const char *);
} }
} }
void __acc_cdecl_va ElfLinker::addLoaderVA(const char *s, ...) void __acc_cdecl_va ElfLinker::addLoaderVA(const char *s, ...) {
{
va_list ap; va_list ap;
va_start(ap, s); va_start(ap, s);
addLoader(s, ap); addLoader(s, ap);
va_end(ap); va_end(ap);
} }
int ElfLinker::getSection(const char *sname, int *slen) const int ElfLinker::getSection(const char *sname, int *slen) const {
{
const Section *section = findSection(sname); const Section *section = findSection(sname);
if (slen) if (slen)
*slen = section->size; *slen = section->size;
return (int) (section->output - output); return (int) (section->output - output);
} }
int ElfLinker::getSectionSize(const char *sname) const int ElfLinker::getSectionSize(const char *sname) const {
{
const Section *section = findSection(sname); const Section *section = findSection(sname);
return section->size; return section->size;
} }
upx_byte *ElfLinker::getLoader(int *llen) const upx_byte *ElfLinker::getLoader(int *llen) const {
{
if (llen) if (llen)
*llen = outputlen; *llen = outputlen;
return output; return output;
} }
void ElfLinker::relocate() void ElfLinker::relocate() {
{
assert(!reloc_done); assert(!reloc_done);
reloc_done = true; reloc_done = true;
for (unsigned ic = 0; ic < nrelocations; ic++) for (unsigned ic = 0; ic < nrelocations; ic++) {
{
const Relocation *rel = relocations[ic]; const Relocation *rel = relocations[ic];
upx_uint64_t value = 0; upx_uint64_t value = 0;
if (rel->section->output == NULL) if (rel->section->output == NULL)
continue; continue;
if (strcmp(rel->value->section->name, "*ABS*") == 0) if (strcmp(rel->value->section->name, "*ABS*") == 0) {
{
value = rel->value->offset; value = rel->value->offset;
} } else if (strcmp(rel->value->section->name, "*UND*") == 0 &&
else if (strcmp(rel->value->section->name, "*UND*") == 0 &&
rel->value->offset == 0xdeaddead) rel->value->offset == 0xdeaddead)
internal_error("undefined symbol '%s' referenced\n", rel->value->name); internal_error("undefined symbol '%s' referenced\n", rel->value->name);
else if (rel->value->section->output == NULL) else if (rel->value->section->output == NULL)
internal_error("can not apply reloc '%s:%x' without section '%s'\n", internal_error("can not apply reloc '%s:%x' without section '%s'\n", rel->section->name,
rel->section->name, rel->offset, rel->offset, rel->value->section->name);
rel->value->section->name); else {
else value = rel->value->section->offset + rel->value->offset + rel->add;
{
value = rel->value->section->offset +
rel->value->offset + rel->add;
} }
upx_byte *location = rel->section->output + rel->offset; upx_byte *location = rel->section->output + rel->offset;
//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("%-28s %-28s %-10s 0x%16llx 0x%16llx\n", rel->section->name, rel->value->name,
//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); // 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); relocate1(rel, location, value, rel->type);
} }
} }
void ElfLinker::defineSymbol(const char *name, upx_uint64_t value) void ElfLinker::defineSymbol(const char *name, upx_uint64_t value) {
{
Symbol *symbol = findSymbol(name); Symbol *symbol = findSymbol(name);
if (strcmp(symbol->section->name, "*ABS*") == 0) if (strcmp(symbol->section->name, "*ABS*") == 0)
internal_error("defineSymbol: symbol '%s' is *ABS*\n", name); internal_error("defineSymbol: symbol '%s' is *ABS*\n", name);
@@ -548,77 +488,62 @@ void ElfLinker::defineSymbol(const char *name, upx_uint64_t value)
symbol->offset = value; symbol->offset = value;
else if (strcmp(symbol->section->name, name) == 0) // for sections else if (strcmp(symbol->section->name, name) == 0) // for sections
{ {
for (Section *section = symbol->section; section; section = section->next) for (Section *section = symbol->section; section; section = section->next) {
{
assert(section->offset < value); assert(section->offset < value);
section->offset = value; section->offset = value;
value += section->size; value += section->size;
} }
} } else
else
internal_error("defineSymbol: symbol '%s' already defined\n", name); internal_error("defineSymbol: symbol '%s' already defined\n", name);
} }
// debugging support // debugging support
void ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const void ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const {
{
if ((flags & 1) && symbol->section->output == NULL) if ((flags & 1) && symbol->section->output == NULL)
return; return;
char d0[16 + 1], d1[16 + 1]; char d0[16 + 1], d1[16 + 1];
upx_snprintf(d0, sizeof(d0), "%016llx", (upx_uint64_t) symbol->offset); upx_snprintf(d0, sizeof(d0), "%016llx", (upx_uint64_t) symbol->offset);
upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) symbol->section->offset); upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) symbol->section->offset);
fprintf(fp, "%-28s 0x%-16s | %-28s 0x%-16s\n", fprintf(fp, "%-28s 0x%-16s | %-28s 0x%-16s\n", symbol->name, d0, symbol->section->name, d1);
symbol->name, d0, symbol->section->name, d1);
} }
void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const {
{
if (fp == NULL) if (fp == NULL)
fp = stdout; fp = stdout;
if ((flags & 2) == 0) if ((flags & 2) == 0) {
{
// default: dump symbols in used section order // default: dump symbols in used section order
for (const Section *section = head; section; section = section->next) for (const Section *section = head; section; section = section->next) {
{
char d1[16 + 1]; char d1[16 + 1];
upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) section->offset); upx_snprintf(d1, sizeof(d1), "%016llx", (upx_uint64_t) section->offset);
fprintf(fp, "%-42s%-28s 0x%-16s\n", "", section->name, d1); fprintf(fp, "%-42s%-28s 0x%-16s\n", "", section->name, d1);
for (unsigned ic = 0; ic < nsymbols; ic++) for (unsigned ic = 0; ic < nsymbols; ic++) {
{
const Symbol *symbol = symbols[ic]; const Symbol *symbol = symbols[ic];
if (symbol->section == section && strcmp(symbol->name, section->name) != 0) if (symbol->section == section && strcmp(symbol->name, section->name) != 0)
dumpSymbol(symbol, flags, fp); dumpSymbol(symbol, flags, fp);
} }
} }
} } else {
else
{
// dump all symbols // dump all symbols
for (unsigned ic = 0; ic < nsymbols; ic++) for (unsigned ic = 0; ic < nsymbols; ic++)
dumpSymbol(symbols[ic], flags, fp); dumpSymbol(symbols[ic], flags, fp);
} }
} }
upx_uint64_t ElfLinker::getSymbolOffset(const char *name) const upx_uint64_t ElfLinker::getSymbolOffset(const char *name) const {
{
const Symbol *symbol = findSymbol(name); const Symbol *symbol = findSymbol(name);
if (symbol->section->output == NULL) if (symbol->section->output == NULL)
return 0xdeaddead; return 0xdeaddead;
return symbol->section->offset + symbol->offset; return symbol->section->offset + symbol->offset;
} }
void ElfLinker::alignWithByte(unsigned len, unsigned char b) void ElfLinker::alignWithByte(unsigned len, unsigned char b) {
{
memset(output + outputlen, b, len); memset(output + outputlen, b, len);
outputlen += len; outputlen += len;
} }
void ElfLinker::relocate1(const Relocation *rel, upx_byte *, void ElfLinker::relocate1(const Relocation *rel, upx_byte *, upx_uint64_t, const char *) {
upx_uint64_t, const char *)
{
internal_error("unknown relocation type '%s\n", rel->type); internal_error("unknown relocation type '%s\n", rel->type);
} }
/************************************************************************* /*************************************************************************
// ElfLinker arch subclasses // ElfLinker arch subclasses
// FIXME: add more displacment overflow checks // FIXME: add more displacment overflow checks
@@ -637,31 +562,26 @@ static void check8(const Relocation *rel, const upx_byte *location, int v, int d
} }
#endif #endif
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type)
{
if (strncmp(type, "R_X86_64_", 9)) if (strncmp(type, "R_X86_64_", 9))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
type += 9; type += 9;
bool range_check = false; bool range_check = false;
if (strncmp(type, "PC", 2) == 0) if (strncmp(type, "PC", 2) == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
type += 2; type += 2;
range_check = true; range_check = true;
} }
if (strcmp(type, "8") == 0) if (strcmp(type, "8") == 0) {
{
int displ = (signed char) *location + (int) value; int displ = (signed char) *location + (int) value;
if (range_check && (displ < -128 || displ > 127)) if (range_check && (displ < -128 || displ > 127))
internal_error("target out of range (%d) in reloc %s:%x\n", internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
displ, rel->section->name, rel->offset); rel->offset);
*location += value; *location += value;
} } else if (strcmp(type, "16") == 0)
else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value); set_le16(location, get_le16(location) + value);
else if (strncmp(type, "32", 2) == 0) // for "32" and "32S" else if (strncmp(type, "32", 2) == 0) // for "32" and "32S"
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
@@ -671,24 +591,15 @@ void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type) if (strcmp(type, "R_ARM_PC24") == 0) {
{
if (strcmp(type, "R_ARM_PC24") == 0)
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_be24(1 + location, get_be24(1 + location) + value / 4); set_be24(1 + location, get_be24(1 + location) + value / 4);
} } else if (strcmp(type, "R_ARM_ABS32") == 0) {
else if (strcmp(type, "R_ARM_ABS32") == 0)
{
set_be32(location, get_be32(location) + value); set_be32(location, get_be32(location) + value);
} } else if (strcmp(type, "R_ARM_THM_CALL") == 0 || strcmp(type, "R_ARM_THM_XPC22") == 0 ||
else if (strcmp(type, "R_ARM_THM_CALL") == 0 strcmp(type, "R_ARM_THM_PC22") == 0) {
|| strcmp(type, "R_ARM_THM_XPC22") == 0
|| strcmp(type, "R_ARM_THM_PC22") == 0
)
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
value += ((get_be16(location) & 0x7ff) << 12); value += ((get_be16(location) & 0x7ff) << 12);
value += (get_be16(location + 2) & 0x7ff) << 1; value += (get_be16(location + 2) & 0x7ff) << 1;
@@ -698,32 +609,21 @@ void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location,
//(b, 0xF000 + ((v - 1) / 2) * 0x10000); //(b, 0xF000 + ((v - 1) / 2) * 0x10000);
// set_be32(location, get_be32(location) + value / 4); // set_be32(location, get_be32(location) + value / 4);
} } else if (0 == strcmp("R_ARM_ABS8", type)) {
else if (0==strcmp("R_ARM_ABS8", type)) {
*location += value; *location += value;
} } else
else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type) if (strcmp(type, "R_ARM_PC24") == 0) {
{
if (strcmp(type, "R_ARM_PC24") == 0)
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_le24(location, get_le24(location) + value / 4); set_le24(location, get_le24(location) + value / 4);
} } else if (strcmp(type, "R_ARM_ABS32") == 0) {
else if (strcmp(type, "R_ARM_ABS32") == 0)
{
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
} } else if (strcmp(type, "R_ARM_THM_CALL") == 0 || strcmp(type, "R_ARM_THM_XPC22") == 0 ||
else if (strcmp(type, "R_ARM_THM_CALL") == 0 strcmp(type, "R_ARM_THM_PC22") == 0) {
|| strcmp(type, "R_ARM_THM_XPC22") == 0
|| strcmp(type, "R_ARM_THM_PC22") == 0
)
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
value += ((get_le16(location) & 0x7ff) << 12); value += ((get_le16(location) & 0x7ff) << 12);
value += (get_le16(location + 2) & 0x7ff) << 1; value += (get_le16(location + 2) & 0x7ff) << 1;
@@ -733,33 +633,24 @@ void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location,
//(b, 0xF000 + ((v - 1) / 2) * 0x10000); //(b, 0xF000 + ((v - 1) / 2) * 0x10000);
// set_le32(location, get_le32(location) + value / 4); // set_le32(location, get_le32(location) + value / 4);
} } else if (0 == strcmp("R_ARM_ABS8", type)) {
else if (0==strcmp("R_ARM_ABS8", type)) {
*location += value; *location += value;
} } else
else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerArm64LE::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerArm64LE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type) const char *type) {
{ if (strcmp(type, "R_AARCH64_CALL26") == 0) {
if (strcmp(type, "R_AARCH64_CALL26") == 0)
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_le24(location, get_le24(location) + value / 4); // FIXME set_le26 set_le24(location, get_le24(location) + value / 4); // FIXME set_le26
} } else if (strcmp(type, "R_AARCH64_ABS32") == 0) {
else if (strcmp(type, "R_AARCH64_ABS32") == 0)
{
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
} } else
else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerM68k::alignCode(unsigned len) {
void ElfLinkerM68k::alignCode(unsigned len)
{
assert((len & 1) == 0); assert((len & 1) == 0);
assert((outputlen & 1) == 0); assert((outputlen & 1) == 0);
for (unsigned i = 0; i < len; i += 2) for (unsigned i = 0; i < len; i += 2)
@@ -767,35 +658,28 @@ void ElfLinkerM68k::alignCode(unsigned len)
outputlen += len; outputlen += len;
} }
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type) const char *type) {
{
if (strncmp(type, "R_68K_", 6)) if (strncmp(type, "R_68K_", 6))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
type += 6; type += 6;
if (strncmp(type, "PC", 2) == 0) if (strncmp(type, "PC", 2) == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
type += 2; type += 2;
} }
if (strcmp(type, "8") == 0) { if (strcmp(type, "8") == 0) {
*location += value; *location += value;
} } else if (strcmp(type, "16") == 0) {
else if (strcmp(type, "16") == 0) {
set_be16(location, get_be16(location) + value); set_be16(location, get_be16(location) + value);
} } else if (strcmp(type, "32") == 0) {
else if (strcmp(type, "32") == 0) {
set_be32(location, get_be32(location) + value); set_be32(location, get_be32(location) + value);
} } else
else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type)
{
#define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15)) #define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15))
#define MIPS_LO(a) ((a) &0xffff) #define MIPS_LO(a) ((a) &0xffff)
#define MIPS_PC16(a) ((a) >> 2) #define MIPS_PC16(a) ((a) >> 2)
@@ -805,12 +689,10 @@ void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location,
set_be16(2 + location, get_be16(2 + location) + MIPS_HI(value)); set_be16(2 + location, get_be16(2 + location) + MIPS_HI(value));
else if (strcmp(type, "R_MIPS_LO16") == 0) else if (strcmp(type, "R_MIPS_LO16") == 0)
set_be16(2 + location, get_be16(2 + location) + MIPS_LO(value)); set_be16(2 + location, get_be16(2 + location) + MIPS_LO(value));
else if (strcmp(type, "R_MIPS_PC16") == 0) else if (strcmp(type, "R_MIPS_PC16") == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_be16(2 + location, get_be16(2 + location) + MIPS_PC16(value)); set_be16(2 + location, get_be16(2 + location) + MIPS_PC16(value));
} } else if (strcmp(type, "R_MIPS_26") == 0)
else if (strcmp(type, "R_MIPS_26") == 0)
set_be32(location, get_be32(location) + MIPS_PC26(value)); set_be32(location, get_be32(location) + MIPS_PC26(value));
else if (strcmp(type, "R_MIPS_32") == 0) else if (strcmp(type, "R_MIPS_32") == 0)
set_be32(location, get_be32(location) + value); set_be32(location, get_be32(location) + value);
@@ -823,10 +705,8 @@ void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location,
#undef MIPS_PC26 #undef MIPS_PC26
} }
void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type)
{
#define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15)) #define MIPS_HI(a) (((a) >> 16) + (((a) &0x8000) >> 15))
#define MIPS_LO(a) ((a) &0xffff) #define MIPS_LO(a) ((a) &0xffff)
#define MIPS_PC16(a) ((a) >> 2) #define MIPS_PC16(a) ((a) >> 2)
@@ -836,12 +716,10 @@ void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location,
set_le16(location, get_le16(location) + MIPS_HI(value)); set_le16(location, get_le16(location) + MIPS_HI(value));
else if (strcmp(type, "R_MIPS_LO16") == 0) else if (strcmp(type, "R_MIPS_LO16") == 0)
set_le16(location, get_le16(location) + MIPS_LO(value)); set_le16(location, get_le16(location) + MIPS_LO(value));
else if (strcmp(type, "R_MIPS_PC16") == 0) else if (strcmp(type, "R_MIPS_PC16") == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_le16(location, get_le16(location) + MIPS_PC16(value)); set_le16(location, get_le16(location) + MIPS_PC16(value));
} } else if (strcmp(type, "R_MIPS_26") == 0)
else if (strcmp(type, "R_MIPS_26") == 0)
set_le32(location, get_le32(location) + MIPS_PC26(value)); set_le32(location, get_le32(location) + MIPS_PC26(value));
else if (strcmp(type, "R_MIPS_32") == 0) else if (strcmp(type, "R_MIPS_32") == 0)
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
@@ -854,22 +732,18 @@ void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location,
#undef MIPS_PC26 #undef MIPS_PC26
} }
void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type)
{
if (strncmp(type, "R_PPC_", 6)) if (strncmp(type, "R_PPC_", 6))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
type += 6; type += 6;
if (strcmp(type, "ADDR32") == 0) if (strcmp(type, "ADDR32") == 0) {
{
set_be32(location, get_be32(location) + value); set_be32(location, get_be32(location) + value);
return; return;
} }
if (strncmp(type, "REL", 3) == 0) if (strncmp(type, "REL", 3) == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
type += 3; type += 3;
} }
@@ -881,30 +755,24 @@ void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location,
if (3 & value) if (3 & value)
internal_error("unaligned word diplacement"); internal_error("unaligned word diplacement");
// FIXME: displacment overflow? // FIXME: displacment overflow?
set_be32(location, (0xfc000003 & get_be32(location)) + set_be32(location, (0xfc000003 & get_be32(location)) + (0x03fffffc & value));
(0x03fffffc & value)); } else if (strcmp(type, "14") == 0) {
}
else if (strcmp(type, "14") == 0) {
if (3 & value) if (3 & value)
internal_error("unaligned word diplacement"); internal_error("unaligned word diplacement");
// FIXME: displacment overflow? // FIXME: displacment overflow?
set_be32(location, (0xffff0003 & get_be32(location)) + set_be32(location, (0xffff0003 & get_be32(location)) + (0x0000fffc & value));
(0x0000fffc & value)); } else
}
else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location, void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type) const char *type) {
{
if (strncmp(type, "R_PPC64_REL", 11)) if (strncmp(type, "R_PPC64_REL", 11))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
type += 11; type += 11;
bool range_check = false; bool range_check = false;
if (strncmp(type, "PC", 2) == 0) if (strncmp(type, "PC", 2) == 0) {
{
type += 2; type += 2;
range_check = true; range_check = true;
} }
@@ -912,15 +780,13 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location,
/* value will hold relative displacement */ /* value will hold relative displacement */
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
if (strcmp(type, "8") == 0) if (strcmp(type, "8") == 0) {
{
int displ = (signed char) *location + (int) value; int displ = (signed char) *location + (int) value;
if (range_check && (displ < -128 || displ > 127)) if (range_check && (displ < -128 || displ > 127))
internal_error("target out of range (%d) in reloc %s:%x\n", internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
displ, rel->section->name, rel->offset); rel->offset);
*location += value; *location += value;
} } else if (strncmp(type, "14", 2) == 0) // for "32" and "32S"
else if (strncmp(type, "14", 2) == 0) // for "32" and "32S"
set_le16(location, get_le16(location) + value); set_le16(location, get_le16(location) + value);
else if (strcmp(type, "16") == 0) else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value); set_le16(location, get_le16(location) + value);
@@ -934,31 +800,26 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, upx_byte *location,
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value,
void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location, const char *type) {
upx_uint64_t value, const char *type)
{
if (strncmp(type, "R_386_", 6)) if (strncmp(type, "R_386_", 6))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
type += 6; type += 6;
bool range_check = false; bool range_check = false;
if (strncmp(type, "PC", 2) == 0) if (strncmp(type, "PC", 2) == 0) {
{
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
type += 2; type += 2;
range_check = true; range_check = true;
} }
if (strcmp(type, "8") == 0) if (strcmp(type, "8") == 0) {
{
int displ = (signed char) *location + (int) value; int displ = (signed char) *location + (int) value;
if (range_check && (displ < -128 || displ > 127)) if (range_check && (displ < -128 || displ > 127))
internal_error("target out of range (%d,%d,%d) in reloc %s:%x\n", internal_error("target out of range (%d,%d,%d) in reloc %s:%x\n", displ, *location,
displ, *location, value, rel->section->name, rel->offset); value, rel->section->name, rel->offset);
*location += value; *location += value;
} } else if (strcmp(type, "16") == 0)
else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value); set_le16(location, get_le16(location) + value);
else if (strcmp(type, "32") == 0) else if (strcmp(type, "32") == 0)
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
+52 -67
View File
@@ -25,18 +25,16 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#ifndef __UPX_LINKER_H #ifndef __UPX_LINKER_H
#define __UPX_LINKER_H 1 #define __UPX_LINKER_H 1
/************************************************************************* /*************************************************************************
// ElfLinker // ElfLinker
**************************************************************************/ **************************************************************************/
class ElfLinker : private noncopyable class ElfLinker : private noncopyable {
{
friend class Packer; friend class Packer;
public: public:
const N_BELE_RTP::AbstractPolicy *bele; // target endianness const N_BELE_RTP::AbstractPolicy *bele; // target endianness
protected: protected:
@@ -105,8 +103,8 @@ public:
protected: protected:
virtual void relocate(); virtual void relocate();
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
// target endianness abstraction // target endianness abstraction
unsigned get_te16(const void *p) const { return bele->get16(p); } unsigned get_te16(const void *p) const { return bele->get16(p); }
@@ -117,9 +115,7 @@ protected:
void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); } void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
}; };
struct ElfLinker::Section : private noncopyable {
struct ElfLinker::Section : private noncopyable
{
char *name; char *name;
void *input; void *input;
upx_byte *output; upx_byte *output;
@@ -132,9 +128,7 @@ struct ElfLinker::Section : private noncopyable
~Section(); ~Section();
}; };
struct ElfLinker::Symbol : private noncopyable {
struct ElfLinker::Symbol : private noncopyable
{
char *name; char *name;
Section *section; Section *section;
upx_uint64_t offset; upx_uint64_t offset;
@@ -143,124 +137,115 @@ struct ElfLinker::Symbol : private noncopyable
~Symbol(); ~Symbol();
}; };
struct ElfLinker::Relocation : private noncopyable {
struct ElfLinker::Relocation : private noncopyable
{
const Section *section; const Section *section;
unsigned offset; unsigned offset;
const char *type; const char *type;
const Symbol *value; const Symbol *value;
upx_uint64_t add; // used in .rela relocations upx_uint64_t add; // used in .rela relocations
Relocation(const Section *s, unsigned o, const char *t, Relocation(const Section *s, unsigned o, const char *t, const Symbol *v, upx_uint64_t a);
const Symbol *v, upx_uint64_t a);
}; };
/************************************************************************* /*************************************************************************
// ElfLinker arch subclasses // ElfLinker arch subclasses
**************************************************************************/ **************************************************************************/
class ElfLinkerAMD64 : public ElfLinker class ElfLinkerAMD64 : public ElfLinker {
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); } virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerArmBE : public ElfLinker {
class ElfLinkerArmBE : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
public: public:
ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; } ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; }
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerArmLE : public ElfLinker {
class ElfLinkerArmLE : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerArm64LE : public ElfLinker class ElfLinkerArm64LE : public ElfLinker {
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerM68k : public ElfLinker {
class ElfLinkerM68k : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
public: public:
ElfLinkerM68k() { bele = &N_BELE_RTP::be_policy; } ElfLinkerM68k() { bele = &N_BELE_RTP::be_policy; }
protected: protected:
virtual void alignCode(unsigned len); virtual void alignCode(unsigned len);
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerMipsBE : public ElfLinker {
class ElfLinkerMipsBE : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
public: public:
ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; } ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; }
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerMipsLE : public ElfLinker {
class ElfLinkerMipsLE : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerPpc32 : public ElfLinker {
class ElfLinkerPpc32 : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
public: public:
ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; } ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; }
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerPpc64le : public ElfLinker class ElfLinkerPpc64le : public ElfLinker {
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
class ElfLinkerX86 : public ElfLinker {
class ElfLinkerX86 : public ElfLinker
{
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); } virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
upx_uint64_t value, const char *type); const char *type);
}; };
#endif /* already included */ #endif /* already included */
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */