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