Line | Count | Source |
1 | | /* p_lx_elf.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 | | Copyright (C) 2000-2025 John F. Reiser |
8 | | All Rights Reserved. |
9 | | |
10 | | UPX and the UCL library are free software; you can redistribute them |
11 | | and/or modify them under the terms of the GNU General Public License as |
12 | | published by the Free Software Foundation; either version 2 of |
13 | | the License, or (at your option) any later version. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, |
16 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | GNU General Public License for more details. |
19 | | |
20 | | You should have received a copy of the GNU General Public License |
21 | | along with this program; see the file COPYING. |
22 | | If not, write to the Free Software Foundation, Inc., |
23 | | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
24 | | |
25 | | Markus F.X.J. Oberhumer Laszlo Molnar |
26 | | <markus@oberhumer.com> <ezerotven+github@gmail.com> |
27 | | |
28 | | John F. Reiser |
29 | | <jreiser@users.sourceforge.net> |
30 | | */ |
31 | | |
32 | | |
33 | | #pragma once |
34 | | #ifndef __UPX_P_LX_ELF_H //{ |
35 | | #define __UPX_P_LX_ELF_H 1 |
36 | | |
37 | | typedef upx_uint32_t u32_t; // easier to type; more narrow |
38 | | typedef upx_uint64_t u64_t; // easier to type; more narrow |
39 | | |
40 | | class PackLinuxElf : public PackUnix |
41 | | { |
42 | | typedef PackUnix super; |
43 | | public: |
44 | | PackLinuxElf(InputFile *f); |
45 | | virtual ~PackLinuxElf(); |
46 | | /*virtual void buildLoader(const Filter *);*/ |
47 | 236k | virtual int getVersion() const override { return 14; } // upx-3.96 cannot unpack, for instance |
48 | 6.34k | virtual bool canUnpackVersion(int version) const override { return (version >= 11); } |
49 | 7.50k | virtual tribool canUnpack() override { return super::canUnpack(); } // bool, except -1: format known, but not packed |
50 | | |
51 | | protected: |
52 | | virtual const int *getCompressionMethods(int method, int level) const override; |
53 | | |
54 | | // All other virtual functions in this class must be pure virtual |
55 | | // because they depend on Elf32 or Elf64 data structures, which differ. |
56 | | |
57 | | virtual void pack1(OutputFile *, Filter &) override = 0; // generate executable header |
58 | | virtual int pack2(OutputFile *, Filter &) override = 0; // append compressed data |
59 | | virtual off_t pack3(OutputFile *, Filter &) override = 0; // append loader |
60 | | //virtual void pack4(OutputFile *, Filter &) override = 0; // append pack header |
61 | | |
62 | | virtual unsigned pack2_shlib_overlay_init(OutputFile *fo); |
63 | | virtual unsigned pack2_shlib_overlay_compress(MemBuffer &obuf, |
64 | | upx_byte const *inp, unsigned u_len); |
65 | | virtual unsigned pack2_shlib_overlay_write(OutputFile *fo, MemBuffer &obuf, |
66 | | unsigned hdr_u_len, unsigned hdr_c_len); |
67 | | |
68 | | virtual void generateElfHdr( |
69 | | OutputFile *, |
70 | | void const *proto, |
71 | | unsigned const brka |
72 | | ) = 0; |
73 | | virtual void defineSymbols(Filter const *); |
74 | | virtual void addStubEntrySections(Filter const *, unsigned m_decompr); |
75 | | virtual void unpack(OutputFile *fo) override; |
76 | | unsigned old_data_off, old_data_len; // un_shlib |
77 | | |
78 | | virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const = 0; |
79 | | static unsigned elf_hash(char const *) /*const*/; |
80 | | static unsigned gnu_hash(char const *) /*const*/; |
81 | | |
82 | | protected: |
83 | | static unsigned int const asl_delta = (1u<<12); // --android-shlib extra page |
84 | | unsigned e_type; |
85 | | unsigned e_phnum; /* Program header table entry count */ |
86 | | unsigned e_shnum; |
87 | | unsigned e_shstrndx; |
88 | | MemBuffer file_image; // if ET_DYN investigation |
89 | | MemBuffer lowmem; // at least including PT_LOAD[0] |
90 | | MemBuffer mb_shdr; // Shdr might not be near Phdr |
91 | | MemBuffer mb_dt_offsets; // file offset of various DT_ tables |
92 | | unsigned *dt_offsets; // index by dt_table[] |
93 | | unsigned symnum_max; |
94 | | unsigned strtab_max; |
95 | | char const *dynstr; // from DT_STRTAB |
96 | | |
97 | | unsigned sz_phdrs; // sizeof Phdr[] |
98 | | unsigned sz_elf_hdrs; // all Elf headers |
99 | | unsigned sz_pack2; // after pack2(), before loader |
100 | | unsigned sz_pack2a; // after pack2() of all PT_LOAD |
101 | | unsigned lg2_page; // log2(PAGE_SIZE) |
102 | | unsigned page_size; // 1u<<lg2_page |
103 | | bool is_pie; // is Position-Independent-Executable (ET_DYN main program) |
104 | | unsigned is_asl; // is Android Shared Library |
105 | | unsigned xct_off; // shared library: file offset of SHT_EXECINSTR |
106 | | unsigned hatch_off; // file offset of escape hatch |
107 | | unsigned o_binfo; // offset to first b_info |
108 | | upx_off_t so_slide; |
109 | | upx_uint64_t load_va; // PT_LOAD[0].p_vaddr |
110 | | upx_uint64_t xct_va; // minimum SHT_EXECINSTR virtual address |
111 | | upx_uint64_t jni_onload_va; // runtime &JNI_OnLoad |
112 | | upx_uint64_t user_init_va; |
113 | | void *user_init_rp; // Elf32_Rel *, Elf64_Rela *, ... |
114 | | upx_uint64_t plt_va, plt_off; |
115 | | unsigned user_init_off; // within file_image |
116 | | unsigned linfo_off; |
117 | | unsigned loader_offset; // during de-compression |
118 | | |
119 | | upx_uint16_t e_machine; |
120 | | unsigned char ei_class; |
121 | | unsigned char ei_data; |
122 | | unsigned char ei_osabi; |
123 | | unsigned char prev_method; |
124 | | char const *osabi_note; |
125 | | unsigned upx_dt_init; // DT_INIT, DT_PREINIT_ARRAY, DT_INIT_ARRAY |
126 | | static unsigned const DT_NUM = 34; // elf.h |
127 | | unsigned dt_table[DT_NUM]; // 1+ index of DT_xxxxx in PT_DYNAMIC |
128 | | |
129 | | MemBuffer mb_shstrtab; // via ElfXX_Shdr |
130 | | char const *shstrtab; |
131 | | MemBuffer jump_slots; // is_asl de-compression fixing |
132 | | MemBuffer buildid_data; |
133 | | MemBuffer note_body; // concatenated contents of PT_NOTEs, if any |
134 | | unsigned note_size; // total size of PT_NOTEs |
135 | | int o_elf_shnum; // num output Shdrs |
136 | | static const unsigned char o_shstrtab[]; |
137 | | }; |
138 | | |
139 | | class PackLinuxElf32 : public PackLinuxElf |
140 | | { |
141 | | typedef PackLinuxElf super; |
142 | | public: |
143 | | PackLinuxElf32(InputFile *f); |
144 | | virtual ~PackLinuxElf32(); |
145 | | protected: |
146 | | virtual void PackLinuxElf32help1(InputFile *f); |
147 | | virtual int checkEhdr(Elf32_Ehdr const *ehdr) const; |
148 | | virtual bool canPackOSABI(Elf32_Ehdr const *); |
149 | | virtual tribool canPack() override; |
150 | | virtual tribool canUnpack() override; // bool, except -1: format known, but not packed |
151 | | |
152 | | // These ARM routines are essentially common to big/little endian, |
153 | | // but the class hierarchy splits after this class. |
154 | | virtual void ARM_defineSymbols(Filter const *ft); |
155 | | virtual void ARM_updateLoader(OutputFile *); |
156 | | virtual int ARM_is_QNX(void); |
157 | | |
158 | | virtual upx_uint64_t canPack_Shdr(Elf32_Phdr const *pload_x0); |
159 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
160 | | virtual void asl_pack2_Shdrs(OutputFile *, unsigned pre_xct_top); // AndroidSharedLibrary processes Shdrs |
161 | | virtual void asl_slide_Shdrs(); // by so_slide if above xct_off |
162 | | virtual unsigned slide_sh_offset(Elf32_Shdr *shdr); |
163 | | virtual int pack2(OutputFile *, Filter &) override; // append compressed data |
164 | | virtual int pack2_shlib(OutputFile *fo, Filter &ft, unsigned pre_xct_top); |
165 | | virtual off_t pack3(OutputFile *, Filter &) override; // append loader |
166 | | virtual void pack4(OutputFile *, Filter &) override; // append pack header |
167 | | virtual unsigned forward_Shdrs(OutputFile *fo, Elf32_Ehdr *ehdro); |
168 | | virtual void unpack(OutputFile *fo) override; |
169 | | virtual void un_asl_dynsym(unsigned orig_file_size, OutputFile *); |
170 | | virtual void un_shlib_1( |
171 | | OutputFile *const fo, |
172 | | MemBuffer &o_elfhdrs, |
173 | | unsigned &c_adler, |
174 | | unsigned &u_adler, |
175 | | unsigned const orig_file_size |
176 | | ); |
177 | | virtual void un_DT_INIT( |
178 | | unsigned old_dtinit, |
179 | | Elf32_Phdr const *phdro, |
180 | | Elf32_Phdr const *dynhdr, // in phdri |
181 | | OutputFile *fo |
182 | | ); |
183 | | virtual void unRel32(unsigned dt_rel, Elf32_Rel *rel0, unsigned relsz, |
184 | | MemBuffer &membuf, unsigned const load_off, OutputFile *fo); |
185 | | |
186 | | virtual void generateElfHdr( |
187 | | OutputFile *, |
188 | | void const *proto, |
189 | | unsigned const brka |
190 | | ) override; |
191 | | virtual void defineSymbols(Filter const *) override; |
192 | | virtual void buildLinuxLoader( |
193 | | upx_byte const *const proto, // assembly-only sections |
194 | | unsigned const szproto, |
195 | | upx_byte const *const fold, // linked assembly + C section |
196 | | unsigned const szfold, |
197 | | Filter const *ft |
198 | | ); |
199 | | virtual off_t getbrk(const Elf32_Phdr *phdr, int e_phnum) const; |
200 | | virtual void patchLoader() override; |
201 | | virtual void updateLoader(OutputFile *fo) override; |
202 | | virtual unsigned find_LOAD_gap(Elf32_Phdr const *const phdri, unsigned const k, |
203 | | unsigned const e_phnum); |
204 | | virtual off_t getbase(const Elf32_Phdr *phdr, int e_phnum) const; |
205 | | bool calls_crt1(Elf32_Rel const *rel, int sz); |
206 | | |
207 | | virtual Elf32_Sym const *elf_lookup(char const *) const; |
208 | | virtual unsigned elf_get_offset_from_address(unsigned) const; |
209 | | virtual unsigned elf_get_offset_from_Phdrs(unsigned, Elf32_Phdr const *phdr0) const; |
210 | | virtual Elf32_Phdr const *elf_find_Phdr_for_va(unsigned addr, Elf32_Phdr const *phdr, unsigned phnum); |
211 | | Elf32_Phdr const *elf_find_ptype(unsigned type, Elf32_Phdr const *phdr0, unsigned phnum); |
212 | | Elf32_Shdr const *elf_find_section_name(char const *) const; |
213 | | Elf32_Shdr *elf_find_section_type(unsigned) const; |
214 | | Elf32_Dyn *elf_find_dynptr(unsigned) const; |
215 | | unsigned elf_find_table_size(unsigned dt_type, unsigned sh_type); |
216 | | void sort_DT32_offsets(Elf32_Dyn const *const dynp0); |
217 | | |
218 | | int is_LOAD(Elf32_Phdr const *phdr) const; // beware confusion with (1+ LO_PROC) |
219 | | unsigned check_pt_load(Elf32_Phdr const *); |
220 | | unsigned check_pt_dynamic(Elf32_Phdr const *); |
221 | | void invert_pt_dynamic(Elf32_Dyn const *, unsigned dt_filesz); |
222 | | void *elf_find_dynamic(unsigned) const; |
223 | | Elf32_Dyn const *elf_has_dynamic(unsigned) const; |
224 | | virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const override; |
225 | | unsigned find_dt_ndx(unsigned rva); |
226 | | virtual int adjABS(Elf32_Sym *sym, unsigned delta); |
227 | | void add_phdrx(Elf32_Phdr const *); |
228 | | |
229 | | char const *get_str_name(unsigned st_name, unsigned symnum) const; |
230 | | char const *get_dynsym_name(unsigned symnum, unsigned relnum) const; |
231 | | protected: |
232 | | Elf32_Ehdr ehdri; // from input file |
233 | | Elf32_Phdr *phdri; // for input file |
234 | | Elf32_Shdr *shdri; // from input file |
235 | | Elf32_Shdr *shdro; // for output file |
236 | | static unsigned const END_PHDRX = 5; |
237 | | Elf32_Phdr const *phdrx[END_PHDRX]; // "extra" arch-specific Phdr |
238 | | unsigned n_phdrx; // number actually used |
239 | | unsigned sz_phdrx; // total size of bodies |
240 | | unsigned e_phoff; |
241 | | unsigned e_shoff; |
242 | | unsigned sz_dynseg; // PT_DYNAMIC.p_memsz |
243 | | unsigned n_jmp_slot; |
244 | | unsigned plt_off; |
245 | | unsigned page_mask; // AND clears the offset-within-page |
246 | | |
247 | | Elf32_Dyn *dynseg; // from PT_DYNAMIC |
248 | | unsigned int const *hashtab, *hashend; // from DT_HASH |
249 | | unsigned int const *gashtab, *gashend; // from DT_GNU_HASH |
250 | | Elf32_Sym *dynsym; // DT_SYMTAB; 'const' except [0] for decompressor |
251 | | Elf32_Sym const *jni_onload_sym; |
252 | | |
253 | | Elf32_Shdr *sec_strndx; |
254 | | Elf32_Shdr const *sec_dynsym; |
255 | | Elf32_Shdr const *sec_dynstr; |
256 | | Elf32_Shdr *sec_arm_attr; // SHT_ARM_ATTRIBUTES; |
257 | | |
258 | | packed_struct(cprElfHdr1) { |
259 | | Elf32_Ehdr ehdr; |
260 | | Elf32_Phdr phdr[1]; |
261 | | l_info linfo; |
262 | | }; |
263 | | |
264 | | packed_struct(cprElfHdr2) { |
265 | | Elf32_Ehdr ehdr; |
266 | | Elf32_Phdr phdr[2]; |
267 | | l_info linfo; |
268 | | }; |
269 | | |
270 | | packed_struct(cprElfHdr3) { |
271 | | Elf32_Ehdr ehdr; |
272 | | Elf32_Phdr phdr[3]; |
273 | | l_info linfo; |
274 | | }; |
275 | | |
276 | | packed_struct(cprElfHdr4) { |
277 | | Elf32_Ehdr ehdr; |
278 | | Elf32_Phdr phdr[4]; |
279 | | l_info linfo; |
280 | | }; |
281 | | |
282 | | packed_struct(cprElfHdrNetBSD) { |
283 | | Elf32_Ehdr ehdr; |
284 | | Elf32_Phdr phdr[4]; |
285 | | unsigned char notes[512]; |
286 | | }; |
287 | | |
288 | | cprElfHdrNetBSD elfout; |
289 | | |
290 | | packed_struct(cprElfShdr3) { |
291 | | Elf32_Shdr shdr[3]; |
292 | | }; |
293 | | |
294 | | cprElfShdr3 shdrout; |
295 | | |
296 | | struct Elf32_Nhdr { |
297 | | unsigned namesz; |
298 | | unsigned descsz; |
299 | | unsigned type; |
300 | | //unsigned char body[0]; |
301 | | }; |
302 | | |
303 | 0 | static void compileTimeAssertions() { |
304 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr1) == 52 + 1*32 + 12) |
305 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr2) == 52 + 2*32 + 12) |
306 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr3) == 52 + 3*32 + 12) |
307 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdrNetBSD) == 52 + 4*32 + 512) |
308 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr1) |
309 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr2) |
310 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr3) |
311 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdrNetBSD) |
312 | 0 | } |
313 | | }; |
314 | | |
315 | | |
316 | | class PackLinuxElf64 : public PackLinuxElf |
317 | | { |
318 | | typedef PackLinuxElf super; |
319 | | public: |
320 | | PackLinuxElf64(InputFile *f); |
321 | | virtual ~PackLinuxElf64(); |
322 | | /*virtual void buildLoader(const Filter *);*/ |
323 | | |
324 | | protected: |
325 | | virtual void PackLinuxElf64help1(InputFile *f); |
326 | | virtual int checkEhdr(Elf64_Ehdr const *ehdr) const; |
327 | | virtual tribool canPack() override; |
328 | | virtual tribool canUnpack() override; // bool, except -1: format known, but not packed |
329 | | |
330 | | virtual upx_uint64_t canPack_Shdr(Elf64_Phdr const *pload_x0); |
331 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
332 | | virtual void asl_pack2_Shdrs(OutputFile *, unsigned pre_xct_top); // AndroidSharedLibrary processes Shdrs |
333 | | virtual void asl_slide_Shdrs(); // by so_slide if above xct_off |
334 | | virtual unsigned slide_sh_offset(Elf64_Shdr *shdr); |
335 | | virtual int pack2(OutputFile *, Filter &) override; // append compressed data |
336 | | virtual int pack2_shlib(OutputFile *fo, Filter &ft, unsigned pre_xct_top); |
337 | | virtual off_t pack3(OutputFile *, Filter &) override; // append loader |
338 | | virtual void pack4(OutputFile *, Filter &) override; // append pack header |
339 | | virtual unsigned forward_Shdrs(OutputFile *fo, Elf64_Ehdr *ehdro); |
340 | | virtual void unpack(OutputFile *fo) override; |
341 | | virtual void un_asl_dynsym(unsigned orig_file_size, OutputFile *); |
342 | | virtual void un_shlib_1( |
343 | | OutputFile *const fo, |
344 | | MemBuffer &o_elfhdrs, |
345 | | unsigned &c_adler, |
346 | | unsigned &u_adler, |
347 | | unsigned const orig_file_size |
348 | | ); |
349 | | virtual void un_DT_INIT( |
350 | | unsigned old_dtinit, |
351 | | Elf64_Phdr const *phdro, |
352 | | Elf64_Phdr const *dynhdr, // in phdri |
353 | | OutputFile *fo |
354 | | ); |
355 | | virtual void unRela64(upx_uint64_t dt_rela, Elf64_Rela *rela0, unsigned relasz, |
356 | | upx_uint64_t const old_dtinit, OutputFile *fo); |
357 | | |
358 | | virtual void generateElfHdr( |
359 | | OutputFile *, |
360 | | void const *proto, |
361 | | unsigned const brka |
362 | | ) override; |
363 | | virtual void defineSymbols(Filter const *) override; |
364 | | virtual void buildLinuxLoader( |
365 | | upx_byte const *const proto, // assembly-only sections |
366 | | unsigned const szproto, |
367 | | upx_byte const *const fold, // linked assembly + C section |
368 | | unsigned const szfold, |
369 | | Filter const *ft |
370 | | ); |
371 | | virtual off_t getbrk(const Elf64_Phdr *phdr, int e_phnum) const; |
372 | | virtual void patchLoader() override; |
373 | | virtual void updateLoader(OutputFile *fo) override; |
374 | | virtual unsigned find_LOAD_gap(Elf64_Phdr const *const phdri, unsigned const k, |
375 | | unsigned const e_phnum); |
376 | | bool calls_crt1(Elf64_Rela const *rela, int sz); |
377 | | |
378 | | virtual Elf64_Sym const *elf_lookup(char const *) const; |
379 | | virtual upx_uint64_t elf_get_offset_from_address(upx_uint64_t) const; |
380 | | virtual Elf64_Phdr const *elf_find_Phdr_for_va(upx_uint64_t addr, Elf64_Phdr const *phdr, unsigned phnum); |
381 | | Elf64_Phdr const *elf_find_ptype(unsigned type, Elf64_Phdr const *phdr0, unsigned phnum); |
382 | | Elf64_Shdr const *elf_find_section_name(char const *) const; |
383 | | Elf64_Shdr *elf_find_section_type(unsigned) const; |
384 | | Elf64_Dyn *elf_find_dynptr(unsigned) const; |
385 | | unsigned elf_find_table_size(unsigned dt_type, unsigned sh_type); |
386 | | void sort_DT64_offsets(Elf64_Dyn const *const dynp0); |
387 | | int is_LOAD(Elf64_Phdr const *phdr) const; // beware confusion with (1+ LO_PROC) |
388 | | upx_uint64_t check_pt_load(Elf64_Phdr const *); |
389 | | upx_uint64_t check_pt_dynamic(Elf64_Phdr const *); |
390 | | void invert_pt_dynamic(Elf64_Dyn const *, upx_uint64_t dt_filesz); |
391 | | void *elf_find_dynamic(unsigned) const; |
392 | | Elf64_Dyn const *elf_has_dynamic(unsigned) const; |
393 | | virtual upx_uint64_t elf_unsigned_dynamic(unsigned) const override; |
394 | | unsigned find_dt_ndx(u64_t rva); |
395 | | virtual int adjABS(Elf64_Sym *sym, unsigned long delta); |
396 | | void add_phdrx(Elf64_Phdr const *); |
397 | | |
398 | | char const *get_str_name(unsigned st_name, unsigned symnum) const; |
399 | | char const *get_dynsym_name(unsigned symnum, unsigned relnum) const; |
400 | | protected: |
401 | | Elf64_Ehdr ehdri; // from input file |
402 | | Elf64_Phdr *phdri; // for input file |
403 | | Elf64_Shdr *shdri; // from input file |
404 | | Elf64_Shdr *shdro; // for output file |
405 | | static unsigned const END_PHDRX = 5; |
406 | | Elf64_Phdr const *phdrx[END_PHDRX]; // "extra" arch-specific Phdr |
407 | | unsigned n_phdrx; // number actually used |
408 | | unsigned sz_phdrx; // total size of bodies |
409 | | upx_uint64_t e_phoff; |
410 | | upx_uint64_t e_shoff; |
411 | | upx_uint64_t sz_dynseg; // PT_DYNAMIC.p_memsz |
412 | | unsigned n_jmp_slot; |
413 | | upx_uint64_t page_mask; // AND clears the offset-within-page |
414 | | |
415 | | Elf64_Dyn *dynseg; // from PT_DYNAMIC |
416 | | unsigned int const *hashtab, *hashend; // from DT_HASH |
417 | | unsigned int const *gashtab, *gashend; // from DT_GNU_HASH |
418 | | Elf64_Sym *dynsym; // DT_SYMTAB; 'const' except [0] for decompressor |
419 | | Elf64_Sym const *jni_onload_sym; |
420 | | |
421 | | Elf64_Shdr *sec_strndx; |
422 | | Elf64_Shdr *sec_dynsym; |
423 | | Elf64_Shdr const *sec_dynstr; |
424 | | Elf64_Shdr *sec_arm_attr; // SHT_ARM_ATTRIBUTES; |
425 | | |
426 | | packed_struct(cprElfHdr1) { |
427 | | Elf64_Ehdr ehdr; |
428 | | Elf64_Phdr phdr[1]; |
429 | | l_info linfo; |
430 | | }; |
431 | | |
432 | | packed_struct(cprElfHdr2) { |
433 | | Elf64_Ehdr ehdr; |
434 | | Elf64_Phdr phdr[2]; |
435 | | l_info linfo; |
436 | | }; |
437 | | |
438 | | packed_struct(cprElfHdr3) { |
439 | | Elf64_Ehdr ehdr; |
440 | | Elf64_Phdr phdr[3]; |
441 | | l_info linfo; |
442 | | }; |
443 | | |
444 | | packed_struct(cprElfHdr4) { |
445 | | Elf64_Ehdr ehdr; |
446 | | Elf64_Phdr phdr[4]; |
447 | | l_info linfo; |
448 | | }; |
449 | | |
450 | | cprElfHdr4 elfout; |
451 | | |
452 | | packed_struct(cprElfShdr3) { |
453 | | Elf64_Shdr shdr[3]; |
454 | | }; |
455 | | |
456 | | cprElfShdr3 shdrout; |
457 | | |
458 | 0 | static void compileTimeAssertions() { |
459 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr1) == 64 + 1*56 + 12) |
460 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr2) == 64 + 2*56 + 12) |
461 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr3) == 64 + 3*56 + 12) |
462 | 0 | COMPILE_TIME_ASSERT(sizeof(cprElfHdr4) == 64 + 4*56 + 12) |
463 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr1) |
464 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr2) |
465 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr3) |
466 | 0 | COMPILE_TIME_ASSERT_ALIGNED1(cprElfHdr4) |
467 | 0 | } |
468 | | }; |
469 | | |
470 | | class PackLinuxElf32Be : public PackLinuxElf32 |
471 | | { |
472 | | typedef PackLinuxElf32 super; |
473 | | protected: |
474 | 48.8k | PackLinuxElf32Be(InputFile *f) : super(f) { |
475 | 48.8k | bele = &N_BELE_RTP::be_policy; |
476 | 48.8k | PackLinuxElf32help1(f); |
477 | 48.8k | } |
478 | | }; |
479 | | |
480 | | class PackLinuxElf32Le : public PackLinuxElf32 |
481 | | { |
482 | | typedef PackLinuxElf32 super; |
483 | | protected: |
484 | 120k | PackLinuxElf32Le(InputFile *f) : super(f) { |
485 | 120k | bele = &N_BELE_RTP::le_policy; |
486 | 120k | PackLinuxElf32help1(f); |
487 | 120k | } |
488 | | }; |
489 | | |
490 | | class PackLinuxElf64Le : public PackLinuxElf64 |
491 | | { |
492 | | typedef PackLinuxElf64 super; |
493 | | protected: |
494 | 51.8k | PackLinuxElf64Le(InputFile *f) : super(f) { |
495 | 51.8k | lg2_page=16; |
496 | 51.8k | page_size=1u<<lg2_page; |
497 | 51.8k | bele = &N_BELE_RTP::le_policy; |
498 | 51.8k | PackLinuxElf64help1(f); |
499 | 51.8k | } |
500 | | }; |
501 | | |
502 | | class PackLinuxElf64Be : public PackLinuxElf64 |
503 | | { |
504 | | typedef PackLinuxElf64 super; |
505 | | protected: |
506 | 16.0k | PackLinuxElf64Be(InputFile *f) : super(f) { |
507 | 16.0k | lg2_page=16; |
508 | 16.0k | page_size=1u<<lg2_page; |
509 | 16.0k | bele = &N_BELE_RTP::be_policy; |
510 | 16.0k | PackLinuxElf64help1(f); |
511 | 16.0k | } |
512 | | }; |
513 | | |
514 | | |
515 | | /************************************************************************* |
516 | | // linux/elf64amd |
517 | | **************************************************************************/ |
518 | | |
519 | | class PackLinuxElf64amd : public PackLinuxElf64Le |
520 | | { |
521 | | typedef PackLinuxElf64Le super; |
522 | | public: |
523 | | PackLinuxElf64amd(InputFile *f); |
524 | | virtual ~PackLinuxElf64amd(); |
525 | 19.9k | virtual int getFormat() const override { return UPX_F_LINUX_ELF64_AMD64; } |
526 | 8 | virtual const char *getName() const override { return "linux/amd64"; } |
527 | 0 | virtual const char *getFullName(const options_t *) const override { return "amd64-linux.elf"; } |
528 | | virtual const int *getFilters() const override; |
529 | | protected: |
530 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
531 | | virtual void buildLoader(const Filter *) override; |
532 | | virtual Linker* newLinker() const override; |
533 | | virtual void defineSymbols(Filter const *) override; |
534 | | }; |
535 | | |
536 | | class PackLinuxElf64arm : public PackLinuxElf64Le |
537 | | { |
538 | | typedef PackLinuxElf64Le super; |
539 | | public: |
540 | | PackLinuxElf64arm(InputFile *f); |
541 | | virtual ~PackLinuxElf64arm(); |
542 | 16.4k | virtual int getFormat() const override { return UPX_F_LINUX_ELF64_ARM64; } |
543 | 7 | virtual const char *getName() const override { return "linux/arm64"; } |
544 | 0 | virtual const char *getFullName(const options_t *) const override { return "arm64-linux.elf"; } |
545 | | virtual const int *getFilters() const override; |
546 | | protected: |
547 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
548 | | virtual void buildLoader(const Filter *) override; |
549 | | virtual Linker* newLinker() const override; |
550 | | virtual void defineSymbols(Filter const *) override; |
551 | | }; |
552 | | |
553 | | |
554 | | /************************************************************************* |
555 | | // linux/elf32ppc |
556 | | **************************************************************************/ |
557 | | |
558 | | class PackLinuxElf32ppc : public PackLinuxElf32Be |
559 | | { |
560 | | typedef PackLinuxElf32Be super; |
561 | | public: |
562 | | PackLinuxElf32ppc(InputFile *f); |
563 | | virtual ~PackLinuxElf32ppc(); |
564 | 16.3k | virtual int getFormat() const override { return UPX_F_LINUX_ELF32_PPC32; } |
565 | 5 | virtual const char *getName() const override { return "linux/ppc32"; } |
566 | 0 | virtual const char *getFullName(const options_t *) const override { return "powerpc-linux.elf"; } |
567 | | virtual const int *getFilters() const override; |
568 | | protected: |
569 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
570 | | virtual void buildLoader(const Filter *) override; |
571 | | virtual Linker* newLinker() const override; |
572 | | }; |
573 | | |
574 | | /************************************************************************* |
575 | | // linux/elf64ppcle |
576 | | **************************************************************************/ |
577 | | |
578 | | class PackLinuxElf64ppcle : public PackLinuxElf64Le |
579 | | { |
580 | | typedef PackLinuxElf64Le super; |
581 | | public: |
582 | | PackLinuxElf64ppcle(InputFile *f); |
583 | | virtual ~PackLinuxElf64ppcle(); |
584 | 14.3k | virtual int getFormat() const override { return UPX_F_LINUX_ELF64_PPC64LE; } |
585 | 4 | virtual const char *getName() const override { return "linux/ppc64le"; } |
586 | 0 | virtual const char *getFullName(const options_t *) const override { return "powerpc64le-linux.elf"; } |
587 | | virtual const int *getFilters() const override; |
588 | | protected: |
589 | | unsigned lg2_page; // log2(PAGE_SIZE) |
590 | | unsigned page_size; // 1u<<lg2_page |
591 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
592 | | virtual void buildLoader(const Filter *) override; |
593 | | virtual Linker* newLinker() const override; |
594 | | }; |
595 | | |
596 | | |
597 | | class PackLinuxElf64ppc : public PackLinuxElf64Be |
598 | | { |
599 | | typedef PackLinuxElf64Be super; |
600 | | public: |
601 | | PackLinuxElf64ppc(InputFile *f); |
602 | | virtual ~PackLinuxElf64ppc(); |
603 | 14.3k | virtual int getFormat() const override { return UPX_F_LINUX_ELF64_PPC64; } |
604 | 2 | virtual const char *getName() const override { return "linux/ppc64"; } |
605 | 0 | virtual const char *getFullName(const options_t *) const override { return "powerpc64-linux.elf"; } |
606 | | virtual const int *getFilters() const override; |
607 | | protected: |
608 | | unsigned lg2_page; // log2(PAGE_SIZE) |
609 | | unsigned page_size; // 1u<<lg2_page |
610 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
611 | | virtual void buildLoader(const Filter *) override; |
612 | | virtual Linker* newLinker() const override; |
613 | | }; |
614 | | |
615 | | |
616 | | /************************************************************************* |
617 | | // linux/elf386 |
618 | | **************************************************************************/ |
619 | | |
620 | | class PackLinuxElf32x86 : public PackLinuxElf32Le |
621 | | { |
622 | | typedef PackLinuxElf32Le super; |
623 | | public: |
624 | | PackLinuxElf32x86(InputFile *f); |
625 | | virtual ~PackLinuxElf32x86(); |
626 | 22.8k | virtual int getFormat() const override { return UPX_F_LINUX_ELF_i386; } |
627 | 7 | virtual const char *getName() const override { return "linux/i386"; } |
628 | 0 | virtual const char *getFullName(const options_t *) const override { return "i386-linux.elf"; } |
629 | | virtual const int *getFilters() const override; |
630 | | virtual tribool canUnpack() override; // bool, except -1: format known, but not packed |
631 | | |
632 | | protected: |
633 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
634 | | |
635 | | virtual void buildLoader(const Filter *) override; |
636 | | virtual void addStubEntrySections(Filter const *, unsigned m_decompr) override; |
637 | | virtual Linker* newLinker() const override; |
638 | | virtual void defineSymbols(Filter const *) override; |
639 | | }; |
640 | | |
641 | | class PackBSDElf32x86 : public PackLinuxElf32x86 |
642 | | { |
643 | | typedef PackLinuxElf32x86 super; |
644 | | public: |
645 | | PackBSDElf32x86(InputFile *f); |
646 | | virtual ~PackBSDElf32x86(); |
647 | | virtual int getFormat() const override = 0; |
648 | | virtual const char *getName() const override = 0; |
649 | | virtual const char *getFullName(const options_t *) const override = 0; |
650 | | |
651 | | protected: |
652 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
653 | | |
654 | | virtual void buildLoader(const Filter *) override; |
655 | | }; |
656 | | |
657 | | class PackFreeBSDElf32x86 : public PackBSDElf32x86 |
658 | | { |
659 | | typedef PackBSDElf32x86 super; |
660 | | public: |
661 | | PackFreeBSDElf32x86(InputFile *f); |
662 | | virtual ~PackFreeBSDElf32x86(); |
663 | 22.9k | virtual int getFormat() const override { return UPX_F_BSD_ELF_i386; } |
664 | 0 | virtual const char *getName() const override { return "freebsd/i386"; } |
665 | 0 | virtual const char *getFullName(const options_t *) const override { return "i386-freebsd.elf"; } |
666 | | }; |
667 | | |
668 | | class PackNetBSDElf32x86 : public PackLinuxElf32x86 |
669 | | { |
670 | | typedef PackLinuxElf32x86 super; |
671 | | public: |
672 | | PackNetBSDElf32x86(InputFile *f); |
673 | | virtual ~PackNetBSDElf32x86(); |
674 | 22.8k | virtual int getFormat() const override { return UPX_F_BSD_ELF_i386; } |
675 | 0 | virtual const char *getName() const override { return "netbsd/i386"; } |
676 | 0 | virtual const char *getFullName(const options_t *) const override { return "i386-netbsd.elf"; } |
677 | | protected: |
678 | | virtual void buildLoader(const Filter *ft) override; |
679 | | virtual void generateElfHdr( |
680 | | OutputFile *, |
681 | | void const *proto, |
682 | | unsigned const brka |
683 | | ) override; |
684 | | }; |
685 | | |
686 | | class PackOpenBSDElf32x86 : public PackBSDElf32x86 |
687 | | { |
688 | | typedef PackBSDElf32x86 super; |
689 | | public: |
690 | | PackOpenBSDElf32x86(InputFile *f); |
691 | | virtual ~PackOpenBSDElf32x86(); |
692 | 22.8k | virtual int getFormat() const override { return UPX_F_BSD_ELF_i386; } |
693 | 0 | virtual const char *getName() const override { return "openbsd/i386"; } |
694 | 0 | virtual const char *getFullName(const options_t *) const override { return "i386-openbsd.elf"; } |
695 | | |
696 | | protected: |
697 | | virtual void buildLoader(const Filter *ft) override; |
698 | | virtual void generateElfHdr( |
699 | | OutputFile *, |
700 | | void const *proto, |
701 | | unsigned const brka |
702 | | ) override; |
703 | | }; |
704 | | |
705 | | |
706 | | /************************************************************************* |
707 | | // linux/elfarm |
708 | | **************************************************************************/ |
709 | | |
710 | | class PackLinuxElf32armLe : public PackLinuxElf32Le |
711 | | { |
712 | | typedef PackLinuxElf32Le super; |
713 | | public: |
714 | | PackLinuxElf32armLe(InputFile *f); |
715 | | virtual ~PackLinuxElf32armLe(); |
716 | 18.5k | virtual int getFormat() const override { return UPX_F_LINUX_ELF32_ARM; } |
717 | 2 | virtual const char *getName() const override { return "linux/arm"; } |
718 | 0 | virtual const char *getFullName(const options_t *) const override { return "arm-linux.elf"; } |
719 | | virtual const int *getFilters() const override; |
720 | | |
721 | | protected: |
722 | | virtual const int *getCompressionMethods(int method, int level) const override; |
723 | | virtual Linker* newLinker() const override; |
724 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
725 | | virtual void buildLoader(const Filter *) override; |
726 | | virtual void updateLoader(OutputFile *) override; |
727 | | virtual void defineSymbols(Filter const *) override; |
728 | | }; |
729 | | |
730 | | class PackLinuxElf32armBe : public PackLinuxElf32Be |
731 | | { |
732 | | typedef PackLinuxElf32Be super; |
733 | | public: |
734 | | PackLinuxElf32armBe(InputFile *f); |
735 | | virtual ~PackLinuxElf32armBe(); |
736 | 16.7k | virtual int getFormat() const override { return UPX_F_LINUX_ELF32_ARMEB; } |
737 | 4 | virtual const char *getName() const override { return "linux/armeb"; } |
738 | 0 | virtual const char *getFullName(const options_t *) const override { return "armeb-linux.elf"; } |
739 | | virtual const int *getFilters() const override; |
740 | | |
741 | | protected: |
742 | | virtual const int *getCompressionMethods(int method, int level) const override; |
743 | | virtual Linker* newLinker() const override; |
744 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
745 | | virtual void buildLoader(const Filter *) override; |
746 | | virtual void updateLoader(OutputFile *) override; |
747 | | virtual void defineSymbols(Filter const *) override; |
748 | | }; |
749 | | |
750 | | class PackLinuxElf32mipseb : public PackLinuxElf32Be |
751 | | { |
752 | | typedef PackLinuxElf32Be super; |
753 | | public: |
754 | | PackLinuxElf32mipseb(InputFile *f); |
755 | | virtual ~PackLinuxElf32mipseb(); |
756 | 14.1k | virtual int getFormat() const override { return UPX_F_LINUX_ELF32_MIPS; } |
757 | 3 | virtual const char *getName() const override { return "linux/mips"; } |
758 | 0 | virtual const char *getFullName(const options_t *) const override { return "mips-linux.elf"; } |
759 | | virtual const int *getFilters() const override; |
760 | | |
761 | | protected: |
762 | | virtual Linker* newLinker() const override; |
763 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
764 | | virtual void buildLoader(const Filter *) override; |
765 | | virtual void updateLoader(OutputFile *) override; |
766 | | virtual void defineSymbols(Filter const *) override; |
767 | | }; |
768 | | |
769 | | class PackLinuxElf32mipsel : public PackLinuxElf32Le |
770 | | { |
771 | | typedef PackLinuxElf32Le super; |
772 | | public: |
773 | | PackLinuxElf32mipsel(InputFile *f); |
774 | | virtual ~PackLinuxElf32mipsel(); |
775 | 14.2k | virtual int getFormat() const override { return UPX_F_LINUX_ELF32_MIPSEL; } |
776 | 5 | virtual const char *getName() const override { return "linux/mipsel"; } |
777 | 0 | virtual const char *getFullName(const options_t *) const override { return "mipsel-linux.elf"; } |
778 | | virtual const int *getFilters() const override; |
779 | | |
780 | | protected: |
781 | | virtual Linker* newLinker() const override; |
782 | | virtual void pack1(OutputFile *, Filter &) override; // generate executable header |
783 | | virtual void buildLoader(const Filter *) override; |
784 | | virtual void updateLoader(OutputFile *) override; |
785 | | virtual void defineSymbols(Filter const *) override; |
786 | | }; |
787 | | |
788 | | |
789 | | #endif /*} already included */ |
790 | | |
791 | | /* vim:set ts=4 sw=4 et: */ |