ElfLinker improvements
Sections/symbols/relocations are allocated dynamically Sections use an internal copy of their input data
This commit is contained in:
+81
-13
@@ -346,6 +346,42 @@ unsigned char *SimpleLinker::getLoader(int *llen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
ElfLinker::Section::Section(const char *n, const void *i, unsigned s) :
|
||||||
|
name(strdup(n)), output(NULL), size(s), offset(0), next(NULL)
|
||||||
|
{
|
||||||
|
assert(name);
|
||||||
|
input = malloc(s + 1);
|
||||||
|
assert(input);
|
||||||
|
memcpy(input, i, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::Section::~Section()
|
||||||
|
{
|
||||||
|
free(name);
|
||||||
|
free(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::Symbol::Symbol(const char *n, Section *s, unsigned o) :
|
||||||
|
name(strdup(n)), section(s), offset(o)
|
||||||
|
{
|
||||||
|
assert(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::Symbol::~Symbol()
|
||||||
|
{
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::Relocation::Relocation(Section *s, unsigned o, const char *t,
|
||||||
|
Symbol *v, unsigned a) :
|
||||||
|
section(s), offset(o), type(t), value(v), add(a)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
void ElfLinker::preprocessSections(char *start, const char *end)
|
void ElfLinker::preprocessSections(char *start, const char *end)
|
||||||
{
|
{
|
||||||
nsections = 0;
|
nsections = 0;
|
||||||
@@ -390,10 +426,9 @@ void ElfLinker::preprocessSymbols(char *start, const char *end)
|
|||||||
char *s = strstr(start, symbol);
|
char *s = strstr(start, symbol);
|
||||||
s[strlen(symbol)] = 0;
|
s[strlen(symbol)] = 0;
|
||||||
|
|
||||||
assert(nsymbols < TABLESIZE(symbols));
|
|
||||||
if (strcmp(section, "*UND*") == 0)
|
if (strcmp(section, "*UND*") == 0)
|
||||||
offset = 0xdeaddead;
|
offset = 0xdeaddead;
|
||||||
symbols[nsymbols++] = Symbol(s, findSection(section), offset);
|
addSymbol(s, section, offset);
|
||||||
|
|
||||||
//printf("symbol %s preprocessed o=%x\n", s, offset);
|
//printf("symbol %s preprocessed o=%x\n", s, offset);
|
||||||
}
|
}
|
||||||
@@ -433,9 +468,7 @@ void ElfLinker::preprocessRelocations(char *start, const char *end)
|
|||||||
sscanf(p + 3, "%x", &add);
|
sscanf(p + 3, "%x", &add);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(nrelocations < TABLESIZE(relocations));
|
addRelocation(section->name, offset, t, symbol, add);
|
||||||
relocations[nrelocations++] = Relocation(section, offset, t,
|
|
||||||
findSymbol(symbol), add);
|
|
||||||
|
|
||||||
//printf("relocation %s %x preprocessed\n", section->name, offset);
|
//printf("relocation %s %x preprocessed\n", section->name, offset);
|
||||||
}
|
}
|
||||||
@@ -447,8 +480,8 @@ void ElfLinker::preprocessRelocations(char *start, const char *end)
|
|||||||
ElfLinker::Section *ElfLinker::findSection(const char *name)
|
ElfLinker::Section *ElfLinker::findSection(const char *name)
|
||||||
{
|
{
|
||||||
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];
|
||||||
|
|
||||||
printf("unknown section %s\n", name);
|
printf("unknown section %s\n", name);
|
||||||
abort();
|
abort();
|
||||||
@@ -458,21 +491,54 @@ ElfLinker::Section *ElfLinker::findSection(const char *name)
|
|||||||
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name)
|
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name)
|
||||||
{
|
{
|
||||||
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];
|
||||||
|
|
||||||
printf("unknown symbol %s\n", name);
|
printf("unknown symbol %s\n", name);
|
||||||
abort();
|
abort();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfLinker::ElfLinker() : input(NULL), output(NULL), head(NULL), tail(NULL)
|
void ElfLinker::addSymbol(const char *name, const char *section,
|
||||||
|
unsigned offset)
|
||||||
|
{
|
||||||
|
symbols = static_cast<Symbol **>(realloc(symbols, (nsymbols + 1)
|
||||||
|
* sizeof(Symbol *)));
|
||||||
|
assert(symbols);
|
||||||
|
symbols[nsymbols++] = new Symbol(name, findSection(section), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElfLinker::addRelocation(const char *section, unsigned off,
|
||||||
|
const char *type, const char *symbol,
|
||||||
|
unsigned add)
|
||||||
|
{
|
||||||
|
relocations = static_cast<Relocation **>(realloc(relocations,
|
||||||
|
(nrelocations + 1)
|
||||||
|
* sizeof(Relocation *)));
|
||||||
|
assert(relocations);
|
||||||
|
relocations[nrelocations++] = new Relocation(findSection(section), off,
|
||||||
|
type, findSymbol(symbol), add);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfLinker::ElfLinker() : input(NULL), output(NULL), head(NULL), tail(NULL),
|
||||||
|
sections(NULL), symbols(NULL), relocations(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ElfLinker::~ElfLinker()
|
ElfLinker::~ElfLinker()
|
||||||
{
|
{
|
||||||
delete [] input;
|
delete [] input;
|
||||||
delete [] output;
|
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, int)
|
void ElfLinker::init(const void *pdata, int plen, int)
|
||||||
@@ -562,8 +628,10 @@ int ElfLinker::addSection(const char *sname)
|
|||||||
void ElfLinker::addSection(const char *sname, const void *sdata, int slen)
|
void ElfLinker::addSection(const char *sname, const void *sdata, int slen)
|
||||||
{
|
{
|
||||||
assert(!frozen);
|
assert(!frozen);
|
||||||
assert(nsections < TABLESIZE(sections));
|
sections = static_cast<Section **>(realloc(sections, (nsections + 1)
|
||||||
sections[nsections++] = Section(sname, sdata, slen);
|
* sizeof(Section *)));
|
||||||
|
assert(sections);
|
||||||
|
sections[nsections++] = new Section(sname, sdata, slen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfLinker::freeze()
|
void ElfLinker::freeze()
|
||||||
@@ -598,7 +666,7 @@ void ElfLinker::relocate()
|
|||||||
|
|
||||||
for (unsigned ic = 0; ic < nrelocations; ic++)
|
for (unsigned ic = 0; ic < nrelocations; ic++)
|
||||||
{
|
{
|
||||||
Relocation *rel = relocations + ic;
|
Relocation *rel = relocations[ic];
|
||||||
if (rel->section->output == NULL)
|
if (rel->section->output == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (rel->value->section->output == NULL)
|
if (rel->value->section->output == NULL)
|
||||||
|
|||||||
+51
-45
@@ -151,52 +151,18 @@ typedef TSimpleLinker<NBELE::BEPolicy> SimpleBELinker;
|
|||||||
typedef TSimpleLinker<NBELE::LEPolicy> SimpleLELinker;
|
typedef TSimpleLinker<NBELE::LEPolicy> SimpleLELinker;
|
||||||
|
|
||||||
|
|
||||||
class ElfLinker : public Linker
|
/*************************************************************************
|
||||||
|
// ElfLinker
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
class ElfLinker : public Linker, private nocopy
|
||||||
{
|
{
|
||||||
typedef Linker super;
|
typedef Linker super;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct Section
|
struct Section;
|
||||||
{
|
struct Symbol;
|
||||||
const char *name;
|
struct Relocation;
|
||||||
const void *input;
|
|
||||||
upx_byte *output;
|
|
||||||
unsigned size;
|
|
||||||
unsigned offset;
|
|
||||||
Section *next;
|
|
||||||
|
|
||||||
Section(){}
|
|
||||||
Section(const char *n, const void *i, unsigned s) :
|
|
||||||
name(n), input(i), output(NULL), size(s), offset(0), next(NULL)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Symbol
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
Section *section;
|
|
||||||
unsigned offset;
|
|
||||||
|
|
||||||
Symbol(){}
|
|
||||||
Symbol(const char *n, Section *s, unsigned o) :
|
|
||||||
name(n), section(s), offset(o)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Relocation
|
|
||||||
{
|
|
||||||
Section *section;
|
|
||||||
unsigned offset;
|
|
||||||
const char *type;
|
|
||||||
Symbol *value;
|
|
||||||
unsigned add; // used in .rela relocations
|
|
||||||
|
|
||||||
Relocation(){}
|
|
||||||
Relocation(Section *s, unsigned o, const char *t,
|
|
||||||
Symbol *v, unsigned a) :
|
|
||||||
section(s), offset(o), type(t), value(v), add(a)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
upx_byte *input;
|
upx_byte *input;
|
||||||
int inputlen;
|
int inputlen;
|
||||||
@@ -206,9 +172,9 @@ protected:
|
|||||||
Section *head;
|
Section *head;
|
||||||
Section *tail;
|
Section *tail;
|
||||||
|
|
||||||
Section sections[550];
|
Section **sections;
|
||||||
Symbol symbols[1000];
|
Symbol **symbols;
|
||||||
Relocation relocations[2000];
|
Relocation **relocations;
|
||||||
|
|
||||||
unsigned nsections;
|
unsigned nsections;
|
||||||
unsigned nsymbols;
|
unsigned nsymbols;
|
||||||
@@ -220,6 +186,10 @@ protected:
|
|||||||
Section *findSection(const char *name);
|
Section *findSection(const char *name);
|
||||||
Symbol *findSymbol(const char *name);
|
Symbol *findSymbol(const char *name);
|
||||||
|
|
||||||
|
void addSymbol(const char *name, const char *section, unsigned offset);
|
||||||
|
void addRelocation(const char *section, unsigned off, const char *type,
|
||||||
|
const char *symbol, unsigned add);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElfLinker();
|
ElfLinker();
|
||||||
|
|
||||||
@@ -248,6 +218,42 @@ protected:
|
|||||||
unsigned value, const char *type);
|
unsigned value, const char *type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ElfLinker::Section : private nocopy
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
void *input;
|
||||||
|
upx_byte *output;
|
||||||
|
unsigned size;
|
||||||
|
unsigned offset;
|
||||||
|
Section *next;
|
||||||
|
|
||||||
|
Section(const char *n, const void *i, unsigned s);
|
||||||
|
~Section();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ElfLinker::Symbol : private nocopy
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
Section *section;
|
||||||
|
unsigned offset;
|
||||||
|
|
||||||
|
Symbol(const char *n, Section *s, unsigned o);
|
||||||
|
~Symbol();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ElfLinker::Relocation : private nocopy
|
||||||
|
{
|
||||||
|
Section *section;
|
||||||
|
unsigned offset;
|
||||||
|
const char *type;
|
||||||
|
Symbol *value;
|
||||||
|
unsigned add; // used in .rela relocations
|
||||||
|
|
||||||
|
Relocation(Section *s, unsigned o, const char *t,
|
||||||
|
Symbol *v, unsigned a);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class ElfLinkerX86 : public ElfLinker
|
class ElfLinkerX86 : public ElfLinker
|
||||||
{
|
{
|
||||||
typedef ElfLinker super;
|
typedef ElfLinker super;
|
||||||
|
|||||||
Reference in New Issue
Block a user