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

ElfLinker updates

commented out the debugging printfs
now it's possible to set the offset of sections
aligment handling simplified
ElfLinkerArmPE introduced
This commit is contained in:
László Molnár 2006-07-01 00:10:02 +02:00
parent bfc2fab33f
commit c5fb161477
2 changed files with 125 additions and 58 deletions

View File

@ -364,7 +364,7 @@ void ElfLinker::preprocessSections(char *start, const char *end)
n[strlen(name)] = 0; n[strlen(name)] = 0;
addSection(n, input + offset, size); addSection(n, input + offset, size);
printf("section %s preprocessed\n", n); //printf("section %s preprocessed\n", n);
} }
start = nextl + 1; start = nextl + 1;
} }
@ -395,7 +395,7 @@ void ElfLinker::preprocessSymbols(char *start, const char *end)
offset = 0xdeaddead; offset = 0xdeaddead;
symbols[nsymbols++] = Symbol(s, findSection(section), offset); symbols[nsymbols++] = Symbol(s, findSection(section), offset);
printf("symbol %s preprocessed o=%x\n", s, offset); //printf("symbol %s preprocessed o=%x\n", s, offset);
} }
start = nextl + 1; start = nextl + 1;
@ -430,7 +430,7 @@ void ElfLinker::preprocessRelocations(char *start, const char *end)
relocations[nrelocations++] = Relocation(section, offset, t, relocations[nrelocations++] = Relocation(section, offset, t,
findSymbol(symbol)); findSymbol(symbol));
printf("relocation %s %x preprocessed\n", section->name, offset); //printf("relocation %s %x preprocessed\n", section->name, offset);
} }
start = nextl + 1; start = nextl + 1;
@ -459,7 +459,7 @@ ElfLinker::Symbol *ElfLinker::findSymbol(const char *name)
return NULL; return NULL;
} }
ElfLinker::ElfLinker() : input(NULL), output(NULL) ElfLinker::ElfLinker() : input(NULL), output(NULL), head(NULL), tail(NULL)
{} {}
ElfLinker::~ElfLinker() ElfLinker::~ElfLinker()
@ -470,12 +470,12 @@ ElfLinker::~ElfLinker()
void ElfLinker::init(const void *pdata, int plen, int) void ElfLinker::init(const void *pdata, int plen, int)
{ {
unsigned char *i = new unsigned char[plen]; upx_byte *i = new upx_byte[plen];
memcpy(i, pdata, plen); memcpy(i, pdata, plen);
input = i; input = i;
inputlen = plen; inputlen = plen;
output = new unsigned char[plen]; output = new upx_byte[plen];
outputlen = 0; outputlen = 0;
int pos = find(input, plen, "Sections:", 9); int pos = find(input, plen, "Sections:", 9);
@ -491,6 +491,7 @@ void ElfLinker::init(const void *pdata, int plen, int)
preprocessSections(psections, psymbols); preprocessSections(psections, psymbols);
preprocessSymbols(psymbols, prelocs); preprocessSymbols(psymbols, prelocs);
preprocessRelocations(prelocs, (char*) input + inputlen); preprocessRelocations(prelocs, (char*) input + inputlen);
addSection("*UND*");
} }
void ElfLinker::setLoaderAlignOffset(int phase) void ElfLinker::setLoaderAlignOffset(int phase)
@ -517,14 +518,32 @@ int ElfLinker::addSection(const char *sname)
} }
if (*sect == '+') // alignment if (*sect == '+') // alignment
align(hex(sect[1]), hex(sect[2])); {
assert(tail);
if (unsigned l = (hex(sect[1]) - tail->offset - tail->size)
% hex(sect[2]))
{
align(l);
tail->size += l;
outputlen += l;
}
}
else else
{ {
Section *section = findSection(sect); Section *section = findSection(sect);
memcpy(output + outputlen, section->input, section->size); memcpy(output + outputlen, section->input, section->size);
section->output = output + outputlen; section->output = output + outputlen;
outputlen += section->size; outputlen += section->size;
printf("section added: %s\n", sect); //printf("section added: %s\n", sect);
if (head)
{
tail->next = section;
section->offset = tail->offset + tail->size;
}
else
head = section;
tail = section;
} }
sect += strlen(sect) + 1; sect += strlen(sect) + 1;
} }
@ -534,6 +553,7 @@ 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(nsections < TABLESIZE(sections)); assert(nsections < TABLESIZE(sections));
sections[nsections++] = Section(sname, sdata, slen); sections[nsections++] = Section(sname, sdata, slen);
} }
@ -543,9 +563,6 @@ void ElfLinker::freeze()
if (frozen) if (frozen)
return; return;
addSection("*UND*");
findSection("*UND*")->output = output;
frozen = true; frozen = true;
} }
@ -558,7 +575,7 @@ int ElfLinker::getSection(const char *sname, int *slen)
return section->output - output; return section->output - output;
} }
unsigned char *ElfLinker::getLoader(int *llen) upx_byte *ElfLinker::getLoader(int *llen)
{ {
assert(frozen); assert(frozen);
@ -569,6 +586,8 @@ unsigned char *ElfLinker::getLoader(int *llen)
void ElfLinker::relocate() void ElfLinker::relocate()
{ {
assert(frozen);
for (unsigned ic = 0; ic < nrelocations; ic++) for (unsigned ic = 0; ic < nrelocations; ic++)
{ {
Relocation *rel = relocations + ic; Relocation *rel = relocations + ic;
@ -579,8 +598,7 @@ void ElfLinker::relocate()
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();
continue;
} }
if (strcmp(rel->value->section->name, "*UND*") == 0 && if (strcmp(rel->value->section->name, "*UND*") == 0 &&
@ -589,10 +607,8 @@ void ElfLinker::relocate()
printf("undefined symbol '%s' referenced\n", rel->value->name); printf("undefined symbol '%s' referenced\n", rel->value->name);
abort(); abort();
} }
unsigned value = rel->value->section->output + rel->value->offset unsigned value = rel->value->section->offset + rel->value->offset;
- output; upx_byte *location = rel->section->output + rel->offset;
unsigned char *location = rel->section->output + rel->offset;
relocate1(rel, location, value, rel->type); relocate1(rel, location, value, rel->type);
} }
@ -601,71 +617,105 @@ 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) 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
{
for (Section *section = symbol->section; section; section = section->next)
{
assert(section->offset < value);
section->offset = value;
value += section->size;
}
}
else else
{
printf("symbol '%s' already defined\n", name); printf("symbol '%s' already defined\n", name);
abort();
}
} }
void ElfLinker::alignWithByte(unsigned modulus, unsigned remainder, unsigned ElfLinker::getSymbolOffset(const char *name) const
unsigned char b)
{ {
unsigned l = (remainder - outputlen) % modulus; assert(frozen);
memset(output + outputlen, b, l); Symbol *symbol = const_cast<ElfLinker *>(this)->findSymbol(name);
outputlen += l; return symbol->section->offset + symbol->offset;
} }
void ElfLinker::align(unsigned modulus, unsigned remainder) void ElfLinker::alignWithByte(unsigned len, upx_byte b)
{ {
alignWithByte(modulus, remainder, 0); memset(output + outputlen, b, len);
} }
void ElfLinker::relocate1(Relocation *rel, unsigned char *, void ElfLinker::align(unsigned len)
{
alignWithByte(len, 0);
}
void ElfLinker::relocate1(Relocation *rel, upx_byte *,
unsigned, const char *) unsigned, const char *)
{ {
printf("unknown relocation type '%s\n", rel->type); printf("unknown relocation type '%s\n", rel->type);
abort(); abort();
} }
void ElfLinkerX86::align(unsigned modulus, unsigned remainder) void ElfLinkerX86::align(unsigned len)
{ {
alignWithByte(modulus, remainder, 0x90); alignWithByte(len, 0x90);
} }
void ElfLinkerX86::relocate1(Relocation *rel, unsigned char *location, void ElfLinkerX86::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type) unsigned value, const char *type)
{ {
if (strcmp(rel->type, "R_386_PC8") == 0) if (strncmp(type, "R_386_", 6))
return super::relocate1(rel, location, value, type);
type += 6;
if (strncmp(type, "PC", 2) == 0)
{ {
value -= location - output; value -= rel->section->offset + rel->offset;
type += 2;
}
if (strcmp(type, "8") == 0)
*location += value; *location += value;
} else if (strcmp(type, "16") == 0)
else if (strcmp(rel->type, "R_386_PC16") == 0)
{
value -= location - output;
set_le16(location, get_le16(location) + value); set_le16(location, get_le16(location) + value);
} else if (strcmp(type, "32") == 0)
else if (strcmp(rel->type, "R_386_PC32") == 0) set_le32(location, get_le32(location) + value);
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerArmLE::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strcmp(type, "R_ARM_PC24") == 0)
{ {
value -= location - output; value -= location - output;
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value / 4);
} }
else if (strcmp(rel->type, "R_386_32") == 0) else if (strcmp(type, "R_ARM_ABS32") == 0)
{ {
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
} }
else if (strcmp(rel->type, "R_386_16") == 0) else if (strcmp(type, "R_ARM_THM_CALL") == 0)
{ {
set_le16(location, get_le16(location) + value); value -= location - output;
} value += ((get_le16(location) & 0x7ff) << 12);
else if (strcmp(rel->type, "R_386_8") == 0) value += (get_le16(location + 2) & 0x7ff) << 1;
{
*location += value; set_le16(location, 0xf000 + (value) >> 12);
set_le16(location + 2, 0xf800 + (value) >> 1);
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
//set_le32(location, get_le32(location) + value / 4);
} }
else else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
/* /*
vi:ts=4:et vi:ts=4:et
*/ */

View File

@ -54,8 +54,10 @@ public:
virtual int getSection(const char *sname, int *slen=NULL) = 0; virtual int getSection(const char *sname, int *slen=NULL) = 0;
virtual unsigned char *getLoader(int *llen=NULL) = 0; virtual unsigned char *getLoader(int *llen=NULL) = 0;
// for ElfLinker descendants
virtual void defineSymbol(const char *, unsigned) {} virtual void defineSymbol(const char *, unsigned) {}
virtual void relocate() {} virtual void relocate() {}
virtual unsigned getSymbolOffset(const char *) const { return 0; }
protected: protected:
bool frozen; bool frozen;
@ -158,12 +160,14 @@ protected:
{ {
const char *name; const char *name;
const void *input; const void *input;
unsigned char *output; upx_byte *output;
unsigned size; unsigned size;
unsigned offset;
Section *next;
Section(){} Section(){}
Section(const char *n, const void *i, unsigned s) : Section(const char *n, const void *i, unsigned s) :
name(n), input(i), output(NULL), size(s) name(n), input(i), output(NULL), size(s), offset(0), next(NULL)
{} {}
}; };
@ -192,10 +196,13 @@ protected:
{} {}
}; };
unsigned char *input; upx_byte *input;
int inputlen; int inputlen;
unsigned char *output; upx_byte *output;
int outputlen; int outputlen;
Section *head;
Section *tail;
Section sections[550]; Section sections[550];
Symbol symbols[1000]; Symbol symbols[1000];
@ -223,18 +230,19 @@ protected:
virtual void addSection(const char *sname, const void *sdata, int slen); virtual void addSection(const char *sname, const void *sdata, int slen);
virtual void freeze(); virtual void freeze();
virtual int getSection(const char *sname, int *slen=NULL); virtual int getSection(const char *sname, int *slen=NULL);
virtual unsigned char *getLoader(int *llen=NULL); virtual upx_byte *getLoader(int *llen=NULL);
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 get32(const void *) const { return 0; } virtual unsigned get32(const void *) const { return 0; }
virtual void set32(void *, unsigned) const {} virtual void set32(void *, unsigned) const {}
// //
void alignWithByte(unsigned modulus, unsigned remainder, unsigned char b); void alignWithByte(unsigned len, upx_byte b);
virtual void align(unsigned modulus, unsigned remainder); virtual void align(unsigned len);
virtual void relocate1(Relocation *, unsigned char *location, virtual void relocate1(Relocation *, upx_byte *location,
unsigned value, const char *type); unsigned value, const char *type);
}; };
@ -243,8 +251,17 @@ class ElfLinkerX86 : public ElfLinker
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void align(unsigned modulus, unsigned remainder); virtual void align(unsigned len);
virtual void relocate1(Relocation *, unsigned char *location, virtual void relocate1(Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerArmLE : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void relocate1(Relocation *, upx_byte *location,
unsigned value, const char *type); unsigned value, const char *type);
}; };