From 3d3c20e507ddd370a06ec8f107eb30a67b1b8815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Moln=C3=A1r?= Date: Tue, 11 Jul 2006 14:40:58 +0200 Subject: [PATCH] ElfLinker improvements Sections/symbols/relocations are allocated dynamically Sections use an internal copy of their input data --- src/linker.cpp | 94 +++++++++++++++++++++++++++++++++++++++++------- src/linker.h | 96 +++++++++++++++++++++++++++----------------------- 2 files changed, 132 insertions(+), 58 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index 34c34008..b462970b 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -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(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(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
(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) diff --git a/src/linker.h b/src/linker.h index 64c9ea23..372f6415 100644 --- a/src/linker.h +++ b/src/linker.h @@ -151,52 +151,18 @@ typedef TSimpleLinker SimpleBELinker; typedef TSimpleLinker 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;