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:
parent
67a282f19f
commit
3d3c20e507
|
@ -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)
|
||||
|
|
96
src/linker.h
96
src/linker.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user