1 /* linker.h --
2 
3    This file is part of the UPX executable compressor.
4 
5    Copyright (C) 1996-2020 Markus Franz Xaver Johannes Oberhumer
6    Copyright (C) 1996-2020 Laszlo Molnar
7    All Rights Reserved.
8 
9    UPX and the UCL library are free software; you can redistribute them
10    and/or modify them under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2 of
12    the License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; see the file COPYING.
21    If not, write to the Free Software Foundation, Inc.,
22    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24    Markus F.X.J. Oberhumer              Laszlo Molnar
25    <markus@oberhumer.com>               <ezerotven+github@gmail.com>
26  */
27 
28 #ifndef __UPX_LINKER_H
29 #define __UPX_LINKER_H 1
30 
31 /*************************************************************************
32 // ElfLinker
33 **************************************************************************/
34 
35 class ElfLinker : private noncopyable {
36     friend class Packer;
37 
38 public:
39     const N_BELE_RTP::AbstractPolicy *bele; // target endianness
40 protected:
41     struct Section;
42     struct Symbol;
43     struct Relocation;
44 
45     upx_byte *input;
46     int inputlen;
47     upx_byte *output;
48     int outputlen;
49 
50     Section *head;
51     Section *tail;
52 
53     Section **sections;
54     Symbol **symbols;
55     Relocation **relocations;
56 
57     unsigned nsections;
58     unsigned nsections_capacity;
59     unsigned nsymbols;
60     unsigned nsymbols_capacity;
61     unsigned nrelocations;
62     unsigned nrelocations_capacity;
63 
64     bool reloc_done;
65 
66 protected:
67     void preprocessSections(char *start, char *end);
68     void preprocessSymbols(char *start, char *end);
69     void preprocessRelocations(char *start, char *end);
70     Section *findSection(const char *name, bool fatal = true) const;
71     Symbol *findSymbol(const char *name, bool fatal = true) const;
72 
73     Symbol *addSymbol(const char *name, const char *section, upx_uint64_t offset);
74     Relocation *addRelocation(const char *section, unsigned off, const char *type,
75                               const char *symbol, upx_uint64_t add);
76 
77 public:
78     ElfLinker();
79     virtual ~ElfLinker();
80 
81     virtual void init(const void *pdata, int plen);
82     // virtual void setLoaderAlignOffset(int phase);
83     virtual int addLoader(const char *sname);
84     void addLoader(const char *s, va_list ap);
85 #if 1 && (ACC_CC_CLANG || (ACC_CC_GNUC >= 0x040100))
86     void __acc_cdecl_va addLoaderVA(const char *s, ...) __attribute__((__sentinel__));
87 #else
88     void __acc_cdecl_va addLoaderVA(const char *s, ...);
89 #endif
90     virtual Section *addSection(const char *sname, const void *sdata, int slen, unsigned p2align);
91     virtual int getSection(const char *sname, int *slen = NULL) const;
92     virtual int getSectionSize(const char *sname) const;
93     virtual upx_byte *getLoader(int *llen = NULL) const;
94     virtual void defineSymbol(const char *name, upx_uint64_t value);
95     virtual upx_uint64_t getSymbolOffset(const char *) const;
96 
97     virtual void dumpSymbol(const Symbol *, unsigned flags, FILE *fp) const;
98     virtual void dumpSymbols(unsigned flags = 0, FILE *fp = NULL) const;
99 
100     void alignWithByte(unsigned len, unsigned char b);
alignCode(unsigned len)101     virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
alignData(unsigned len)102     virtual void alignData(unsigned len) { alignWithByte(len, 0); }
103 
104 protected:
105     virtual void relocate();
106     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
107                            const char *type);
108 
109     // target endianness abstraction
get_te16(const void * p)110     unsigned get_te16(const void *p) const { return bele->get16(p); }
get_te32(const void * p)111     unsigned get_te32(const void *p) const { return bele->get32(p); }
get_te64(const void * p)112     upx_uint64_t get_te64(const void *p) const { return bele->get64(p); }
set_te16(void * p,unsigned v)113     void set_te16(void *p, unsigned v) const { bele->set16(p, v); }
set_te32(void * p,unsigned v)114     void set_te32(void *p, unsigned v) const { bele->set32(p, v); }
set_te64(void * p,upx_uint64_t v)115     void set_te64(void *p, upx_uint64_t v) const { bele->set64(p, v); }
116 };
117 
118 struct ElfLinker::Section : private noncopyable {
119     char *name;
120     void *input;
121     upx_byte *output;
122     unsigned size;
123     upx_uint64_t offset;
124     unsigned p2align; // log2
125     Section *next;
126 
127     Section(const char *n, const void *i, unsigned s, unsigned a = 0);
128     ~Section();
129 };
130 
131 struct ElfLinker::Symbol : private noncopyable {
132     char *name;
133     Section *section;
134     upx_uint64_t offset;
135 
136     Symbol(const char *n, Section *s, upx_uint64_t o);
137     ~Symbol();
138 };
139 
140 struct ElfLinker::Relocation : private noncopyable {
141     const Section *section;
142     unsigned offset;
143     const char *type;
144     const Symbol *value;
145     upx_uint64_t add; // used in .rela relocations
146 
147     Relocation(const Section *s, unsigned o, const char *t, const Symbol *v, upx_uint64_t a);
148 };
149 
150 /*************************************************************************
151 // ElfLinker arch subclasses
152 **************************************************************************/
153 
154 class ElfLinkerAMD64 : public ElfLinker {
155     typedef ElfLinker super;
156 
157 protected:
alignCode(unsigned len)158     virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
159     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
160                            const char *type);
161 };
162 
163 class ElfLinkerARM64 : public ElfLinker {
164     typedef ElfLinker super;
165 
166 protected:
alignCode(unsigned len)167     virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
168     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
169                            const char *type);
170 };
171 
172 class ElfLinkerArmBE : public ElfLinker {
173     typedef ElfLinker super;
174 
175 public:
ElfLinkerArmBE()176     ElfLinkerArmBE() { bele = &N_BELE_RTP::be_policy; }
177 
178 protected:
179     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
180                            const char *type);
181 };
182 
183 class ElfLinkerArmLE : public ElfLinker {
184     typedef ElfLinker super;
185 
186 protected:
187     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
188                            const char *type);
189 };
190 
191 class ElfLinkerArm64LE : public ElfLinker {
192     typedef ElfLinker super;
193 
194 protected:
195     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
196                            const char *type);
197 };
198 
199 class ElfLinkerM68k : public ElfLinker {
200     typedef ElfLinker super;
201 
202 public:
ElfLinkerM68k()203     ElfLinkerM68k() { bele = &N_BELE_RTP::be_policy; }
204 
205 protected:
206     virtual void alignCode(unsigned len);
207     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
208                            const char *type);
209 };
210 
211 class ElfLinkerMipsBE : public ElfLinker {
212     typedef ElfLinker super;
213 
214 public:
ElfLinkerMipsBE()215     ElfLinkerMipsBE() { bele = &N_BELE_RTP::be_policy; }
216 
217 protected:
218     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
219                            const char *type);
220 };
221 
222 class ElfLinkerMipsLE : public ElfLinker {
223     typedef ElfLinker super;
224 
225 protected:
226     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
227                            const char *type);
228 };
229 
230 class ElfLinkerPpc32 : public ElfLinker {
231     typedef ElfLinker super;
232 
233 public:
ElfLinkerPpc32()234     ElfLinkerPpc32() { bele = &N_BELE_RTP::be_policy; }
235 
236 protected:
237     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
238                            const char *type);
239 };
240 
241 class ElfLinkerPpc64le : public ElfLinker {
242     typedef ElfLinker super;
243 
244 protected:
245     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
246                            const char *type);
247 };
248 
249 class ElfLinkerPpc64 : public ElfLinker {
250     typedef ElfLinker super;
251 
252 public:
ElfLinkerPpc64()253     ElfLinkerPpc64() { bele = &N_BELE_RTP::be_policy; }
254 
255 protected:
256     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
257                            const char *type);
258 };
259 
260 class ElfLinkerX86 : public ElfLinker {
261     typedef ElfLinker super;
262 
263 protected:
alignCode(unsigned len)264     virtual void alignCode(unsigned len) { alignWithByte(len, 0x90); }
265     virtual void relocate1(const Relocation *, upx_byte *location, upx_uint64_t value,
266                            const char *type);
267 };
268 
269 #endif /* already included */
270 
271 /* vim:set ts=4 sw=4 et: */
272