Removed all old linker classes - we exclusively use ElfLinker now.

This commit is contained in:
Markus F.X.J. Oberhumer
2006-08-19 14:00:22 +02:00
parent 033e7928b5
commit 03ce7a8db3
9 changed files with 39 additions and 463 deletions
+7 -318
View File
@@ -29,325 +29,12 @@
#include "conf.h"
#include "linker.h"
static int hex(char c)
static int hex(unsigned char c)
{
return (c & 0xf) + (c > '9' ? 9 : 0);
}
/*************************************************************************
//
**************************************************************************/
#define NJUMPS 200
#define NSECTIONS 550
class DefaultLinker::Label
{
char label[31 + 1];
public:
unsigned set(const char *s)
{
size_t len = strlen(s);
assert(len > 0); assert(len <= 31);
strcpy(label, s);
return len + 1;
}
unsigned set(const unsigned char *s) { return set((const char *)s); }
operator const char *() const { return label; }
};
struct DefaultLinker::Jump
{
int pos;
int len;
int toffs;
DefaultLinker::Label tsect;
};
struct DefaultLinker::Section
{
int istart;
int ostart;
int len;
unsigned char align;
DefaultLinker::Label name;
};
DefaultLinker::DefaultLinker() :
iloader(NULL), oloader(NULL), jumps(NULL), sections(NULL)
{
}
void DefaultLinker::init(const void *pdata, int plen, int pinfo)
{
assert(!frozen);
ilen = plen;
iloader = new unsigned char[plen + 8192];
memcpy(iloader, pdata, plen);
oloader = new unsigned char[plen];
olen = 0;
align_hack = 0;
align_offset = 0;
info = pinfo;
njumps = nsections = frozen = 0;
jumps = new Jump[NJUMPS];
sections = new Section[NSECTIONS];
unsigned char *p = iloader + info;
while (get32(p) != (unsigned)(-1))
{
if (get32(p))
{
p += sections[nsections].name.set(p);
sections[nsections].istart = get32(p);
sections[nsections++].ostart = -1;
p += 4;
assert(nsections < NSECTIONS);
}
else
{
int l;
for (l = get32(p+4) - 1; iloader[l] == 0; l--)
;
jumps[njumps].pos = l+1;
jumps[njumps].len = get32(p+4)-jumps[njumps].pos;
p += 8 + jumps[njumps].tsect.set(p + 8);
jumps[njumps++].toffs = get32(p);
p += 4;
assert(njumps < NJUMPS);
}
}
int ic;
for (ic = 0; ic < nsections - 1; ic++)
sections[ic].len = sections[ic+1].istart - sections[ic].istart;
sections[ic].len = 0;
}
DefaultLinker::~DefaultLinker()
{
delete [] iloader;
delete [] oloader;
delete [] jumps;
delete [] sections;
}
void DefaultLinker::setLoaderAlignOffset(int offset)
{
assert(!frozen);
align_offset = offset;
}
int DefaultLinker::addSection(const char *sname)
{
assert(!frozen);
if (sname[0] == 0)
return olen;
char *begin = strdup(sname);
char *end = begin + strlen(begin);
for (char *sect = begin; sect < end; )
{
for (char *tokend = sect; *tokend; tokend++)
if (*tokend == ' ' || *tokend == ',')
{
*tokend = 0;
break;
}
if (*sect == '+') // alignment
{
if (sect[1] == '0')
align_hack = olen + align_offset;
else
{
unsigned j = hex(sect[1]);
j = (hex(sect[2]) - ((olen + align_offset) - align_hack) ) % j;
memset(oloader+olen, (sect[3] == 'C' ? 0x90 : 0), j);
olen += j;
}
}
else
{
int ic;
for (ic = 0; ic < nsections; ic++)
if (strcmp(sect, sections[ic].name) == 0)
{
memcpy(oloader+olen,iloader+sections[ic].istart,sections[ic].len);
sections[ic].ostart = olen;
olen += sections[ic].len;
break;
}
if (ic == nsections) {
printf("%s", sect);
assert(ic != nsections);
}
}
sect += strlen(sect) + 1;
}
free(begin);
return olen;
}
void DefaultLinker::addSection(const char *sname, const void *sdata, int slen, int align)
{
assert(!frozen);
// add a new section - can be used for adding stuff like ident or header
sections[nsections].name.set(sname);
sections[nsections].istart = ilen;
sections[nsections].len = slen;
sections[nsections].align = align;
sections[nsections++].ostart = olen;
assert(nsections < NSECTIONS);
memcpy(iloader+ilen, sdata, slen);
ilen += slen;
}
void DefaultLinker::freeze()
{
if (frozen)
return;
int ic,jc,kc;
for (ic = 0; ic < njumps; ic++)
{
for (jc = 0; jc < nsections-1; jc++)
if (jumps[ic].pos >= sections[jc].istart
&& jumps[ic].pos < sections[jc+1].istart)
break;
assert(jc!=nsections-1);
if (sections[jc].ostart < 0)
continue;
for (kc = 0; kc < nsections-1; kc++)
if (strcmp(jumps[ic].tsect,sections[kc].name) == 0)
break;
assert(kc!=nsections-1);
int offs = sections[kc].ostart+jumps[ic].toffs -
(jumps[ic].pos+jumps[ic].len -
sections[jc].istart+sections[jc].ostart);
if (jumps[ic].len == 1)
assert(-128 <= offs && offs <= 127);
set32(&offs,offs);
memcpy(oloader+sections[jc].ostart+jumps[ic].pos-sections[jc].istart,&offs,jumps[ic].len);
}
frozen = true;
}
int DefaultLinker::getSection(const char *sname, int *slen)
{
assert(frozen);
for (int ic = 0; ic < nsections; ic++)
if (strcmp(sname, sections[ic].name) == 0)
{
if (slen)
*slen = sections[ic].len;
return sections[ic].ostart;
}
return -1;
}
unsigned char *DefaultLinker::getLoader(int *llen)
{
assert(frozen);
if (llen)
*llen = olen;
return oloader;
}
/*************************************************************************
//
**************************************************************************/
SimpleLinker::SimpleLinker() :
oloader(NULL)
{
}
void SimpleLinker::init(const void *pdata, int plen, int pinfo)
{
assert(!frozen);
UNUSED(pinfo);
oloader = new unsigned char[plen];
olen = plen;
memcpy(oloader, pdata, plen);
}
SimpleLinker::~SimpleLinker()
{
delete [] oloader;
}
void SimpleLinker::setLoaderAlignOffset(int offset)
{
assert(!frozen);
UNUSED(offset);
assert(0);
}
int SimpleLinker::addSection(const char *sname)
{
assert(!frozen);
UNUSED(sname);
assert(0);
return -1;
}
void SimpleLinker::addSection(const char *sname, const void *sdata, int slen, int align)
{
assert(!frozen);
UNUSED(sname); UNUSED(sdata); UNUSED(slen); UNUSED(align);
assert(0);
}
void SimpleLinker::freeze()
{
frozen = true;
}
int SimpleLinker::getSection(const char *sname, int *slen)
{
assert(frozen);
UNUSED(sname); UNUSED(slen);
assert(0);
return -1;
}
unsigned char *SimpleLinker::getLoader(int *llen)
{
assert(frozen);
if (llen)
*llen = olen;
return oloader;
}
/*************************************************************************
//
**************************************************************************/
@@ -535,9 +222,11 @@ void ElfLinker::addRelocation(const char *section, unsigned off,
type, findSymbol(symbol), add);
}
ElfLinker::ElfLinker() : input(NULL), output(NULL), head(NULL), tail(NULL),
ElfLinker::ElfLinker() :
frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL),
sections(NULL), symbols(NULL), relocations(NULL)
{}
{
}
ElfLinker::~ElfLinker()
{
@@ -792,7 +481,7 @@ void ElfLinkerX86::relocate1(Relocation *rel, upx_byte *location,
if (strcmp(type, "8") == 0)
{
int displ = (char) *location + (int) value;
int displ = (signed char) *location + (int) value;
if (displ < -127 || displ > 128)
{
printf("target out of range (%d) in reloc %s:%x\n",
@@ -824,7 +513,7 @@ void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location,
if (strcmp(type, "8") == 0)
{
int displ = (char) *location + (int) value;
int displ = (signed char) *location + (int) value;
if (displ < -127 || displ > 128)
{
printf("target out of range (%d) in reloc %s:%x\n",