Files
upx/src/linker.h
T
2021-01-05 22:03:29 +01:00

272 lines
8.5 KiB
C++

/* linker.h --
This file is part of the UPX executable compressor.
Copyright (C) 1996-2021 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2021 Laszlo Molnar
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#ifndef __UPX_LINKER_H
#define __UPX_LINKER_H 1
/*************************************************************************
// ElfLinker
**************************************************************************/
class ElfLinker : private noncopyable {
friend class Packer;
public:
const N_BELE_RTP::AbstractPolicy *bele = nullptr; // target endianness
protected:
struct Section;
struct Symbol;
struct Relocation;
upx_byte *input = nullptr;
int inputlen = 0;
upx_byte *output = nullptr;
int outputlen = 0;
Section *head = nullptr;
Section *tail = nullptr;
Section **sections = nullptr;
Symbol **symbols = nullptr;
Relocation **relocations = nullptr;
unsigned nsections = 0;
unsigned nsections_capacity = 0;
unsigned nsymbols = 0;
unsigned nsymbols_capacity = 0;
unsigned nrelocations = 0;
unsigned nrelocations_capacity = 0;
bool reloc_done = false;
protected:
void preprocessSections(char *start, char *end);
void preprocessSymbols(char *start, char *end);
void preprocessRelocations(char *start, char *end);
Section *findSection(const char *name, bool fatal = true) const;
Symbol *findSymbol(const char *name, bool fatal = true) const;
Symbol *addSymbol(const char *name, const char *section, upx_uint64_t offset);
Relocation *addRelocation(const char *section, unsigned off, const char *type,
const char *symbol, upx_uint64_t add);
public:
ElfLinker();
virtual ~ElfLinker();
virtual void init(const void *pdata, int plen);
// virtual void setLoaderAlignOffset(int phase);
virtual int addLoader(const char *sname);
void addLoader(const char *s, va_list ap);
#if (ACC_CC_CLANG || ACC_CC_GNUC)
void addLoaderVA(const char *s, ...) __attribute__((__sentinel__));
#else
void addLoaderVA(const char *s, ...);
#endif
virtual Section *addSection(const char *sname, const void *sdata, int slen, unsigned p2align);
virtual int getSection(const char *sname, int *slen = nullptr) const;
virtual int getSectionSize(const char *sname) const;
virtual upx_byte *getLoader(int *llen = nullptr) const;
virtual void defineSymbol(const char *name, upx_uint64_t value);
virtual upx_uint64_t getSymbolOffset(const char *) const;
virtual void dumpSymbol(const Symbol *, unsigned flags, FILE *fp) const;
virtual void dumpSymbols(unsigned flags = 0, FILE *fp = nullptr) const;
void alignWithByte(unsigned len, unsigned char b);
virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
virtual void alignData(unsigned len) { alignWithByte(len, 0); }
protected:
virtual void relocate();
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
// target endianness abstraction
unsigned get_te16(const void *p) const { return bele->get16(p); }
unsigned get_te32(const void *p) const { return bele->get32(p); }
upx_uint64_t get_te64(const void *p) const { return bele->get64(p); }
void set_te16(void *p, unsigned v) const { bele->set16(p, v); }
void set_te32(void *p, unsigned v) const { bele->set32(p, v); }
void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
};
struct ElfLinker::Section : private noncopyable {
char *name = nullptr;
void *input = nullptr;
upx_byte *output = nullptr;
unsigned size = 0;
upx_uint64_t offset = 0;
unsigned p2align = 0; // log2
Section *next = nullptr;
Section(const char *n, const void *i, unsigned s, unsigned a = 0);
~Section();
};
struct ElfLinker::Symbol : private noncopyable {
char *name = nullptr;
Section *section = nullptr;
upx_uint64_t offset = 0;
Symbol(const char *n, Section *s, upx_uint64_t o);
~Symbol();
};
struct ElfLinker::Relocation : private noncopyable {
const Section *section = nullptr;
unsigned offset = 0;
const char *type = nullptr;
const Symbol *value = nullptr;
upx_uint64_t add; // used in .rela relocations
Relocation(const Section *s, unsigned o, const char *t, const Symbol *v, upx_uint64_t a);
};
/*************************************************************************
// ElfLinker arch subclasses
**************************************************************************/
class ElfLinkerAMD64 : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerARM64 : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerArmBE : public ElfLinker {
typedef ElfLinker super;
public:
ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; }
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerArmLE : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerArm64LE : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerM68k : public ElfLinker {
typedef ElfLinker super;
public:
ElfLinkerM68k() { bele = &N_BELE_RTP::be_policy; }
protected:
virtual void alignCode(unsigned len);
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerMipsBE : public ElfLinker {
typedef ElfLinker super;
public:
ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; }
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerMipsLE : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerPpc32 : public ElfLinker {
typedef ElfLinker super;
public:
ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; }
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerPpc64le : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerPpc64 : public ElfLinker {
typedef ElfLinker super;
public:
ElfLinkerPpc64() { bele = &N_BELE_RTP::be_policy; }
protected:
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
class ElfLinkerX86 : public ElfLinker {
typedef ElfLinker super;
protected:
virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
const char *type);
};
#endif /* already included */
/* vim:set ts=4 sw=4 et: */