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.  */
39static void print_version (FILE *stream, struct argp_state *state);
40ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
41
42/* Bug report address.  */
43ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
44
45static int verbose = 0; /* < 0, no warnings, > 0 extra verbosity.  */
46static bool force = false;
47static bool permissive = false;
48static 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 */
54static int type = T_UNSET;
55
56static void
57print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
58{
59  fprintf (stream, "elfcompress (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
60}
61
62struct section_pattern
63{
64  char *pattern;
65  struct section_pattern *next;
66};
67
68static struct section_pattern *patterns = NULL;
69
70static void
71add_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
79static void
80free_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
92static error_t
93parse_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
162static bool
163section_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
175static int
176setshdrstrndx (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
199static int
200compress_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
248static int
249process_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
1260int
1261main (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