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