Some linker.cpp cleanups.

This commit is contained in:
Markus F.X.J. Oberhumer
2006-08-20 11:15:36 +02:00
parent affb926d44
commit 996a99ad75
7 changed files with 224 additions and 211 deletions
+158 -123
View File
@@ -34,6 +34,16 @@ static int hex(unsigned char c)
return (c & 0xf) + (c > '9' ? 9 : 0); return (c & 0xf) + (c > '9' ? 9 : 0);
} }
static bool update_capacity(unsigned size, unsigned *capacity)
{
if (size < *capacity)
return false;
if (*capacity == 0)
*capacity = 16;
while (size >= *capacity)
*capacity *= 2;
return true;
}
/************************************************************************* /*************************************************************************
// //
@@ -65,8 +75,8 @@ ElfLinker::Symbol::~Symbol()
free(name); free(name);
} }
ElfLinker::Relocation::Relocation(Section *s, unsigned o, const char *t, ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t,
Symbol *v, unsigned a) : const Symbol *v, unsigned a) :
section(s), offset(o), type(t), value(v), add(a) section(s), offset(o), type(t), value(v), add(a)
{} {}
@@ -175,7 +185,7 @@ void ElfLinker::preprocessRelocations(char *start, const char *end)
} }
} }
ElfLinker::Section *ElfLinker::findSection(const char *name) ElfLinker::Section *ElfLinker::findSection(const char *name) const
{ {
for (unsigned ic = 0; ic < nsections; ic++) for (unsigned ic = 0; ic < nsections; ic++)
if (strcmp(sections[ic]->name, name) == 0) if (strcmp(sections[ic]->name, name) == 0)
@@ -186,45 +196,51 @@ ElfLinker::Section *ElfLinker::findSection(const char *name)
return NULL; return NULL;
} }
ElfLinker::Symbol *ElfLinker::findSymbol(const char *name) ElfLinker::Symbol *ElfLinker::findSymbol(const char *name) /*const*/
{ {
for (unsigned ic = 0; ic < nsymbols; ic++) for (unsigned ic = 0; ic < nsymbols; ic++)
if (strcmp(symbols[ic]->name, name) == 0) if (strcmp(symbols[ic]->name, name) == 0)
return symbols[ic]; return symbols[ic];
if ('*'==name[0]) { // *ABS* // FIXME: this should be a const method !
addSymbol(name, name, 0); if ('*' == name[0]) // *ABS*
return symbols[nsymbols -1]; return addSymbol(name, name, 0);
}
printf("unknown symbol %s\n", name); printf("unknown symbol %s\n", name);
abort(); abort();
return NULL; return NULL;
} }
void ElfLinker::addSymbol(const char *name, const char *section, ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,
unsigned offset) unsigned offset)
{ {
symbols = static_cast<Symbol **>(realloc(symbols, (nsymbols + 1) if (update_capacity(nsymbols, &nsymbols_capacity))
* sizeof(Symbol *))); symbols = static_cast<Symbol **>(realloc(symbols, nsymbols_capacity * sizeof(Symbol *)));
assert(symbols); assert(symbols != NULL);
symbols[nsymbols++] = new Symbol(name, findSection(section), offset); Symbol *sym = new Symbol(name, findSection(section), offset);
symbols[nsymbols++] = sym;
return sym;
} }
void ElfLinker::addRelocation(const char *section, unsigned off, ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off,
const char *type, const char *symbol, const char *type, const char *symbol,
unsigned add) unsigned add)
{ {
relocations = static_cast<Relocation **>(realloc(relocations, if (update_capacity(nrelocations, &nrelocations_capacity))
(nrelocations + 1) relocations = static_cast<Relocation **>(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));
* sizeof(Relocation *))); assert(relocations != NULL);
assert(relocations); Relocation *rel = new Relocation(findSection(section), off,
relocations[nrelocations++] = new Relocation(findSection(section), off, type, findSymbol(symbol), add);
type, findSymbol(symbol), add); relocations[nrelocations++] = rel;
return rel;
} }
ElfLinker::ElfLinker() : ElfLinker::ElfLinker() :
frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL), frozen(false), input(NULL), output(NULL), head(NULL), tail(NULL),
sections(NULL), symbols(NULL), relocations(NULL) sections(NULL), symbols(NULL), relocations(NULL),
nsections(0), nsections_capacity(0),
nsymbols(0), nsymbols_capacity(0),
nrelocations(0), nrelocations_capacity(0)
{ {
} }
@@ -245,7 +261,7 @@ ElfLinker::~ElfLinker()
free(relocations); free(relocations);
} }
void ElfLinker::init(const void *pdata, int plen, int) void ElfLinker::init(const void *pdata, int plen)
{ {
upx_byte *i = new upx_byte[plen + 1]; upx_byte *i = new upx_byte[plen + 1];
memcpy(i, pdata, plen); memcpy(i, pdata, plen);
@@ -341,10 +357,12 @@ int ElfLinker::addSection(const char *sname)
void ElfLinker::addSection(const char *sname, const void *sdata, int slen, int align) void ElfLinker::addSection(const char *sname, const void *sdata, int slen, int align)
{ {
assert(!frozen); assert(!frozen);
sections = static_cast<Section **>(realloc(sections, (nsections + 1) if (update_capacity(nsections, &nsections_capacity))
* sizeof(Section *))); sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));
assert(sections); assert(sections);
sections[nsections++] = new Section(sname, sdata, slen, align); Section *sec = new Section(sname, sdata, slen, align);
sections[nsections++] = sec;
//return sec;
} }
void ElfLinker::freeze() void ElfLinker::freeze()
@@ -444,62 +462,20 @@ void ElfLinker::align(unsigned len)
alignWithByte(len, 0); alignWithByte(len, 0);
} }
void ElfLinker::relocate1(Relocation *rel, upx_byte *, void ElfLinker::relocate1(const 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 len)
{
alignWithByte(len, 0x90);
}
void ElfLinkerAMD64::align(unsigned len) /*************************************************************************
{ // ElfLinker arch subclasses
alignWithByte(len, 0x90); **************************************************************************/
}
void ElfLinkerPpc32::align(unsigned len) void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,
{ unsigned value, const char *type)
alignWithByte(len, 0);
}
void ElfLinkerX86::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strncmp(type, "R_386_", 6))
return super::relocate1(rel, location, value, type);
type += 6;
if (strncmp(type, "PC", 2) == 0)
{
value -= rel->section->offset + rel->offset;
type += 2;
}
if (strcmp(type, "8") == 0)
{
int displ = (signed char) *location + (int) value;
if (displ < -127 || displ > 128)
{
printf("target out of range (%d) in reloc %s:%x\n",
displ, rel->section->name, rel->offset);
abort();
}
*location += value;
}
else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value);
else if (strcmp(type, "32") == 0)
set_le32(location, get_le32(location) + value);
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{ {
if (strncmp(type, "R_X86_64_", 9)) if (strncmp(type, "R_X86_64_", 9))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
@@ -530,8 +506,90 @@ void ElfLinkerAMD64::relocate1(Relocation *rel, upx_byte *location,
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerPpc32::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type) void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strcmp(type, "R_ARM_PC24") == 0)
{
value -= rel->section->offset + rel->offset;
set_be24(1+ location, get_be24(1+ location) + value / 4);
}
else if (strcmp(type, "R_ARM_ABS32") == 0)
{
set_be32(location, get_be32(location) + value);
}
else if (strcmp(type, "R_ARM_THM_CALL") == 0)
{
value -= rel->section->offset + rel->offset;
value += ((get_be16(location) & 0x7ff) << 12);
value += (get_be16(location + 2) & 0x7ff) << 1;
set_be16(location, 0xf000 + ((value >> 12) & 0x7ff));
set_be16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
//set_be32(location, get_be32(location) + value / 4);
}
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strcmp(type, "R_ARM_PC24") == 0)
{
value -= rel->section->offset + rel->offset;
set_le24(location, get_le24(location) + value / 4);
}
else if (strcmp(type, "R_ARM_ABS32") == 0)
{
set_le32(location, get_le32(location) + value);
}
else if (strcmp(type, "R_ARM_THM_CALL") == 0)
{
value -= rel->section->offset + rel->offset;
value += ((get_le16(location) & 0x7ff) << 12);
value += (get_le16(location + 2) & 0x7ff) << 1;
set_le16(location, 0xf000 + ((value >> 12) & 0x7ff));
set_le16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
//set_le32(location, get_le32(location) + value / 4);
}
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strncmp(type, "R_68K_", 6))
return super::relocate1(rel, location, value, type);
type += 6;
if (strncmp(type, "PC", 2) == 0)
{
value -= rel->section->offset + rel->offset;
type += 2;
}
if (strcmp(type, "8") == 0)
*location += value;
else if (strcmp(type, "16") == 0)
set_be16(location, get_be16(location) + value);
else if (strcmp(type, "32") == 0)
set_be32(location, get_be32(location) + value);
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{ {
if (strncmp(type, "R_PPC_", 6)) if (strncmp(type, "R_PPC_", 6))
return super::relocate1(rel, location, value, type); return super::relocate1(rel, location, value, type);
@@ -568,58 +626,35 @@ void ElfLinkerPpc32::relocate1(Relocation *rel, upx_byte *location,
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
void ElfLinkerArmLE::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type) void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{ {
if (strcmp(type, "R_ARM_PC24") == 0) if (strncmp(type, "R_386_", 6))
return super::relocate1(rel, location, value, type);
type += 6;
if (strncmp(type, "PC", 2) == 0)
{ {
value -= rel->section->offset + rel->offset; value -= rel->section->offset + rel->offset;
set_le24(location, get_le24(location) + value / 4); type += 2;
} }
else if (strcmp(type, "R_ARM_ABS32") == 0)
if (strcmp(type, "8") == 0)
{ {
int displ = (signed char) *location + (int) value;
if (displ < -127 || displ > 128)
{
printf("target out of range (%d) in reloc %s:%x\n",
displ, rel->section->name, rel->offset);
abort();
}
*location += value;
}
else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value);
else if (strcmp(type, "32") == 0)
set_le32(location, get_le32(location) + value); set_le32(location, get_le32(location) + value);
}
else if (strcmp(type, "R_ARM_THM_CALL") == 0)
{
value -= rel->section->offset + rel->offset;
value += ((get_le16(location) & 0x7ff) << 12);
value += (get_le16(location + 2) & 0x7ff) << 1;
set_le16(location, 0xf000 + ((value >> 12) & 0x7ff));
set_le16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
//set_le32(location, get_le32(location) + value / 4);
}
else
super::relocate1(rel, location, value, type);
}
void ElfLinkerArmBE::relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strcmp(type, "R_ARM_PC24") == 0)
{
value -= rel->section->offset + rel->offset;
set_be24(1+ location, get_be24(1+ location) + value / 4);
}
else if (strcmp(type, "R_ARM_ABS32") == 0)
{
set_be32(location, get_be32(location) + value);
}
else if (strcmp(type, "R_ARM_THM_CALL") == 0)
{
value -= rel->section->offset + rel->offset;
value += ((get_be16(location) & 0x7ff) << 12);
value += (get_be16(location + 2) & 0x7ff) << 1;
set_be16(location, 0xf000 + ((value >> 12) & 0x7ff));
set_be16(location + 2, 0xf800 + ((value >> 1) & 0x7ff));
//(b, 0xF000 + ((v - 1) / 2) * 0x10000);
//set_be32(location, get_be32(location) + value / 4);
}
else else
super::relocate1(rel, location, value, type); super::relocate1(rel, location, value, type);
} }
+60 -49
View File
@@ -37,12 +37,12 @@
class ElfLinker : private nocopy class ElfLinker : private nocopy
{ {
protected: protected:
bool frozen; // FIXME: can we remove this ?
struct Section; struct Section;
struct Symbol; struct Symbol;
struct Relocation; struct Relocation;
bool frozen; // FIXME: can we remove this ?
upx_byte *input; upx_byte *input;
int inputlen; int inputlen;
upx_byte *output; upx_byte *output;
@@ -56,24 +56,27 @@ protected:
Relocation **relocations; Relocation **relocations;
unsigned nsections; unsigned nsections;
unsigned nsections_capacity;
unsigned nsymbols; unsigned nsymbols;
unsigned nsymbols_capacity;
unsigned nrelocations; unsigned nrelocations;
unsigned nrelocations_capacity;
void preprocessSections(char *start, const char *end); void preprocessSections(char *start, const char *end);
void preprocessSymbols(char *start, const char *end); void preprocessSymbols(char *start, const char *end);
void preprocessRelocations(char *start, const char *end); void preprocessRelocations(char *start, const char *end);
Section *findSection(const char *name); Section *findSection(const char *name) const;
Symbol *findSymbol(const char *name); Symbol *findSymbol(const char *name) /*const*/;
void addSymbol(const char *name, const char *section, unsigned offset); Symbol *addSymbol(const char *name, const char *section, unsigned offset);
void addRelocation(const char *section, unsigned off, const char *type, Relocation *addRelocation(const char *section, unsigned off, const char *type,
const char *symbol, unsigned add); const char *symbol, unsigned add);
public: public:
ElfLinker(); ElfLinker();
virtual ~ElfLinker(); virtual ~ElfLinker();
virtual void init(const void *pdata, int plen, int); virtual void init(const void *pdata, int plen);
virtual void setLoaderAlignOffset(int phase); virtual void setLoaderAlignOffset(int phase);
virtual int addSection(const char *sname); virtual int addSection(const char *sname);
virtual void addSection(const char *sname, const void *sdata, int slen, int align); virtual void addSection(const char *sname, const void *sdata, int slen, int align);
@@ -86,7 +89,7 @@ public:
void alignWithByte(unsigned len, upx_byte b); void alignWithByte(unsigned len, upx_byte b);
virtual void align(unsigned len); virtual void align(unsigned len);
virtual void relocate1(Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type); unsigned value, const char *type);
}; };
@@ -119,56 +122,27 @@ struct ElfLinker::Symbol : private nocopy
struct ElfLinker::Relocation : private nocopy struct ElfLinker::Relocation : private nocopy
{ {
Section *section; const Section *section;
unsigned offset; unsigned offset;
const char *type; const char *type;
Symbol *value; const Symbol *value;
unsigned add; // used in .rela relocations unsigned add; // used in .rela relocations
Relocation(Section *s, unsigned o, const char *t, Relocation(const Section *s, unsigned o, const char *t,
Symbol *v, unsigned a); const Symbol *v, unsigned a);
}; };
class ElfLinkerX86 : public ElfLinker /*************************************************************************
{ // ElfLinker arch subclasses
typedef ElfLinker super; **************************************************************************/
protected:
virtual void align(unsigned len);
virtual void relocate1(Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerAMD64 : public ElfLinker class ElfLinkerAMD64 : public ElfLinker
{ {
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void align(unsigned len); virtual void align(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerPpc32 : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void align(unsigned len);
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);
}; };
@@ -176,13 +150,50 @@ protected:
class ElfLinkerArmBE : public ElfLinker class ElfLinkerArmBE : public ElfLinker
{ {
typedef ElfLinker super; typedef ElfLinker super;
protected: protected:
virtual void relocate1(Relocation *, upx_byte *location, virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type); unsigned value, const char *type);
}; };
class ElfLinkerArmLE : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerM68k : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerPpc32 : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type);
};
class ElfLinkerX86 : public ElfLinker
{
typedef ElfLinker super;
protected:
virtual void align(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location,
unsigned value, const char *type);
};
#endif /* already included */ #endif /* already included */
-27
View File
@@ -78,33 +78,6 @@ const int *PackTos::getFilters() const
Linker* PackTos::newLinker() const Linker* PackTos::newLinker() const
{ {
class ElfLinkerM68k : public ElfLinker
{
typedef ElfLinker super;
virtual void relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strncmp(type, "R_68K_", 6))
return super::relocate1(rel, location, value, type);
type += 6;
if (strncmp(type, "PC", 2) == 0)
{
value -= rel->section->offset + rel->offset;
type += 2;
}
if (strcmp(type, "8") == 0)
*location += value;
else if (strcmp(type, "16") == 0)
set_be16(location, get_be16(location) + value);
else if (strcmp(type, "32") == 0)
set_be32(location, get_be32(location) + value);
else
super::relocate1(rel, location, value, type);
}
};
return new ElfLinkerM68k; return new ElfLinkerM68k;
} }
+1 -1
View File
@@ -545,7 +545,7 @@ int PackW32Pe::buildLoader(const Filter *ft)
tmp_tlsindex = 0; tmp_tlsindex = 0;
// prepare loader // prepare loader
initLoader(nrv_loader, sizeof(nrv_loader), -1, 2); initLoader(nrv_loader, sizeof(nrv_loader), 2);
addLoader(isdll ? "PEISDLL1" : "", addLoader(isdll ? "PEISDLL1" : "",
"PEMAIN01", "PEMAIN01",
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "", icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
+2 -8
View File
@@ -1046,17 +1046,11 @@ char const *Packer::getIdentstr(unsigned *size, int small) const
} }
void Packer::initLoader(const void *pdata, int plen, int pinfo, int small) void Packer::initLoader(const void *pdata, int plen, int small)
{ {
if (pinfo < 0)
{
pinfo = get_le16((const unsigned char *)pdata + plen - 2);
pinfo = (pinfo + 3) &~ 3;
}
delete linker; delete linker;
linker = newLinker(); linker = newLinker();
linker->init(pdata, plen, pinfo); linker->init(pdata, plen);
unsigned size; unsigned size;
char const * const ident = getIdentstr(&size, small); char const * const ident = getIdentstr(&size, small);
+1 -1
View File
@@ -210,7 +210,7 @@ protected:
virtual upx_byte *getLoader() const; virtual upx_byte *getLoader() const;
virtual int getLoaderSize() const; virtual int getLoaderSize() const;
virtual const char *getIdentstr(unsigned *size, int small=-1) const; virtual const char *getIdentstr(unsigned *size, int small=-1) const;
virtual void initLoader(const void *pdata, int plen, int pinfo=-1, int small=-1); virtual void initLoader(const void *pdata, int plen, int small=-1);
#if 1 && (ACC_CC_GNUC >= 0x040100) #if 1 && (ACC_CC_GNUC >= 0x040100)
virtual void __acc_cdecl_va addLoader(const char *s, ...) __attribute__((__sentinel__)); virtual void __acc_cdecl_va addLoader(const char *s, ...) __attribute__((__sentinel__));
#else #else
+2 -2
View File
@@ -153,8 +153,8 @@ define tc.default.embed_objinfo
$(call tc,m-objcopy) --strip-unneeded $2 $(call tc,m-objcopy) --strip-unneeded $2
$(call tc,m-objcopy) -R .text -R .data -R .bss $2 $(call tc,m-objcopy) -R .text -R .data -R .bss $2
$(call tc,m-objcopy) -R .comment -R .note -R .reginfo $2 $(call tc,m-objcopy) -R .comment -R .note -R .reginfo $2
$(call tc,m-objdump) -trwh $2 > $2.dump $(call tc,m-objdump) -trwh $2 | sed -e 's/[ ]*$$//' > $2.dump
sed -e 's/[ ]*$$//' < $2.dump >> $2 cat $2.dump >> $2
endef endef
# some common settings for $(tc_list) # some common settings for $(tc_list)