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:
parent
bfc2fab33f
commit
c5fb161477
142
src/linker.cpp
142
src/linker.cpp
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
41
src/linker.h
41
src/linker.h
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user