1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

ElfLinker improvements

Sections/symbols/relocations are allocated dynamically
Sections use an internal copy of their input data
This commit is contained in:
László Molnár 2006-07-11 14:40:58 +02:00
parent 67a282f19f
commit 3d3c20e507
2 changed files with 132 additions and 58 deletions

View File

@ -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)
{
nsections = 0;
@ -390,10 +426,9 @@ void ElfLinker::preprocessSymbols(char *start, const char *end)
char *s = strstr(start, symbol);
s[strlen(symbol)] = 0;
assert(nsymbols < TABLESIZE(symbols));
if (strcmp(section, "*UND*") == 0)
offset = 0xdeaddead;
symbols[nsymbols++] = Symbol(s, findSection(section), offset);
addSymbol(s, section, 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);
}
assert(nrelocations < TABLESIZE(relocations));
relocations[nrelocations++] = Relocation(section, offset, t,
findSymbol(symbol), add);
addRelocation(section->name, offset, t, symbol, add);
//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)
{
for (unsigned ic = 0; ic < nsections; ic++)
if (strcmp(sections[ic].name, name) == 0)
return sections + ic;
if (strcmp(sections[ic]->name, name) == 0)
return sections[ic];
printf("unknown section %s\n", name);
abort();
@ -458,21 +491,54 @@ ElfLinker::Section *ElfLinker::findSection(const char *name)
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name)
{
for (unsigned ic = 0; ic < nsymbols; ic++)
if (strcmp(symbols[ic].name, name) == 0)
return symbols + ic;
if (strcmp(symbols[ic]->name, name) == 0)
return symbols[ic];
printf("unknown symbol %s\n", name);
abort();
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()
{
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, int)
@ -562,8 +628,10 @@ int ElfLinker::addSection(const char *sname)
void ElfLinker::addSection(const char *sname, const void *sdata, int slen)
{
assert(!frozen);
assert(nsections < TABLESIZE(sections));
sections[nsections++] = Section(sname, sdata, slen);
sections = static_cast<Section **>(realloc(sections, (nsections + 1)
* sizeof(Section *)));
assert(sections);
sections[nsections++] = new Section(sname, sdata, slen);
}
void ElfLinker::freeze()
@ -598,7 +666,7 @@ void ElfLinker::relocate()
for (unsigned ic = 0; ic < nrelocations; ic++)
{
Relocation *rel = relocations + ic;
Relocation *rel = relocations[ic];
if (rel->section->output == NULL)
continue;
if (rel->value->section->output == NULL)

View File

@ -151,52 +151,18 @@ typedef TSimpleLinker<NBELE::BEPolicy> SimpleBELinker;
typedef TSimpleLinker<NBELE::LEPolicy> SimpleLELinker;
class ElfLinker : public Linker
/*************************************************************************
// ElfLinker
**************************************************************************/
class ElfLinker : public Linker, private nocopy
{
typedef Linker super;
protected:
struct Section
{
const char *name;
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)
{}
};
struct Section;
struct Symbol;
struct Relocation;
upx_byte *input;
int inputlen;
@ -206,9 +172,9 @@ protected:
Section *head;
Section *tail;
Section sections[550];
Symbol symbols[1000];
Relocation relocations[2000];
Section **sections;
Symbol **symbols;
Relocation **relocations;
unsigned nsections;
unsigned nsymbols;
@ -220,6 +186,10 @@ protected:
Section *findSection(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:
ElfLinker();
@ -248,6 +218,42 @@ protected:
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
{
typedef ElfLinker super;