Line | Count | Source |
1 | | /* linker.h -- |
2 | | |
3 | | This file is part of the UPX executable compressor. |
4 | | |
5 | | Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer |
6 | | Copyright (C) 1996-2025 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 | | #pragma once |
29 | | |
30 | | /************************************************************************* |
31 | | // ElfLinker |
32 | | **************************************************************************/ |
33 | | |
34 | | class ElfLinker /*not_final*/ : private upx::noncopyable { |
35 | | friend class Packer; |
36 | | |
37 | | public: |
38 | | const N_BELE_RTP::AbstractPolicy *const bele; // target endianness |
39 | | protected: |
40 | | struct Section; |
41 | | struct Symbol; |
42 | | struct Relocation; |
43 | | |
44 | | byte *input = nullptr; |
45 | | int inputlen = 0; |
46 | | byte *output = nullptr; |
47 | | int outputlen = 0; |
48 | | unsigned output_capacity = 0; |
49 | | |
50 | | Section *head = nullptr; |
51 | | Section *tail = nullptr; |
52 | | |
53 | | Section **sections = nullptr; |
54 | | Symbol **symbols = nullptr; |
55 | | Relocation **relocations = nullptr; |
56 | | |
57 | | unsigned nsections = 0; |
58 | | unsigned nsections_capacity = 0; |
59 | | unsigned nsymbols = 0; |
60 | | unsigned nsymbols_capacity = 0; |
61 | | unsigned nrelocations = 0; |
62 | | unsigned nrelocations_capacity = 0; |
63 | | |
64 | | bool reloc_done = false; |
65 | | |
66 | | protected: |
67 | | void preprocessSections(char *start, char const *end); |
68 | | void preprocessSymbols(char *start, char const *end); |
69 | | void preprocessRelocations(char *start, char const *end); |
70 | | Section *findSection(const char *name, bool fatal = true) const; |
71 | | |
72 | | Symbol *addSymbol(const char *name, const char *section, upx_uint64_t offset); |
73 | | Relocation *addRelocation(const char *section, unsigned off, const char *type, |
74 | | const char *symbol, upx_uint64_t add); |
75 | | |
76 | | public: |
77 | | explicit ElfLinker(const N_BELE_RTP::AbstractPolicy *b = &N_BELE_RTP::le_policy) noexcept; |
78 | | virtual ~ElfLinker() noexcept; |
79 | | |
80 | | void init(const void *pdata, int plen, unsigned pxtra = 0); |
81 | | // virtual void setLoaderAlignOffset(int phase); |
82 | | int addLoader(const char *sname); |
83 | | void addLoader(const char *s, va_list ap); |
84 | | #if (ACC_CC_CLANG || ACC_CC_GNUC) |
85 | | void addLoaderVA(const char *s, ...) __attribute__((__sentinel__)); |
86 | | #else |
87 | | void addLoaderVA(const char *s, ...); |
88 | | #endif |
89 | | Section *addSection(const char *sname, const void *sdata, int slen, unsigned p2align); |
90 | | int getSection(const char *sname, int *slen = nullptr) const; |
91 | | int getSectionSize(const char *sname) const; |
92 | | byte *getLoader(int *llen = nullptr) const; |
93 | | void defineSymbol(const char *name, upx_uint64_t value); |
94 | | Symbol *findSymbol(const char *name, bool fatal = true) const; |
95 | | upx_uint64_t getSymbolOffset(const char *) const; |
96 | | |
97 | | void dumpSymbol(const Symbol *, unsigned flags, FILE *fp) const; |
98 | | void dumpSymbols(unsigned flags = 0, FILE *fp = nullptr) const; |
99 | | |
100 | | void alignWithByte(unsigned len, byte b); |
101 | 0 | virtual void alignCode(unsigned len) { alignWithByte(len, 0); } |
102 | 0 | virtual void alignData(unsigned len) { alignWithByte(len, 0); } |
103 | | |
104 | | // provide overloads to pacify GitHub CodeQL |
105 | 0 | void defineSymbol(const char *name, int value) { defineSymbol(name, upx_uint64_t(value)); } |
106 | 0 | void defineSymbol(const char *name, unsigned value) { defineSymbol(name, upx_uint64_t(value)); } |
107 | 0 | void defineSymbol(const char *name, unsigned long value) { |
108 | 0 | defineSymbol(name, upx_uint64_t(value)); |
109 | 0 | } |
110 | | |
111 | | protected: |
112 | | void relocate(); |
113 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
114 | | const char *type); |
115 | | }; |
116 | | |
117 | | struct ElfLinker::Section final : private upx::noncopyable { |
118 | | char *name = nullptr; |
119 | | void *input = nullptr; |
120 | | byte *output = nullptr; |
121 | | unsigned size = 0; |
122 | | unsigned sort_id = 0; // for qsort() |
123 | | upx_uint64_t offset = 0; |
124 | | unsigned p2align = 0; // log2 |
125 | | Section *next = nullptr; |
126 | | |
127 | | explicit Section(const char *n, const void *i, unsigned s, unsigned a = 0); |
128 | | ~Section() noexcept; |
129 | | }; |
130 | | |
131 | | struct ElfLinker::Symbol final : private upx::noncopyable { |
132 | | char *name = nullptr; |
133 | | Section *section = nullptr; |
134 | | upx_uint64_t offset = 0; |
135 | | |
136 | | explicit Symbol(const char *n, Section *s, upx_uint64_t o); |
137 | | ~Symbol() noexcept; |
138 | | }; |
139 | | |
140 | | struct ElfLinker::Relocation final : private upx::noncopyable { |
141 | | const Section *section = nullptr; |
142 | | unsigned offset = 0; |
143 | | const char *type = nullptr; |
144 | | const Symbol *value = nullptr; |
145 | | upx_uint64_t add = 0; // used in .rela relocations |
146 | | |
147 | | explicit Relocation(const Section *s, unsigned o, const char *t, const Symbol *v, |
148 | | upx_uint64_t a); |
149 | 0 | ~Relocation() noexcept {} |
150 | | }; |
151 | | |
152 | | /************************************************************************* |
153 | | // ElfLinker arch subclasses |
154 | | **************************************************************************/ |
155 | | |
156 | | class ElfLinkerAMD64 /*not_final*/ : public ElfLinker { |
157 | | typedef ElfLinker super; |
158 | | protected: |
159 | 0 | virtual void alignCode(unsigned len) override { alignWithByte(len, 0x90); } |
160 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
161 | | const char *type) override; |
162 | | }; |
163 | | |
164 | | class ElfLinkerArm64LE final : public ElfLinker { |
165 | | typedef ElfLinker super; |
166 | | protected: |
167 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
168 | | const char *type) override; |
169 | | }; |
170 | | |
171 | | class ElfLinkerArmBE final : public ElfLinker { |
172 | | typedef ElfLinker super; |
173 | | public: |
174 | 0 | explicit ElfLinkerArmBE() noexcept : super(&N_BELE_RTP::be_policy) {} |
175 | | protected: |
176 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
177 | | const char *type) override; |
178 | | }; |
179 | | |
180 | | class ElfLinkerArmLE final : public ElfLinker { |
181 | | typedef ElfLinker super; |
182 | | protected: |
183 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
184 | | const char *type) override; |
185 | | }; |
186 | | |
187 | | class ElfLinkerM68k final : public ElfLinker { |
188 | | typedef ElfLinker super; |
189 | | public: |
190 | 0 | explicit ElfLinkerM68k() noexcept : super(&N_BELE_RTP::be_policy) {} |
191 | | protected: |
192 | | virtual void alignCode(unsigned len) override; |
193 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
194 | | const char *type) override; |
195 | | }; |
196 | | |
197 | | class ElfLinkerMipsBE final : public ElfLinker { |
198 | | typedef ElfLinker super; |
199 | | public: |
200 | 0 | explicit ElfLinkerMipsBE() noexcept : super(&N_BELE_RTP::be_policy) {} |
201 | | protected: |
202 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
203 | | const char *type) override; |
204 | | }; |
205 | | |
206 | | class ElfLinkerMipsLE final : public ElfLinker { |
207 | | typedef ElfLinker super; |
208 | | protected: |
209 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
210 | | const char *type) override; |
211 | | }; |
212 | | |
213 | | class ElfLinkerPpc32 final : public ElfLinker { |
214 | | typedef ElfLinker super; |
215 | | public: |
216 | 0 | explicit ElfLinkerPpc32() noexcept : super(&N_BELE_RTP::be_policy) {} |
217 | | protected: |
218 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
219 | | const char *type) override; |
220 | | }; |
221 | | |
222 | | class ElfLinkerPpc64 final : public ElfLinker { |
223 | | typedef ElfLinker super; |
224 | | public: |
225 | 0 | explicit ElfLinkerPpc64() noexcept : super(&N_BELE_RTP::be_policy) {} |
226 | | protected: |
227 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
228 | | const char *type) override; |
229 | | }; |
230 | | |
231 | | class ElfLinkerPpc64le final : public ElfLinker { |
232 | | typedef ElfLinker super; |
233 | | protected: |
234 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
235 | | const char *type) override; |
236 | | }; |
237 | | |
238 | | class ElfLinkerX86 final : public ElfLinker { |
239 | | typedef ElfLinker super; |
240 | | protected: |
241 | 0 | virtual void alignCode(unsigned len) override { alignWithByte(len, 0x90); } |
242 | | virtual void relocate1(const Relocation *, byte *location, upx_uint64_t value, |
243 | | const char *type) override; |
244 | | }; |
245 | | |
246 | | /* vim:set ts=4 sw=4 et: */ |