Major cleanup of ElfLinker.
This commit is contained in:
parent
6e763b0b42
commit
a74e239e28
330
src/linker.cpp
330
src/linker.cpp
@ -29,7 +29,7 @@
|
|||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "linker.h"
|
#include "linker.h"
|
||||||
|
|
||||||
static int hex(unsigned char c)
|
static unsigned hex(unsigned char c)
|
||||||
{
|
{
|
||||||
return (c & 0xf) + (c > '9' ? 9 : 0);
|
return (c & 0xf) + (c > '9' ? 9 : 0);
|
||||||
}
|
}
|
||||||
@ -45,17 +45,20 @@ static bool update_capacity(unsigned size, unsigned *capacity)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// 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(strdup(n)), output(NULL), size(s), offset(0), align(a), next(NULL)
|
name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL)
|
||||||
{
|
{
|
||||||
assert(name);
|
name = strdup(n);
|
||||||
|
assert(name != NULL);
|
||||||
input = malloc(s + 1);
|
input = malloc(s + 1);
|
||||||
assert(input);
|
assert(input != NULL);
|
||||||
memcpy(input, i, s);
|
memcpy(input, i, s);
|
||||||
|
((char *)input)[s] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Section::~Section()
|
ElfLinker::Section::~Section()
|
||||||
@ -64,10 +67,17 @@ ElfLinker::Section::~Section()
|
|||||||
free(input);
|
free(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// Symbol
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
ElfLinker::Symbol::Symbol(const char *n, Section *s, unsigned o) :
|
ElfLinker::Symbol::Symbol(const char *n, Section *s, unsigned o) :
|
||||||
name(strdup(n)), section(s), offset(o)
|
name(NULL), section(s), offset(o)
|
||||||
{
|
{
|
||||||
assert(name);
|
name = strdup(n);
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(section != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Symbol::~Symbol()
|
ElfLinker::Symbol::~Symbol()
|
||||||
@ -75,12 +85,77 @@ ElfLinker::Symbol::~Symbol()
|
|||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 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, unsigned a) :
|
const Symbol *v, unsigned a) :
|
||||||
section(s), offset(o), type(t), value(v), add(a)
|
section(s), offset(o), type(t), value(v), add(a)
|
||||||
{}
|
{
|
||||||
|
assert(section != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// ElfLinker
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
ElfLinker::ElfLinker() :
|
||||||
|
input(NULL), output(NULL), head(NULL), tail(NULL),
|
||||||
|
sections(NULL), symbols(NULL), relocations(NULL),
|
||||||
|
nsections(0), nsections_capacity(0),
|
||||||
|
nsymbols(0), nsymbols_capacity(0),
|
||||||
|
nrelocations(0), nrelocations_capacity(0),
|
||||||
|
reloc_done(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::~ElfLinker()
|
||||||
|
{
|
||||||
|
delete [] input;
|
||||||
|
delete [] output;
|
||||||
|
|
||||||
|
unsigned ic;
|
||||||
|
for (ic = 0; ic < nsections; ic++)
|
||||||
|
delete sections[ic];
|
||||||
|
free(sections);
|
||||||
|
for (ic = 0; ic < nsymbols; ic++)
|
||||||
|
delete symbols[ic];
|
||||||
|
free(symbols);
|
||||||
|
for (ic = 0; ic < nrelocations; ic++)
|
||||||
|
delete relocations[ic];
|
||||||
|
free(relocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElfLinker::init(const void *pdata, int plen)
|
||||||
|
{
|
||||||
|
upx_byte *i = new upx_byte[plen + 1];
|
||||||
|
memcpy(i, pdata, plen);
|
||||||
|
input = i;
|
||||||
|
inputlen = plen;
|
||||||
|
input[plen] = 0;
|
||||||
|
|
||||||
|
output = new upx_byte[plen];
|
||||||
|
outputlen = 0;
|
||||||
|
|
||||||
|
int pos = find(input, plen, "Sections:", 9);
|
||||||
|
assert(pos != -1);
|
||||||
|
char *psections = (char *) input + pos;
|
||||||
|
|
||||||
|
char *psymbols = strstr(psections, "SYMBOL TABLE:");
|
||||||
|
assert(psymbols != NULL);
|
||||||
|
|
||||||
|
char *prelocs = strstr(psymbols, "RELOCATION RECORDS FOR");
|
||||||
|
assert(prelocs != NULL);
|
||||||
|
|
||||||
|
preprocessSections(psections, psymbols);
|
||||||
|
preprocessSymbols(psymbols, prelocs);
|
||||||
|
preprocessRelocations(prelocs, (char*) input + inputlen);
|
||||||
|
addLoader("*UND*");
|
||||||
|
}
|
||||||
|
|
||||||
void ElfLinker::preprocessSections(char *start, const char *end)
|
void ElfLinker::preprocessSections(char *start, const char *end)
|
||||||
{
|
{
|
||||||
nsections = 0;
|
nsections = 0;
|
||||||
@ -114,22 +189,28 @@ void ElfLinker::preprocessSymbols(char *start, const char *end)
|
|||||||
{
|
{
|
||||||
char section[1024];
|
char section[1024];
|
||||||
char symbol[1024];
|
char symbol[1024];
|
||||||
unsigned offset;
|
unsigned value, offset;
|
||||||
|
|
||||||
char *nextl = strchr(start, '\n');
|
char *nextl = strchr(start, '\n');
|
||||||
assert(nextl != NULL);
|
assert(nextl != NULL);
|
||||||
|
|
||||||
if (sscanf(start, "%x%*8c %1024s %*x %1023s",
|
if (sscanf(start, "%x g *ABS* %x %1023s",
|
||||||
|
&value, &offset, symbol) == 3)
|
||||||
|
{
|
||||||
|
char *s = strstr(start, symbol);
|
||||||
|
s[strlen(symbol)] = 0;
|
||||||
|
addSymbol(s, "*ABS*", value);
|
||||||
|
assert(offset == 0);
|
||||||
|
}
|
||||||
|
else if (sscanf(start, "%x%*8c %1023s %*x %1023s",
|
||||||
&offset, section, symbol) == 3)
|
&offset, section, symbol) == 3)
|
||||||
{
|
{
|
||||||
char *s = strstr(start, symbol);
|
char *s = strstr(start, symbol);
|
||||||
s[strlen(symbol)] = 0;
|
s[strlen(symbol)] = 0;
|
||||||
|
|
||||||
if (strcmp(section, "*UND*") == 0)
|
if (strcmp(section, "*UND*") == 0)
|
||||||
offset = 0xdeaddead;
|
offset = 0xdeaddead;
|
||||||
|
assert(strcmp(section, "*ABS*") != 0);
|
||||||
addSymbol(s, section, offset);
|
addSymbol(s, section, offset);
|
||||||
|
|
||||||
//printf("symbol %s preprocessed o=%x\n", s, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start = nextl + 1;
|
start = nextl + 1;
|
||||||
@ -185,38 +266,54 @@ void ElfLinker::preprocessRelocations(char *start, const char *end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Section *ElfLinker::findSection(const char *name) 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];
|
||||||
|
if (fatal)
|
||||||
printf("unknown section %s\n", name);
|
{
|
||||||
abort();
|
printf("unknown section %s\n", name);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name) /*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];
|
||||||
|
if (fatal)
|
||||||
// FIXME: this should be a const method !
|
{
|
||||||
if ('*' == name[0]) // *ABS*
|
printf("unknown symbol %s\n", name);
|
||||||
return addSymbol(name, name, 0);
|
abort();
|
||||||
|
}
|
||||||
printf("unknown symbol %s\n", name);
|
|
||||||
abort();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
|
ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen, unsigned p2align)
|
||||||
unsigned offset)
|
|
||||||
{
|
{
|
||||||
|
//printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);
|
||||||
|
if (update_capacity(nsections, &nsections_capacity))
|
||||||
|
sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
|
||||||
|
assert(sections);
|
||||||
|
assert(sname); assert(sname[0]); assert(sname[strlen(sname)-1] != ':');
|
||||||
|
assert(findSection(sname, false) == NULL);
|
||||||
|
Section *sec = new Section(sname, sdata, slen, p2align);
|
||||||
|
sections[nsections++] = sec;
|
||||||
|
return sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
|
||||||
|
unsigned 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(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;
|
||||||
@ -235,59 +332,6 @@ ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned of
|
|||||||
return rel;
|
return rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::ElfLinker() :
|
|
||||||
frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL),
|
|
||||||
sections(NULL), symbols(NULL), relocations(NULL),
|
|
||||||
nsections(0), nsections_capacity(0),
|
|
||||||
nsymbols(0), nsymbols_capacity(0),
|
|
||||||
nrelocations(0), nrelocations_capacity(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ElfLinker::~ElfLinker()
|
|
||||||
{
|
|
||||||
delete [] input;
|
|
||||||
delete [] output;
|
|
||||||
|
|
||||||
unsigned ic;
|
|
||||||
for (ic = 0; ic < nsections; ic++)
|
|
||||||
delete sections[ic];
|
|
||||||
free(sections);
|
|
||||||
for (ic = 0; ic < nsymbols; ic++)
|
|
||||||
delete symbols[ic];
|
|
||||||
free(symbols);
|
|
||||||
for (ic = 0; ic < nrelocations; ic++)
|
|
||||||
delete relocations[ic];
|
|
||||||
free(relocations);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ElfLinker::init(const void *pdata, int plen)
|
|
||||||
{
|
|
||||||
upx_byte *i = new upx_byte[plen + 1];
|
|
||||||
memcpy(i, pdata, plen);
|
|
||||||
input = i;
|
|
||||||
inputlen = plen;
|
|
||||||
|
|
||||||
output = new upx_byte[plen];
|
|
||||||
outputlen = 0;
|
|
||||||
|
|
||||||
int pos = find(input, plen, "Sections:", 9);
|
|
||||||
assert(pos != -1);
|
|
||||||
char *psections = pos + (char *) input;
|
|
||||||
|
|
||||||
char *psymbols = strstr(psections, "SYMBOL TABLE:");
|
|
||||||
assert(psymbols != NULL);
|
|
||||||
|
|
||||||
char *prelocs = strstr(psymbols, "RELOCATION RECORDS FOR");
|
|
||||||
assert(prelocs != NULL);
|
|
||||||
input[plen] = 0;
|
|
||||||
|
|
||||||
preprocessSections(psections, psymbols);
|
|
||||||
preprocessSymbols(psymbols, prelocs);
|
|
||||||
preprocessRelocations(prelocs, (char*) input + inputlen);
|
|
||||||
addLoader("*UND*");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ElfLinker::setLoaderAlignOffset(int phase)
|
void ElfLinker::setLoaderAlignOffset(int phase)
|
||||||
{
|
{
|
||||||
//assert(phase & 0);
|
//assert(phase & 0);
|
||||||
@ -296,7 +340,6 @@ void ElfLinker::setLoaderAlignOffset(int phase)
|
|||||||
|
|
||||||
int ElfLinker::addLoader(const char *sname)
|
int ElfLinker::addLoader(const char *sname)
|
||||||
{
|
{
|
||||||
assert(!frozen);
|
|
||||||
if (sname[0] == 0)
|
if (sname[0] == 0)
|
||||||
return outputlen;
|
return outputlen;
|
||||||
|
|
||||||
@ -311,27 +354,28 @@ int ElfLinker::addLoader(const char *sname)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*sect == '+') // alignment
|
if (sect[0] == '+') // alignment
|
||||||
{
|
{
|
||||||
assert(tail);
|
assert(tail);
|
||||||
if (unsigned l = (hex(sect[2]) - tail->offset - tail->size)
|
unsigned l = (hex(sect[2]) - tail->offset - tail->size) % hex(sect[1]);
|
||||||
% hex(sect[1]))
|
if (l)
|
||||||
{
|
{
|
||||||
alignCode(l);
|
if (sect[3] == 'D')
|
||||||
|
alignData(l);
|
||||||
|
else
|
||||||
|
alignCode(l);
|
||||||
tail->size += l;
|
tail->size += l;
|
||||||
outputlen += l;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Section *section = findSection(sect);
|
Section *section = findSection(sect);
|
||||||
if (section->align) {
|
if (section->p2align) {
|
||||||
unsigned const v = ~0u << section->align;
|
|
||||||
assert(tail);
|
assert(tail);
|
||||||
|
unsigned const v = ~0u << section->p2align;
|
||||||
if (unsigned const l = ~v & -(tail->offset + tail->size)) {
|
if (unsigned const l = ~v & -(tail->offset + tail->size)) {
|
||||||
alignCode(l);
|
alignCode(l);
|
||||||
tail->size += l;
|
tail->size += l;
|
||||||
outputlen += l;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(output + outputlen, section->input, section->size);
|
memcpy(output + outputlen, section->input, section->size);
|
||||||
@ -354,38 +398,22 @@ int ElfLinker::addLoader(const char *sname)
|
|||||||
return outputlen;
|
return outputlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfLinker::addSection(const char *sname, const void *sdata, int slen, int align)
|
int ElfLinker::getSection(const char *sname, int *slen) const
|
||||||
{
|
{
|
||||||
assert(!frozen);
|
const Section *section = findSection(sname);
|
||||||
if (update_capacity(nsections, &nsections_capacity))
|
|
||||||
sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
|
|
||||||
assert(sections);
|
|
||||||
Section *sec = new Section(sname, sdata, slen, align);
|
|
||||||
sections[nsections++] = sec;
|
|
||||||
//return sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ElfLinker::freeze()
|
|
||||||
{
|
|
||||||
if (frozen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
frozen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ElfLinker::getSection(const char *sname, int *slen)
|
|
||||||
{
|
|
||||||
assert(frozen);
|
|
||||||
Section *section = findSection(sname);
|
|
||||||
if (slen)
|
if (slen)
|
||||||
*slen = section->size;
|
*slen = section->size;
|
||||||
return section->output - output;
|
return section->output - output;
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_byte *ElfLinker::getLoader(int *llen)
|
int ElfLinker::getSectionSize(const char *sname) const
|
||||||
{
|
{
|
||||||
assert(frozen);
|
const Section *section = findSection(sname);
|
||||||
|
return section->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
upx_byte *ElfLinker::getLoader(int *llen) const
|
||||||
|
{
|
||||||
if (llen)
|
if (llen)
|
||||||
*llen = outputlen;
|
*llen = outputlen;
|
||||||
return output;
|
return output;
|
||||||
@ -393,31 +421,38 @@ upx_byte *ElfLinker::getLoader(int *llen)
|
|||||||
|
|
||||||
void ElfLinker::relocate()
|
void ElfLinker::relocate()
|
||||||
{
|
{
|
||||||
assert(frozen);
|
assert(!reloc_done);
|
||||||
|
reloc_done = true;
|
||||||
for (unsigned ic = 0; ic < nrelocations; ic++)
|
for (unsigned ic = 0; ic < nrelocations; ic++)
|
||||||
{
|
{
|
||||||
Relocation *rel = relocations[ic];
|
const Relocation *rel = relocations[ic];
|
||||||
|
unsigned value;
|
||||||
|
|
||||||
if (rel->section->output == NULL)
|
if (rel->section->output == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (rel->value->section->output == NULL)
|
if (strcmp(rel->value->section->name, "*ABS*") == 0)
|
||||||
|
{
|
||||||
|
value = rel->value->offset;
|
||||||
|
}
|
||||||
|
else if (strcmp(rel->value->section->name, "*UND*") == 0 &&
|
||||||
|
rel->value->offset == 0xdeaddead)
|
||||||
|
{
|
||||||
|
printf("undefined symbol '%s' referenced\n", rel->value->name);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
else if (rel->value->section->output == NULL)
|
||||||
{
|
{
|
||||||
printf("can not apply reloc '%s:%x' without section '%s'\n",
|
printf("can not apply reloc '%s:%x' without section '%s'\n",
|
||||||
rel->section->name, rel->offset,
|
rel->section->name, rel->offset,
|
||||||
rel->value->section->name);
|
rel->value->section->name);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (strcmp(rel->value->section->name, "*UND*") == 0 &&
|
|
||||||
rel->value->offset == 0xdeaddead)
|
|
||||||
{
|
{
|
||||||
printf("undefined symbol '%s' referenced\n", rel->value->name);
|
value = rel->value->section->offset +
|
||||||
abort();
|
rel->value->offset + rel->add;
|
||||||
}
|
}
|
||||||
unsigned 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;
|
||||||
|
|
||||||
relocate1(rel, location, value, rel->type);
|
relocate1(rel, location, value, rel->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,7 +460,12 @@ void ElfLinker::relocate()
|
|||||||
void ElfLinker::defineSymbol(const char *name, unsigned value)
|
void ElfLinker::defineSymbol(const char *name, unsigned value)
|
||||||
{
|
{
|
||||||
Symbol *symbol = findSymbol(name);
|
Symbol *symbol = findSymbol(name);
|
||||||
if (strcmp(symbol->section->name, "*UND*") == 0) // for undefined symbols
|
if (strcmp(symbol->section->name, "*ABS*") == 0)
|
||||||
|
{
|
||||||
|
printf("defineSymbol: symbol '%s' is *ABS*\n", name);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
else if (strcmp(symbol->section->name, "*UND*") == 0) // for undefined symbols
|
||||||
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
|
||||||
{
|
{
|
||||||
@ -438,36 +478,38 @@ void ElfLinker::defineSymbol(const char *name, unsigned value)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("symbol '%s' already defined\n", name);
|
printf("defineSymbol: symbol '%s' already defined\n", name);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// debugging support
|
// debugging support
|
||||||
void ElfLinker::dumpSymbols(FILE *fp) const
|
void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const
|
||||||
{
|
{
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
fp = stdout;
|
fp = stdout;
|
||||||
for (unsigned ic = 0; ic < nsymbols; ic++)
|
for (unsigned ic = 0; ic < nsymbols; ic++)
|
||||||
{
|
{
|
||||||
Symbol *symbol = symbols[ic];
|
const Symbol *symbol = symbols[ic];
|
||||||
fprintf(fp, "%-20s 0x%08x | %-20s 0x%08x\n",
|
if ((flags & 1) && symbol->section->output == NULL)
|
||||||
|
continue;
|
||||||
|
fprintf(fp, "%-28s 0x%08x | %-28s 0x%08x\n",
|
||||||
symbol->name, symbol->offset, symbol->section->name, symbol->section->offset);
|
symbol->name, symbol->offset, symbol->section->name, symbol->section->offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ElfLinker::getSymbolOffset(const char *name) const
|
unsigned ElfLinker::getSymbolOffset(const char *name) const
|
||||||
{
|
{
|
||||||
assert(frozen);
|
const Symbol *symbol = findSymbol(name);
|
||||||
Symbol *symbol = const_cast<ElfLinker *>(this)->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, upx_byte b)
|
void ElfLinker::alignWithByte(unsigned len, unsigned char b)
|
||||||
{
|
{
|
||||||
memset(output + outputlen, b, len);
|
memset(output + outputlen, b, len);
|
||||||
|
outputlen += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfLinker::relocate1(const Relocation *rel, upx_byte *,
|
void ElfLinker::relocate1(const Relocation *rel, upx_byte *,
|
||||||
@ -483,6 +525,23 @@ void ElfLinker::relocate1(const Relocation *rel, upx_byte *,
|
|||||||
// FIXME: add more displacment overflow checks
|
// FIXME: add more displacment overflow checks
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if 0 // FIXME
|
||||||
|
static void check8(const Relocation *rel, const upx_byte *location, int v, int d)
|
||||||
|
{
|
||||||
|
if (v < -128 || v > 127) {
|
||||||
|
printf("value out of range (%d) in reloc %s:%x\n",
|
||||||
|
v, rel->section->name, rel->offset);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (d < -128 || d > 127) {
|
||||||
|
printf("displacement target out of range (%d) in reloc %s:%x\n",
|
||||||
|
v, rel->section->name, rel->offset);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
|
void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
|
||||||
unsigned value, const char *type)
|
unsigned value, const char *type)
|
||||||
{
|
{
|
||||||
@ -580,6 +639,7 @@ void ElfLinkerM68k::alignCode(unsigned len)
|
|||||||
assert((outputlen & 1) == 0);
|
assert((outputlen & 1) == 0);
|
||||||
for (unsigned i = 0; i < len; i += 2)
|
for (unsigned i = 0; i < len; i += 2)
|
||||||
set_be16(output + outputlen + i, 0x4e71); // "nop"
|
set_be16(output + outputlen + i, 0x4e71); // "nop"
|
||||||
|
outputlen += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location,
|
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location,
|
||||||
@ -651,12 +711,12 @@ void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location,
|
|||||||
return super::relocate1(rel, location, value, type);
|
return super::relocate1(rel, location, value, type);
|
||||||
type += 6;
|
type += 6;
|
||||||
|
|
||||||
int range_check = 0;
|
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 = 1;
|
range_check = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(type, "8") == 0)
|
if (strcmp(type, "8") == 0)
|
||||||
|
|||||||
22
src/linker.h
22
src/linker.h
@ -41,8 +41,6 @@ protected:
|
|||||||
struct Symbol;
|
struct Symbol;
|
||||||
struct Relocation;
|
struct Relocation;
|
||||||
|
|
||||||
bool frozen; // FIXME: can we remove this ?
|
|
||||||
|
|
||||||
upx_byte *input;
|
upx_byte *input;
|
||||||
int inputlen;
|
int inputlen;
|
||||||
upx_byte *output;
|
upx_byte *output;
|
||||||
@ -62,11 +60,13 @@ protected:
|
|||||||
unsigned nrelocations;
|
unsigned nrelocations;
|
||||||
unsigned nrelocations_capacity;
|
unsigned nrelocations_capacity;
|
||||||
|
|
||||||
|
bool reloc_done;
|
||||||
|
|
||||||
void preprocessSections(char *start, const char *end);
|
void preprocessSections(char *start, const char *end);
|
||||||
void preprocessSymbols(char *start, const char *end);
|
void preprocessSymbols(char *start, const char *end);
|
||||||
void preprocessRelocations(char *start, const char *end);
|
void preprocessRelocations(char *start, const char *end);
|
||||||
Section *findSection(const char *name) const;
|
Section *findSection(const char *name, bool fatal=true) const;
|
||||||
Symbol *findSymbol(const char *name) /*const*/;
|
Symbol *findSymbol(const char *name, bool fatal=true) const;
|
||||||
|
|
||||||
Symbol *addSymbol(const char *name, const char *section, unsigned offset);
|
Symbol *addSymbol(const char *name, const char *section, unsigned offset);
|
||||||
Relocation *addRelocation(const char *section, unsigned off, const char *type,
|
Relocation *addRelocation(const char *section, unsigned off, const char *type,
|
||||||
@ -79,16 +79,16 @@ public:
|
|||||||
virtual void init(const void *pdata, int plen);
|
virtual void init(const void *pdata, int plen);
|
||||||
virtual void setLoaderAlignOffset(int phase);
|
virtual void setLoaderAlignOffset(int phase);
|
||||||
virtual int addLoader(const char *sname);
|
virtual int addLoader(const char *sname);
|
||||||
virtual void addSection(const char *sname, const void *sdata, int slen, int align);
|
virtual Section *addSection(const char *sname, const void *sdata, int slen, unsigned p2align);
|
||||||
virtual void freeze();
|
virtual int getSection(const char *sname, int *slen=NULL) const;
|
||||||
virtual int getSection(const char *sname, int *slen=NULL);
|
virtual int getSectionSize(const char *sname) const;
|
||||||
virtual upx_byte *getLoader(int *llen=NULL);
|
virtual upx_byte *getLoader(int *llen=NULL) const;
|
||||||
virtual void relocate();
|
virtual void relocate();
|
||||||
virtual void defineSymbol(const char *name, unsigned value);
|
virtual void defineSymbol(const char *name, unsigned value);
|
||||||
virtual unsigned getSymbolOffset(const char *) const;
|
virtual unsigned getSymbolOffset(const char *) const;
|
||||||
virtual void dumpSymbols(FILE *fp=NULL) const;
|
virtual void dumpSymbols(unsigned flags=0, FILE *fp=NULL) const;
|
||||||
|
|
||||||
void alignWithByte(unsigned len, upx_byte b);
|
void alignWithByte(unsigned len, unsigned char b);
|
||||||
virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
|
virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
|
||||||
virtual void alignData(unsigned len) { alignWithByte(len, 0); }
|
virtual void alignData(unsigned len) { alignWithByte(len, 0); }
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ struct ElfLinker::Section : private nocopy
|
|||||||
upx_byte *output;
|
upx_byte *output;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
unsigned char align; // log2
|
unsigned p2align; // log2
|
||||||
Section *next;
|
Section *next;
|
||||||
|
|
||||||
Section(const char *n, const void *i, unsigned s, unsigned a=0);
|
Section(const char *n, const void *i, unsigned s, unsigned a=0);
|
||||||
|
|||||||
@ -932,12 +932,6 @@ unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image,
|
|||||||
// loader util
|
// loader util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void Packer::freezeLoader()
|
|
||||||
{
|
|
||||||
linker->freeze();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
upx_byte *Packer::getLoader() const
|
upx_byte *Packer::getLoader() const
|
||||||
{
|
{
|
||||||
int size = -1;
|
int size = -1;
|
||||||
@ -1034,6 +1028,12 @@ void Packer::initLoader(const void *pdata, int plen, int small)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Packer::addLoader(const char *s)
|
||||||
|
{
|
||||||
|
if (s && *s)
|
||||||
|
linker->addLoader(s);
|
||||||
|
}
|
||||||
|
|
||||||
void __acc_cdecl_va Packer::addLoader(const char *s, ...)
|
void __acc_cdecl_va Packer::addLoader(const char *s, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
@ -206,14 +206,16 @@ protected:
|
|||||||
virtual int buildLoader(const Filter *ft) = 0;
|
virtual int buildLoader(const Filter *ft) = 0;
|
||||||
virtual Linker* newLinker() const = 0;
|
virtual Linker* newLinker() const = 0;
|
||||||
// loader util for linker
|
// loader util for linker
|
||||||
virtual void freezeLoader();
|
void freezeLoader() { }
|
||||||
virtual upx_byte *getLoader() const;
|
virtual upx_byte *getLoader() const;
|
||||||
virtual int getLoaderSize() const;
|
virtual int getLoaderSize() const;
|
||||||
virtual void initLoader(const void *pdata, int plen, int small=-1);
|
virtual void initLoader(const void *pdata, int plen, int small=-1);
|
||||||
#if 1 && (ACC_CC_GNUC >= 0x040100)
|
#if 1 && (ACC_CC_GNUC >= 0x040100)
|
||||||
virtual void __acc_cdecl_va addLoader(const char *s, ...) __attribute__((__sentinel__));
|
virtual void addLoader(const char *);
|
||||||
|
virtual void __acc_cdecl_va addLoader(const char *, ...) __attribute__((__sentinel__));
|
||||||
#else
|
#else
|
||||||
virtual void __acc_cdecl_va addLoader(const char *s, ...);
|
virtual void addLoader(const char *);
|
||||||
|
virtual void __acc_cdecl_va addLoader(const char *, ...);
|
||||||
#endif
|
#endif
|
||||||
virtual int getLoaderSection(const char *name, int *slen=NULL) const;
|
virtual int getLoaderSection(const char *name, int *slen=NULL) const;
|
||||||
virtual int getLoaderSectionStart(const char *name, int *slen=NULL) const;
|
virtual int getLoaderSectionStart(const char *name, int *slen=NULL) const;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user