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