1 /* Compress or decompress an ELF file.
2 Copyright (C) 2015 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19 #include <assert.h>
20 #include <argp.h>
21 #include <error.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <inttypes.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <locale.h>
28 #include <fcntl.h>
29 #include <fnmatch.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include ELFUTILS_HEADER(elf)
34 #include ELFUTILS_HEADER(ebl)
35 #include <gelf.h>
36 #include "system.h"
37
38 /* Name and version of program. */
39 static void print_version (FILE *stream, struct argp_state *state);
40 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
41
42 /* Bug report address. */
43 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
44
45 static int verbose = 0; /* < 0, no warnings, > 0 extra verbosity. */
46 static bool force = false;
47 static bool permissive = false;
48 static const char *foutput = NULL;
49
50 #define T_UNSET 0
51 #define T_DECOMPRESS 1 /* none */
52 #define T_COMPRESS_ZLIB 2 /* zlib */
53 #define T_COMPRESS_GNU 3 /* zlib-gnu */
54 static int type = T_UNSET;
55
56 static void
print_version(FILE * stream,struct argp_state * state)57 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
58 {
59 fprintf (stream, "elfcompress (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
60 }
61
62 struct section_pattern
63 {
64 char *pattern;
65 struct section_pattern *next;
66 };
67
68 static struct section_pattern *patterns = NULL;
69
70 static void
add_pattern(const char * pattern)71 add_pattern (const char *pattern)
72 {
73 struct section_pattern *p = xmalloc (sizeof *p);
74 p->pattern = xstrdup (pattern);
75 p->next = patterns;
76 patterns = p;
77 }
78
79 static void
free_patterns(void)80 free_patterns (void)
81 {
82 struct section_pattern *pattern = patterns;
83 while (pattern != NULL)
84 {
85 struct section_pattern *p = pattern;
86 pattern = p->next;
87 free (p->pattern);
88 free (p);
89 }
90 }
91
92 static error_t
parse_opt(int key,char * arg,struct argp_state * state)93 parse_opt (int key, char *arg __attribute__ ((unused)),
94 struct argp_state *state __attribute__ ((unused)))
95 {
96 switch (key)
97 {
98 case 'v':
99 verbose++;
100 break;
101
102 case 'q':
103 verbose--;
104
105 case 'f':
106 force = true;
107 break;
108
109 case 'p':
110 permissive = true;
111 break;
112
113 case 'n':
114 add_pattern (arg);
115 break;
116
117 case 'o':
118 if (foutput != NULL)
119 argp_error (state, N_("-o option specified twice"));
120 else
121 foutput = arg;
122 break;
123
124 case 't':
125 if (type != T_UNSET)
126 argp_error (state, N_("-t option specified twice"));
127
128 if (strcmp ("none", arg) == 0)
129 type = T_DECOMPRESS;
130 else if (strcmp ("zlib", arg) == 0 || strcmp ("zlib-gabi", arg) == 0)
131 type = T_COMPRESS_ZLIB;
132 else if (strcmp ("zlib-gnu", arg) == 0 || strcmp ("gnu", arg) == 0)
133 type = T_COMPRESS_GNU;
134 else
135 argp_error (state, N_("unknown compression type '%s'"), arg);
136 break;
137
138 case ARGP_KEY_SUCCESS:
139 if (type == T_UNSET)
140 type = T_COMPRESS_ZLIB;
141 if (patterns == NULL)
142 add_pattern (".?(z)debug*");
143 break;
144
145 case ARGP_KEY_NO_ARGS:
146 /* We need at least one input file. */
147 argp_error (state, N_("No input file given"));
148 break;
149
150 case ARGP_KEY_ARGS:
151 if (foutput != NULL && state->argc - state->next > 1)
152 argp_error (state,
153 N_("Only one input file allowed together with '-o'"));
154 /* We only use this for checking the number of arguments, we don't
155 actually want to consume them, so fallthrough. */
156 default:
157 return ARGP_ERR_UNKNOWN;
158 }
159 return 0;
160 }
161
162 static bool
section_name_matches(const char * name)163 section_name_matches (const char *name)
164 {
165 struct section_pattern *pattern = patterns;
166 while (pattern != NULL)
167 {
168 if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
169 return true;
170 pattern = pattern->next;
171 }
172 return false;
173 }
174
175 static int
setshdrstrndx(Elf * elf,GElf_Ehdr * ehdr,size_t ndx)176 setshdrstrndx (Elf *elf, GElf_Ehdr *ehdr, size_t ndx)
177 {
178 if (ndx < SHN_LORESERVE)
179 ehdr->e_shstrndx = ndx;
180 else
181 {
182 ehdr->e_shstrndx = SHN_XINDEX;
183 Elf_Scn *zscn = elf_getscn (elf, 0);
184 GElf_Shdr zshdr_mem;
185 GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
186 if (zshdr == NULL)
187 return -1;
188 zshdr->sh_link = ndx;
189 if (gelf_update_shdr (zscn, zshdr) == 0)
190 return -1;
191 }
192
193 if (gelf_update_ehdr (elf, ehdr) == 0)
194 return -1;
195
196 return 0;
197 }
198
199 static int
compress_section(Elf_Scn * scn,size_t orig_size,const char * name,const char * newname,size_t ndx,bool gnu,bool compress,bool report_verbose)200 compress_section (Elf_Scn *scn, size_t orig_size, const char *name,
201 const char *newname, size_t ndx,
202 bool gnu, bool compress, bool report_verbose)
203 {
204 int res;
205 unsigned int flags = compress && force ? ELF_CHF_FORCE : 0;
206 if (gnu)
207 res = elf_compress_gnu (scn, compress ? 1 : 0, flags);
208 else
209 res = elf_compress (scn, compress ? ELFCOMPRESS_ZLIB : 0, flags);
210
211 if (res < 0)
212 error (0, 0, "Couldn't decompress section [%zd] %s: %s",
213 ndx, name, elf_errmsg (-1));
214 else
215 {
216 if (compress && res == 0)
217 {
218 if (verbose >= 0)
219 printf ("[%zd] %s NOT compressed, wouldn't be smaller\n",
220 ndx, name);
221 }
222
223 if (report_verbose && res > 0)
224 {
225 printf ("[%zd] %s %s", ndx, name,
226 compress ? "compressed" : "decompressed");
227 if (newname != NULL)
228 printf (" -> %s", newname);
229
230 /* Reload shdr, it has changed. */
231 GElf_Shdr shdr_mem;
232 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
233 if (shdr == NULL)
234 {
235 error (0, 0, "Couldn't get shdr for section [%zd]", ndx);
236 return -1;
237 }
238 float new = shdr->sh_size;
239 float orig = orig_size ?: 1;
240 printf (" (%zu => %" PRIu64 " %.2f%%)\n",
241 orig_size, shdr->sh_size, (new / orig) * 100);
242 }
243 }
244
245 return res;
246 }
247
248 static int
process_file(const char * fname)249 process_file (const char *fname)
250 {
251 if (verbose > 0)
252 printf ("processing: %s\n", fname);
253
254 /* The input ELF. */
255 int fd = -1;
256 Elf *elf = NULL;
257
258 /* The output ELF. */
259 char *fnew = NULL;
260 int fdnew = -1;
261 Elf *elfnew = NULL;
262
263 /* Buffer for (one) new section name if necessary. */
264 char *snamebuf = NULL;
265
266 /* String table (and symbol table), if section names need adjusting. */
267 struct Ebl_Strtab *names = NULL;
268 struct Ebl_Strent **scnstrents = NULL;
269 struct Ebl_Strent **symstrents = NULL;
270 char **scnnames = NULL;
271
272 /* Section data from names. */
273 void *namesbuf = NULL;
274
275 /* Which sections match and need to be (un)compressed. */
276 unsigned int *sections = NULL;
277
278 /* How many sections are we talking about? */
279 size_t shnum = 0;
280
281 #define WORD_BITS (8U * sizeof (unsigned int))
282 void set_section (size_t ndx)
283 {
284 sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS));
285 }
286
287 bool get_section (size_t ndx)
288 {
289 return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
290 }
291
292 int cleanup (int res)
293 {
294 elf_end (elf);
295 close (fd);
296
297 elf_end (elfnew);
298 close (fdnew);
299
300 if (fnew != NULL)
301 {
302 unlink (fnew);
303 free (fnew);
304 fnew = NULL;
305 }
306
307 free (snamebuf);
308 if (names != NULL)
309 {
310 ebl_strtabfree (names);
311 free (scnstrents);
312 free (symstrents);
313 free (namesbuf);
314 if (scnnames != NULL)
315 {
316 for (size_t n = 0; n < shnum; n++)
317 free (scnnames[n]);
318 free (scnnames);
319 }
320 }
321
322 free (sections);
323
324 return res;
325 }
326
327 fd = open (fname, O_RDONLY);
328 if (fd < 0)
329 {
330 error (0, errno, "Couldn't open %s\n", fname);
331 return cleanup (-1);
332 }
333
334 elf = elf_begin (fd, ELF_C_READ, NULL);
335 if (elf == NULL)
336 {
337 error (0, 0, "Couldn't open ELF file %s for reading: %s",
338 fname, elf_errmsg (-1));
339 return cleanup (-1);
340 }
341
342 /* We dont' handle ar files (or anything else), we probably should. */
343 Elf_Kind kind = elf_kind (elf);
344 if (kind != ELF_K_ELF)
345 {
346 if (kind == ELF_K_AR)
347 error (0, 0, "Cannot handle ar files: %s", fname);
348 else
349 error (0, 0, "Unknown file type: %s", fname);
350 return cleanup (-1);
351 }
352
353 struct stat st;
354 if (fstat (fd, &st) != 0)
355 {
356 error (0, errno, "Couldn't fstat %s", fname);
357 return cleanup (-1);
358 }
359
360 GElf_Ehdr ehdr;
361 if (gelf_getehdr (elf, &ehdr) == NULL)
362 {
363 error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1));
364 return cleanup (-1);
365 }
366
367 /* Get the section header string table. */
368 size_t shdrstrndx;
369 if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
370 {
371 error (0, 0, "Couldn't get section header string table index in %s: %s",
372 fname, elf_errmsg (-1));
373 return cleanup (-1);
374 }
375
376 /* How many sections are we talking about? */
377 if (elf_getshdrnum (elf, &shnum) != 0)
378 {
379 error (0, 0, "Couldn't get number of sections in %s: %s",
380 fname, elf_errmsg (1));
381 return cleanup (-1);
382 }
383
384 if (shnum == 0)
385 {
386 error (0, 0, "ELF file %s has no sections", fname);
387 return cleanup (-1);
388 }
389
390 sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int));
391
392 size_t phnum;
393 if (elf_getphdrnum (elf, &phnum) != 0)
394 {
395 error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1));
396 return cleanup (-1);
397 }
398
399 /* Whether we need to adjust any section names (going to/from GNU
400 naming). If so we'll need to build a new section header string
401 table. */
402 bool adjust_names = false;
403
404 /* If there are phdrs we want to maintain the layout of the
405 allocated sections in the file. */
406 bool layout = phnum != 0;
407
408 /* While going through all sections keep track of last section data
409 offset if needed to keep the layout. We are responsible for
410 adding the section offsets and headers (e_shoff) in that case
411 (which we will place after the last section). */
412 GElf_Off last_offset = 0;
413 if (layout)
414 last_offset = (ehdr.e_phoff
415 + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT));
416
417 /* Which section, if any, is a symbol table that shares a string
418 table with the section header string table? */
419 size_t symtabndx = 0;
420
421 /* We do three passes over all sections.
422
423 First an inspection pass over the old Elf to see which section
424 data needs to be copied and/or transformed, which sections need a
425 names change and whether there is a symbol table that might need
426 to be adjusted be if the section header name table is changed.
427
428 Second a collection pass that creates the Elf sections and copies
429 the data. This pass will compress/decompress section data when
430 needed. And it will collect all data needed if we'll need to
431 construct a new string table. Afterwards the new string table is
432 constructed.
433
434 Third a fixup/adjustment pass over the new Elf that will adjust
435 any section references (names) and adjust the layout based on the
436 new sizes of the sections if necessary. This pass is optional if
437 we aren't responsible for the layout and the section header
438 string table hasn't been changed. */
439
440 /* Inspection pass. */
441 size_t maxnamelen = 0;
442 Elf_Scn *scn = NULL;
443 while ((scn = elf_nextscn (elf, scn)) != NULL)
444 {
445 size_t ndx = elf_ndxscn (scn);
446 if (ndx > shnum)
447 {
448 error (0, 0, "Unexpected section number %zd, expected only %zd",
449 ndx, shnum);
450 cleanup (-1);
451 }
452
453 GElf_Shdr shdr_mem;
454 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
455 if (shdr == NULL)
456 {
457 error (0, 0, "Couldn't get shdr for section %zd", ndx);
458 return cleanup (-1);
459 }
460
461 const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
462 if (sname == NULL)
463 {
464 error (0, 0, "Couldn't get name for section %zd", ndx);
465 return cleanup (-1);
466 }
467
468 if (section_name_matches (sname))
469 {
470 if (shdr->sh_type != SHT_NOBITS
471 && (shdr->sh_flags & SHF_ALLOC) == 0)
472 {
473 set_section (ndx);
474 /* Check if we might want to change this section name. */
475 if (! adjust_names
476 && ((type != T_COMPRESS_GNU
477 && strncmp (sname, ".zdebug",
478 strlen (".zdebug")) == 0)
479 || (type == T_COMPRESS_GNU
480 && strncmp (sname, ".debug",
481 strlen (".debug")) == 0)))
482 adjust_names = true;
483
484 /* We need a buffer this large if we change the names. */
485 if (adjust_names)
486 {
487 size_t slen = strlen (sname);
488 if (slen > maxnamelen)
489 maxnamelen = slen;
490 }
491 }
492 else
493 if (verbose >= 0)
494 printf ("[%zd] %s ignoring %s section\n", ndx, sname,
495 (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated"));
496 }
497
498 if (shdr->sh_type == SHT_SYMTAB)
499 {
500 /* Check if we might have to adjust the symbol name indexes. */
501 if (shdr->sh_link == shdrstrndx)
502 {
503 if (symtabndx != 0)
504 {
505 error (0, 0,
506 "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx);
507 return cleanup (-1);
508 }
509 symtabndx = ndx;
510 }
511 }
512
513 /* Keep track of last allocated data offset. */
514 if (layout)
515 if ((shdr->sh_flags & SHF_ALLOC) != 0)
516 {
517 GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS
518 ? shdr->sh_size : 0);
519 if (last_offset < off)
520 last_offset = off;
521 }
522 }
523
524 if (adjust_names)
525 {
526 names = ebl_strtabinit (true);
527 if (names == NULL)
528 {
529 error (0, 0, "Not enough memory for new strtab");
530 return cleanup (-1);
531 }
532 scnstrents = xmalloc (shnum
533 * sizeof (struct Ebl_Strent *));
534 scnnames = xcalloc (shnum, sizeof (char *));
535 }
536
537 /* Create a new (temporary) ELF file for the result. */
538 if (foutput == NULL)
539 {
540 size_t fname_len = strlen (fname);
541 fnew = xmalloc (fname_len + sizeof (".XXXXXX"));
542 strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX");
543 fdnew = mkstemp (fnew);
544 }
545 else
546 {
547 fnew = xstrdup (foutput);
548 fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS);
549 }
550
551 if (fdnew < 0)
552 {
553 error (0, errno, "Couldn't create output file %s", fnew);
554 /* Since we didn't create it we don't want to try to unlink it. */
555 free (fnew);
556 fnew = NULL;
557 return cleanup (-1);
558 }
559
560 elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
561 if (elfnew == NULL)
562 {
563 error (0, 0, "Couldn't open new ELF %s for writing: %s",
564 fnew, elf_errmsg (-1));
565 return cleanup (-1);
566 }
567
568 /* Create the new ELF header and copy over all the data. */
569 if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
570 {
571 error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1));
572 return cleanup (-1);
573 }
574
575 GElf_Ehdr newehdr;
576 if (gelf_getehdr (elfnew, &newehdr) == NULL)
577 {
578 error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1));
579 return cleanup (-1);
580 }
581
582 newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
583 newehdr.e_type = ehdr.e_type;
584 newehdr.e_machine = ehdr.e_machine;
585 newehdr.e_version = ehdr.e_version;
586 newehdr.e_entry = ehdr.e_entry;
587 newehdr.e_flags = ehdr.e_flags;
588
589 if (gelf_update_ehdr (elfnew, &newehdr) == 0)
590 {
591 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
592 return cleanup (-1);
593 }
594
595 /* Copy over the phdrs as is. */
596 if (phnum != 0)
597 {
598 if (gelf_newphdr (elfnew, phnum) == 0)
599 {
600 error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1));
601 return cleanup (-1);
602 }
603
604 for (size_t cnt = 0; cnt < phnum; ++cnt)
605 {
606 GElf_Phdr phdr_mem;
607 GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
608 if (phdr == NULL)
609 {
610 error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1));
611 return cleanup (-1);
612 }
613 if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
614 {
615 error (0, 0, "Couldn't create phdr %zd: %s", cnt,
616 elf_errmsg (-1));
617 return cleanup (-1);
618 }
619 }
620 }
621
622 /* Possibly add a 'z' and zero terminator. */
623 if (maxnamelen > 0)
624 snamebuf = xmalloc (maxnamelen + 2);
625
626 /* We might want to read/adjust the section header strings and
627 symbol tables. If so, and those sections are to be compressed
628 then we will have to decompress it during the collection pass and
629 compress it again in the fixup pass. Don't compress unnecessary
630 and keep track of whether or not to compress them (later in the
631 fixup pass). Also record the original size, so we can report the
632 difference later when we do compress. */
633 int shstrtab_compressed = T_UNSET;
634 size_t shstrtab_size = 0;
635 char *shstrtab_name = NULL;
636 char *shstrtab_newname = NULL;
637 int symtab_compressed = T_UNSET;
638 size_t symtab_size = 0;
639 char *symtab_name = NULL;
640 char *symtab_newname = NULL;
641
642 /* Collection pass. Copy over the sections, (de)compresses matching
643 sections, collect names of sections and symbol table if
644 necessary. */
645 scn = NULL;
646 while ((scn = elf_nextscn (elf, scn)) != NULL)
647 {
648 size_t ndx = elf_ndxscn (scn);
649 assert (ndx < shnum);
650
651 /* (de)compress if section matched. */
652 char *sname = NULL;
653 char *newname = NULL;
654 if (get_section (ndx))
655 {
656 GElf_Shdr shdr_mem;
657 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
658 if (shdr == NULL)
659 {
660 error (0, 0, "Couldn't get shdr for section %zd", ndx);
661 return cleanup (-1);
662 }
663
664 uint64_t size = shdr->sh_size;
665 sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
666 if (sname == NULL)
667 {
668 error (0, 0, "Couldn't get name for section %zd", ndx);
669 return cleanup (-1);
670 }
671
672 /* strdup sname, the shdrstrndx section itself might be
673 (de)compressed, invalidating the string pointers. */
674 sname = xstrdup (sname);
675
676 /* We might want to decompress (and rename), but not
677 compress during this pass since we might need the section
678 data in later passes. Skip those sections for now and
679 compress them in the fixup pass. */
680 bool skip_compress_section = (adjust_names
681 && (ndx == shdrstrndx
682 || ndx == symtabndx));
683
684 switch (type)
685 {
686 case T_DECOMPRESS:
687 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
688 {
689 if (compress_section (scn, size, sname, NULL, ndx,
690 false, false, verbose > 0) < 0)
691 return cleanup (-1);
692 }
693 else if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
694 {
695 snamebuf[0] = '.';
696 strcpy (&snamebuf[1], &sname[2]);
697 newname = snamebuf;
698 if (compress_section (scn, size, sname, newname, ndx,
699 true, false, verbose > 0) < 0)
700 return cleanup (-1);
701 }
702 else if (verbose > 0)
703 printf ("[%zd] %s already decompressed\n", ndx, sname);
704 break;
705
706 case T_COMPRESS_GNU:
707 if (strncmp (sname, ".debug", strlen (".debug")) == 0)
708 {
709 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
710 {
711 /* First decompress to recompress GNU style.
712 Don't report even when verbose. */
713 if (compress_section (scn, size, sname, NULL, ndx,
714 false, false, false) < 0)
715 return cleanup (-1);
716 }
717
718 snamebuf[0] = '.';
719 snamebuf[1] = 'z';
720 strcpy (&snamebuf[2], &sname[1]);
721 newname = snamebuf;
722
723 if (skip_compress_section)
724 {
725 if (ndx == shdrstrndx)
726 {
727 shstrtab_size = size;
728 shstrtab_compressed = T_COMPRESS_GNU;
729 shstrtab_name = xstrdup (sname);
730 shstrtab_newname = xstrdup (newname);
731 }
732 else
733 {
734 symtab_size = size;
735 symtab_compressed = T_COMPRESS_GNU;
736 symtab_name = xstrdup (sname);
737 symtab_newname = xstrdup (newname);
738 }
739 }
740 else
741 {
742 int res = compress_section (scn, size, sname, newname,
743 ndx, true, true,
744 verbose > 0);
745 if (res < 0)
746 return cleanup (-1);
747
748 if (res == 0)
749 newname = NULL;
750 }
751 }
752 else if (verbose >= 0)
753 {
754 if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
755 printf ("[%zd] %s unchanged, already GNU compressed",
756 ndx, sname);
757 else
758 printf ("[%zd] %s cannot GNU compress section not starting with .debug\n",
759 ndx, sname);
760 }
761 break;
762
763 case T_COMPRESS_ZLIB:
764 if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
765 {
766 if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
767 {
768 /* First decompress to recompress zlib style.
769 Don't report even when verbose. */
770 if (compress_section (scn, size, sname, NULL, ndx,
771 true, false, false) < 0)
772 return cleanup (-1);
773
774 snamebuf[0] = '.';
775 strcpy (&snamebuf[1], &sname[2]);
776 newname = snamebuf;
777 }
778
779 if (skip_compress_section)
780 {
781 if (ndx == shdrstrndx)
782 {
783 shstrtab_size = size;
784 shstrtab_compressed = T_COMPRESS_ZLIB;
785 shstrtab_name = xstrdup (sname);
786 shstrtab_newname = (newname == NULL
787 ? NULL : xstrdup (newname));
788 }
789 else
790 {
791 symtab_size = size;
792 symtab_compressed = T_COMPRESS_ZLIB;
793 symtab_name = xstrdup (sname);
794 symtab_newname = (newname == NULL
795 ? NULL : xstrdup (newname));
796 }
797 }
798 else if (compress_section (scn, size, sname, newname, ndx,
799 false, true, verbose > 0) < 0)
800 return cleanup (-1);
801 }
802 else if (verbose > 0)
803 printf ("[%zd] %s already compressed\n", ndx, sname);
804 break;
805 }
806
807 free (sname);
808 }
809
810 Elf_Scn *newscn = elf_newscn (elfnew);
811 if (newscn == NULL)
812 {
813 error (0, 0, "Couldn't create new section %zd", ndx);
814 return cleanup (-1);
815 }
816
817 GElf_Shdr shdr_mem;
818 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
819 if (shdr == NULL)
820 {
821 error (0, 0, "Couldn't get shdr for section %zd", ndx);
822 return cleanup (-1);
823 }
824
825 if (gelf_update_shdr (newscn, shdr) == 0)
826 {
827 error (0, 0, "Couldn't update section header %zd", ndx);
828 return cleanup (-1);
829 }
830
831 /* Except for the section header string table all data can be
832 copied as is. The section header string table will be
833 created later and the symbol table might be fixed up if
834 necessary. */
835 if (! adjust_names || ndx != shdrstrndx)
836 {
837 Elf_Data *data = elf_getdata (scn, NULL);
838 if (data == NULL)
839 {
840 error (0, 0, "Couldn't get data from section %zd", ndx);
841 return cleanup (-1);
842 }
843
844 Elf_Data *newdata = elf_newdata (newscn);
845 if (newdata == NULL)
846 {
847 error (0, 0, "Couldn't create new data for section %zd", ndx);
848 return cleanup (-1);
849 }
850
851 *newdata = *data;
852 }
853
854 /* Keep track of the (new) section names. */
855 if (adjust_names)
856 {
857 char *name;
858 if (newname != NULL)
859 name = newname;
860 else
861 {
862 name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
863 if (name == NULL)
864 {
865 error (0, 0, "Couldn't get name for section [%zd]", ndx);
866 return cleanup (-1);
867 }
868 }
869
870 /* We need to keep a copy of the name till the strtab is done. */
871 name = scnnames[ndx] = xstrdup (name);
872 if ((scnstrents[ndx] = ebl_strtabadd (names, name, 0)) == NULL)
873 {
874 error (0, 0, "No memory to add section name string table");
875 return cleanup (-1);
876 }
877
878 /* If the symtab shares strings then add those too. */
879 if (ndx == symtabndx)
880 {
881 /* If the section is (still) compressed we'll need to
882 uncompress it first to adjust the data, then
883 recompress it in the fixup pass. */
884 if (symtab_compressed == T_UNSET)
885 {
886 size_t size = shdr->sh_size;
887 if ((shdr->sh_flags == SHF_COMPRESSED) != 0)
888 {
889 /* Don't report the (internal) uncompression. */
890 if (compress_section (newscn, size, sname, NULL, ndx,
891 false, false, false) < 0)
892 return cleanup (-1);
893
894 symtab_size = size;
895 symtab_compressed = T_COMPRESS_ZLIB;
896 }
897 else if (strncmp (name, ".zdebug", strlen (".zdebug")) == 0)
898 {
899 /* Don't report the (internal) uncompression. */
900 if (compress_section (newscn, size, sname, NULL, ndx,
901 true, false, false) < 0)
902 return cleanup (-1);
903
904 symtab_size = size;
905 symtab_compressed = T_COMPRESS_GNU;
906 }
907 }
908
909 Elf_Data *symd = elf_getdata (newscn, NULL);
910 if (symd == NULL)
911 {
912 error (0, 0, "Couldn't get symtab data for section [%zd] %s",
913 ndx, name);
914 return cleanup (-1);
915 }
916 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
917 size_t syms = symd->d_size / elsize;
918 symstrents = xmalloc (syms * sizeof (struct Ebl_Strent *));
919 for (size_t i = 0; i < syms; i++)
920 {
921 GElf_Sym sym_mem;
922 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
923 if (sym == NULL)
924 {
925 error (0, 0, "Couldn't get symbol %zd", i);
926 return cleanup (-1);
927 }
928 if (sym->st_name != 0)
929 {
930 /* Note we take the name from the original ELF,
931 since the new one will not have setup the
932 strtab yet. */
933 const char *symname = elf_strptr (elf, shdrstrndx,
934 sym->st_name);
935 if (symname == NULL)
936 {
937 error (0, 0, "Couldn't get symbol %zd name", i);
938 return cleanup (-1);
939 }
940 symstrents[i] = ebl_strtabadd (names, symname, 0);
941 if (symstrents[i] == NULL)
942 {
943 error (0, 0, "No memory to add to symbol name");
944 return cleanup (-1);
945 }
946 }
947 }
948 }
949 }
950 }
951
952 if (adjust_names)
953 {
954 /* We got all needed strings, put the new data in the shstrtab. */
955 if (verbose > 0)
956 printf ("[%zd] Updating section string table\n", shdrstrndx);
957
958 scn = elf_getscn (elfnew, shdrstrndx);
959 if (scn == NULL)
960 {
961 error (0, 0, "Couldn't get new section header string table [%zd]",
962 shdrstrndx);
963 return cleanup (-1);
964 }
965
966 Elf_Data *data = elf_newdata (scn);
967 if (data == NULL)
968 {
969 error (0, 0, "Couldn't create new section header string table data");
970 return cleanup (-1);
971 }
972 ebl_strtabfinalize (names, data);
973 namesbuf = data->d_buf;
974
975 GElf_Shdr shdr_mem;
976 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
977 if (shdr == NULL)
978 {
979 error (0, 0, "Couldn't get shdr for new section strings %zd",
980 shdrstrndx);
981 return cleanup (-1);
982 }
983
984 /* Note that we also might have to compress and possibly set
985 sh_off below */
986 shdr->sh_name = ebl_strtaboffset (scnstrents[shdrstrndx]);
987 shdr->sh_type = SHT_STRTAB;
988 shdr->sh_flags = 0;
989 shdr->sh_addr = 0;
990 shdr->sh_offset = 0;
991 shdr->sh_size = data->d_size;
992 shdr->sh_link = SHN_UNDEF;
993 shdr->sh_info = SHN_UNDEF;
994 shdr->sh_addralign = 1;
995 shdr->sh_entsize = 0;
996
997 if (gelf_update_shdr (scn, shdr) == 0)
998 {
999 error (0, 0, "Couldn't update new section strings [%zd]",
1000 shdrstrndx);
1001 return cleanup (-1);
1002 }
1003
1004 /* We might have to compress the data if the user asked us to,
1005 or if the section was already compressed (and the user didn't
1006 ask for decompression). Note somewhat identical code for
1007 symtab below. */
1008 if (shstrtab_compressed == T_UNSET)
1009 {
1010 /* The user didn't ask for compression, but maybe it was
1011 compressed in the original ELF file. */
1012 Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx);
1013 if (oldscn == NULL)
1014 {
1015 error (0, 0, "Couldn't get section header string table [%zd]",
1016 shdrstrndx);
1017 return cleanup (-1);
1018 }
1019
1020 shdr = gelf_getshdr (oldscn, &shdr_mem);
1021 if (shdr == NULL)
1022 {
1023 error (0, 0, "Couldn't get shdr for old section strings [%zd]",
1024 shdrstrndx);
1025 return cleanup (-1);
1026 }
1027
1028 shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1029 if (shstrtab_name == NULL)
1030 {
1031 error (0, 0, "Couldn't get name for old section strings [%zd]",
1032 shdrstrndx);
1033 return cleanup (-1);
1034 }
1035
1036 shstrtab_size = shdr->sh_size;
1037 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1038 shstrtab_compressed = T_COMPRESS_ZLIB;
1039 else if (strncmp (shstrtab_name, ".zdebug", strlen (".zdebug")) == 0)
1040 shstrtab_compressed = T_COMPRESS_GNU;
1041 }
1042
1043 /* Should we (re)compress? */
1044 if (shstrtab_compressed != T_UNSET)
1045 {
1046 if (compress_section (scn, shstrtab_size, shstrtab_name,
1047 shstrtab_newname, shdrstrndx,
1048 shstrtab_compressed == T_COMPRESS_GNU,
1049 true, verbose > 0) < 0)
1050 return cleanup (-1);
1051 }
1052 }
1053
1054 /* Make sure to re-get the new ehdr. Adding phdrs and shdrs will
1055 have changed it. */
1056 if (gelf_getehdr (elfnew, &newehdr) == NULL)
1057 {
1058 error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
1059 return cleanup (-1);
1060 }
1061
1062 /* Set this after the sections have been created, otherwise section
1063 zero might not exist yet. */
1064 if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
1065 {
1066 error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
1067 return cleanup (-1);
1068 }
1069
1070 /* Fixup pass. Adjust string table references, symbol table and
1071 layout if necessary. */
1072 if (layout || adjust_names)
1073 {
1074 scn = NULL;
1075 while ((scn = elf_nextscn (elfnew, scn)) != NULL)
1076 {
1077 size_t ndx = elf_ndxscn (scn);
1078
1079 GElf_Shdr shdr_mem;
1080 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1081 if (shdr == NULL)
1082 {
1083 error (0, 0, "Couldn't get shdr for section %zd", ndx);
1084 return cleanup (-1);
1085 }
1086
1087 /* Keep the offset of allocated sections so they are at the
1088 same place in the file. Add (possibly changed)
1089 unallocated ones after the allocated ones. */
1090 if ((shdr->sh_flags & SHF_ALLOC) == 0)
1091 {
1092 /* Zero means one. No alignment constraints. */
1093 size_t addralign = shdr->sh_addralign ?: 1;
1094 last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
1095 shdr->sh_offset = last_offset;
1096 if (shdr->sh_type != SHT_NOBITS)
1097 last_offset += shdr->sh_size;
1098 }
1099
1100 if (adjust_names)
1101 shdr->sh_name = ebl_strtaboffset (scnstrents[ndx]);
1102
1103 if (gelf_update_shdr (scn, shdr) == 0)
1104 {
1105 error (0, 0, "Couldn't update section header %zd", ndx);
1106 return cleanup (-1);
1107 }
1108
1109 if (adjust_names && ndx == symtabndx)
1110 {
1111 if (verbose > 0)
1112 printf ("[%zd] Updating symbol table\n", symtabndx);
1113
1114 Elf_Data *symd = elf_getdata (scn, NULL);
1115 if (symd == NULL)
1116 {
1117 error (0, 0, "Couldn't get new symtab data section [%zd]",
1118 ndx);
1119 return cleanup (-1);
1120 }
1121 size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
1122 size_t syms = symd->d_size / elsize;
1123 for (size_t i = 0; i < syms; i++)
1124 {
1125 GElf_Sym sym_mem;
1126 GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
1127 if (sym == NULL)
1128 {
1129 error (0, 0, "2 Couldn't get symbol %zd", i);
1130 return cleanup (-1);
1131 }
1132
1133 if (sym->st_name != 0)
1134 {
1135 sym->st_name = ebl_strtaboffset (symstrents[i]);
1136
1137 if (gelf_update_sym (symd, i, sym) == 0)
1138 {
1139 error (0, 0, "Couldn't update symbol %zd", i);
1140 return cleanup (-1);
1141 }
1142 }
1143 }
1144
1145 /* We might have to compress the data if the user asked
1146 us to, or if the section was already compressed (and
1147 the user didn't ask for decompression). Note
1148 somewhat identical code for shstrtab above. */
1149 if (symtab_compressed == T_UNSET)
1150 {
1151 /* The user didn't ask for compression, but maybe it was
1152 compressed in the original ELF file. */
1153 Elf_Scn *oldscn = elf_getscn (elf, symtabndx);
1154 if (oldscn == NULL)
1155 {
1156 error (0, 0, "Couldn't get symbol table [%zd]",
1157 symtabndx);
1158 return cleanup (-1);
1159 }
1160
1161 shdr = gelf_getshdr (oldscn, &shdr_mem);
1162 if (shdr == NULL)
1163 {
1164 error (0, 0, "Couldn't get old symbol table shdr [%zd]",
1165 symtabndx);
1166 return cleanup (-1);
1167 }
1168
1169 symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1170 if (symtab_name == NULL)
1171 {
1172 error (0, 0, "Couldn't get old symbol table name [%zd]",
1173 symtabndx);
1174 return cleanup (-1);
1175 }
1176
1177 symtab_size = shdr->sh_size;
1178 if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1179 symtab_compressed = T_COMPRESS_ZLIB;
1180 else if (strncmp (symtab_name, ".zdebug",
1181 strlen (".zdebug")) == 0)
1182 symtab_compressed = T_COMPRESS_GNU;
1183 }
1184
1185 /* Should we (re)compress? */
1186 if (symtab_compressed != T_UNSET)
1187 {
1188 if (compress_section (scn, symtab_size, symtab_name,
1189 symtab_newname, symtabndx,
1190 symtab_compressed == T_COMPRESS_GNU,
1191 true, verbose > 0) < 0)
1192 return cleanup (-1);
1193 }
1194 }
1195 }
1196 }
1197
1198 /* If we have phdrs we want elf_update to layout the SHF_ALLOC
1199 sections precisely as in the original file. In that case we are
1200 also responsible for setting phoff and shoff */
1201 if (layout)
1202 {
1203 if (gelf_getehdr (elfnew, &newehdr) == NULL)
1204 {
1205 error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
1206 return cleanup (-1);
1207 }
1208
1209 /* Position the shdrs after the last (unallocated) section. */
1210 const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT);
1211 newehdr.e_shoff = ((last_offset + offsize - 1)
1212 & ~((GElf_Off) (offsize - 1)));
1213
1214 /* The phdrs go in the same place as in the original file.
1215 Normally right after the ELF header. */
1216 newehdr.e_phoff = ehdr.e_phoff;
1217
1218 if (gelf_update_ehdr (elfnew, &newehdr) == 0)
1219 {
1220 error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
1221 return cleanup (-1);
1222 }
1223 }
1224
1225 elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0)
1226 | (permissive ? ELF_F_PERMISSIVE : 0)));
1227
1228 if (elf_update (elfnew, ELF_C_WRITE) < 0)
1229 {
1230 error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
1231 return cleanup (-1);
1232 }
1233
1234 elf_end (elfnew);
1235 elfnew = NULL;
1236
1237 /* Try to match mode and owner.group of the original file. */
1238 if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
1239 if (verbose >= 0)
1240 error (0, errno, "Couldn't fchmod %s", fnew);
1241 if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
1242 if (verbose >= 0)
1243 error (0, errno, "Couldn't fchown %s", fnew);
1244
1245 /* Finally replace the old file with the new file. */
1246 if (foutput == NULL)
1247 if (rename (fnew, fname) != 0)
1248 {
1249 error (0, errno, "Couldn't rename %s to %s", fnew, fname);
1250 return cleanup (-1);
1251 }
1252
1253 /* We are finally done with the new file, don't unlink it now. */
1254 free (fnew);
1255 fnew = NULL;
1256
1257 return cleanup (0);
1258 }
1259
1260 int
main(int argc,char ** argv)1261 main (int argc, char **argv)
1262 {
1263 const struct argp_option options[] =
1264 {
1265 { "output", 'o', "FILE", 0,
1266 N_("Place (de)compressed output into FILE"),
1267 0 },
1268 { "type", 't', "TYPE", 0,
1269 N_("What type of compression to apply. TYPE can be 'none' (decompress), 'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias) or 'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias)"),
1270 0 },
1271 { "name", 'n', "SECTION", 0,
1272 N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"),
1273 0 },
1274 { "verbose", 'v', NULL, 0,
1275 N_("Print a message for each section being (de)compressed"),
1276 0 },
1277 { "force", 'f', NULL, 0,
1278 N_("Force compression of section even if it would become larger"),
1279 0 },
1280 { "permissive", 'p', NULL, 0,
1281 N_("Relax a few rules to handle slightly broken ELF files"),
1282 0 },
1283 { "quiet", 'q', NULL, 0,
1284 N_("Be silent when a section cannot be compressed"),
1285 0 },
1286 { NULL, 0, NULL, 0, NULL, 0 }
1287 };
1288
1289 const struct argp argp =
1290 {
1291 .options = options,
1292 .parser = parse_opt,
1293 .args_doc = N_("FILE..."),
1294 .doc = N_("Compress or decompress sections in an ELF file.")
1295 };
1296
1297 int remaining;
1298 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
1299 return EXIT_FAILURE;
1300
1301 /* Should already be handled by ARGP_KEY_NO_ARGS case above,
1302 just sanity check. */
1303 if (remaining >= argc)
1304 error (EXIT_FAILURE, 0, N_("No input file given"));
1305
1306 /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check. */
1307 if (foutput != NULL && remaining + 1 < argc)
1308 error (EXIT_FAILURE, 0,
1309 N_("Only one input file allowed together with '-o'"));
1310
1311 elf_version (EV_CURRENT);
1312
1313 /* Process all the remaining files. */
1314 int result = 0;
1315 do
1316 result |= process_file (argv[remaining]);
1317 while (++remaining < argc);
1318
1319 free_patterns ();
1320 return result;
1321 }
1322