• 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 			  shstrtab_name = xstrdup (sname);
734 			  shstrtab_newname = xstrdup (newname);
735 			}
736 		      else
737 			{
738 			  symtab_size = size;
739 			  symtab_compressed = T_COMPRESS_GNU;
740 			  symtab_name = xstrdup (sname);
741 			  symtab_newname = xstrdup (newname);
742 			}
743 		    }
744 		  else
745 		    {
746 		      int result = compress_section (scn, size, sname, newname,
747 						     ndx, true, true,
748 						     verbose > 0);
749 		      if (result < 0)
750 			goto cleanup;
751 
752 		      if (result == 0)
753 			newname = NULL;
754 		    }
755 		}
756 	      else if (verbose >= 0)
757 		{
758 		  if (startswith (sname, ".zdebug"))
759 		    printf ("[%zd] %s unchanged, already GNU compressed",
760 			    ndx, sname);
761 		  else
762 		    printf ("[%zd] %s cannot GNU compress section not starting with .debug\n",
763 			    ndx, sname);
764 		}
765 	      break;
766 
767 	    case T_COMPRESS_ZLIB:
768 	      if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
769 		{
770 		  if (startswith (sname, ".zdebug"))
771 		    {
772 		      /* First decompress to recompress zlib style.
773 			 Don't report even when verbose.  */
774 		      if (compress_section (scn, size, sname, NULL, ndx,
775 					    true, false, false) < 0)
776 			goto cleanup;
777 
778 		      snamebuf[0] = '.';
779 		      strcpy (&snamebuf[1], &sname[2]);
780 		      newname = snamebuf;
781 		    }
782 
783 		  if (skip_compress_section)
784 		    {
785 		      if (ndx == shdrstrndx)
786 			{
787 			  shstrtab_size = size;
788 			  shstrtab_compressed = T_COMPRESS_ZLIB;
789 			  shstrtab_name = xstrdup (sname);
790 			  shstrtab_newname = (newname == NULL
791 					      ? NULL : xstrdup (newname));
792 			}
793 		      else
794 			{
795 			  symtab_size = size;
796 			  symtab_compressed = T_COMPRESS_ZLIB;
797 			  symtab_name = xstrdup (sname);
798 			  symtab_newname = (newname == NULL
799 					    ? NULL : xstrdup (newname));
800 			}
801 		    }
802 		  else if (compress_section (scn, size, sname, newname, ndx,
803 					     false, true, verbose > 0) < 0)
804 		    goto cleanup;
805 		}
806 	      else if (verbose > 0)
807 		printf ("[%zd] %s already compressed\n", ndx, sname);
808 	      break;
809 	    }
810 
811 	  free (sname);
812 	}
813 
814       Elf_Scn *newscn = elf_newscn (elfnew);
815       if (newscn == NULL)
816 	{
817 	  error (0, 0, "Couldn't create new section %zd", ndx);
818 	  goto cleanup;
819 	}
820 
821       GElf_Shdr shdr_mem;
822       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
823       if (shdr == NULL)
824 	{
825 	  error (0, 0, "Couldn't get shdr for section %zd", ndx);
826 	  goto cleanup;
827 	}
828 
829       if (gelf_update_shdr (newscn, shdr) == 0)
830         {
831 	  error (0, 0, "Couldn't update section header %zd", ndx);
832 	  goto cleanup;
833 	}
834 
835       /* Except for the section header string table all data can be
836 	 copied as is.  The section header string table will be
837 	 created later and the symbol table might be fixed up if
838 	 necessary.  */
839       if (! adjust_names || ndx != shdrstrndx)
840 	{
841 	  Elf_Data *data = elf_getdata (scn, NULL);
842 	  if (data == NULL)
843 	    {
844 	      error (0, 0, "Couldn't get data from section %zd", ndx);
845 	      goto cleanup;
846 	    }
847 
848 	  Elf_Data *newdata = elf_newdata (newscn);
849 	  if (newdata == NULL)
850 	    {
851 	      error (0, 0, "Couldn't create new data for section %zd", ndx);
852 	      goto cleanup;
853 	    }
854 
855 	  *newdata = *data;
856 	}
857 
858       /* Keep track of the (new) section names.  */
859       if (adjust_names)
860 	{
861 	  char *name;
862 	  if (newname != NULL)
863 	    name = newname;
864 	  else
865 	    {
866 	      name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
867 	      if (name == NULL)
868 		{
869 		  error (0, 0, "Couldn't get name for section [%zd]", ndx);
870 		  goto cleanup;
871 		}
872 	    }
873 
874 	  /* We need to keep a copy of the name till the strtab is done.  */
875 	  name = scnnames[ndx] = xstrdup (name);
876 	  if ((scnstrents[ndx] = dwelf_strtab_add (names, name)) == NULL)
877 	    {
878 	      error (0, 0, "No memory to add section name string table");
879 	      goto cleanup;
880 	    }
881 
882 	  /* If the symtab shares strings then add those too.  */
883 	  if (ndx == symtabndx)
884 	    {
885 	      /* If the section is (still) compressed we'll need to
886 		 uncompress it first to adjust the data, then
887 		 recompress it in the fixup pass.  */
888 	      if (symtab_compressed == T_UNSET)
889 		{
890 		  size_t size = shdr->sh_size;
891 		  if ((shdr->sh_flags == SHF_COMPRESSED) != 0)
892 		    {
893 		      /* Don't report the (internal) uncompression.  */
894 		      if (compress_section (newscn, size, sname, NULL, ndx,
895 					    false, false, false) < 0)
896 			goto cleanup;
897 
898 		      symtab_size = size;
899 		      symtab_compressed = T_COMPRESS_ZLIB;
900 		    }
901 		  else if (startswith (name, ".zdebug"))
902 		    {
903 		      /* Don't report the (internal) uncompression.  */
904 		      if (compress_section (newscn, size, sname, NULL, ndx,
905 					    true, false, false) < 0)
906 			goto cleanup;
907 
908 		      symtab_size = size;
909 		      symtab_compressed = T_COMPRESS_GNU;
910 		    }
911 		}
912 
913 	      Elf_Data *symd = elf_getdata (newscn, NULL);
914 	      if (symd == NULL)
915 		{
916 		  error (0, 0, "Couldn't get symtab data for section [%zd] %s",
917 			 ndx, name);
918 		  goto cleanup;
919 		}
920 	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
921 	      size_t syms = symd->d_size / elsize;
922 	      symstrents = xmalloc (syms * sizeof (Dwelf_Strent *));
923 	      for (size_t i = 0; i < syms; i++)
924 		{
925 		  GElf_Sym sym_mem;
926 		  GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
927 		  if (sym == NULL)
928 		    {
929 		      error (0, 0, "Couldn't get symbol %zd", i);
930 		      goto cleanup;
931 		    }
932 		  if (sym->st_name != 0)
933 		    {
934 		      /* Note we take the name from the original ELF,
935 			 since the new one will not have setup the
936 			 strtab yet.  */
937 		      const char *symname = elf_strptr (elf, shdrstrndx,
938 							sym->st_name);
939 		      if (symname == NULL)
940 			{
941 			  error (0, 0, "Couldn't get symbol %zd name", i);
942 			  goto cleanup;
943 			}
944 		      symstrents[i] = dwelf_strtab_add (names, symname);
945 		      if (symstrents[i] == NULL)
946 			{
947 			  error (0, 0, "No memory to add to symbol name");
948 			  goto cleanup;
949 			}
950 		    }
951 		}
952 	    }
953 	}
954     }
955 
956   if (adjust_names)
957     {
958       /* We got all needed strings, put the new data in the shstrtab.  */
959       if (verbose > 0)
960 	printf ("[%zd] Updating section string table\n", shdrstrndx);
961 
962       scn = elf_getscn (elfnew, shdrstrndx);
963       if (scn == NULL)
964 	{
965 	  error (0, 0, "Couldn't get new section header string table [%zd]",
966 		 shdrstrndx);
967 	  goto cleanup;
968 	}
969 
970       Elf_Data *data = elf_newdata (scn);
971       if (data == NULL)
972 	{
973 	  error (0, 0, "Couldn't create new section header string table data");
974 	  goto cleanup;
975 	}
976       if (dwelf_strtab_finalize (names, data) == NULL)
977 	{
978 	  error (0, 0, "Not enough memory to create string table");
979 	  goto cleanup;
980 	}
981       namesbuf = data->d_buf;
982 
983       GElf_Shdr shdr_mem;
984       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
985       if (shdr == NULL)
986 	{
987 	  error (0, 0, "Couldn't get shdr for new section strings %zd",
988 		 shdrstrndx);
989 	  goto cleanup;
990 	}
991 
992       /* Note that we also might have to compress and possibly set
993 	 sh_off below */
994       shdr->sh_name = dwelf_strent_off (scnstrents[shdrstrndx]);
995       shdr->sh_type = SHT_STRTAB;
996       shdr->sh_flags = 0;
997       shdr->sh_addr = 0;
998       shdr->sh_offset = 0;
999       shdr->sh_size = data->d_size;
1000       shdr->sh_link = SHN_UNDEF;
1001       shdr->sh_info = SHN_UNDEF;
1002       shdr->sh_addralign = 1;
1003       shdr->sh_entsize = 0;
1004 
1005       if (gelf_update_shdr (scn, shdr) == 0)
1006 	{
1007 	  error (0, 0, "Couldn't update new section strings [%zd]",
1008 		 shdrstrndx);
1009 	  goto cleanup;
1010 	}
1011 
1012       /* We might have to compress the data if the user asked us to,
1013 	 or if the section was already compressed (and the user didn't
1014 	 ask for decompression).  Note somewhat identical code for
1015 	 symtab below.  */
1016       if (shstrtab_compressed == T_UNSET)
1017 	{
1018 	  /* The user didn't ask for compression, but maybe it was
1019 	     compressed in the original ELF file.  */
1020 	  Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx);
1021 	  if (oldscn == NULL)
1022 	    {
1023 	      error (0, 0, "Couldn't get section header string table [%zd]",
1024 		     shdrstrndx);
1025 	      goto cleanup;
1026 	    }
1027 
1028 	  shdr = gelf_getshdr (oldscn, &shdr_mem);
1029 	  if (shdr == NULL)
1030 	    {
1031 	      error (0, 0, "Couldn't get shdr for old section strings [%zd]",
1032 		     shdrstrndx);
1033 	      goto cleanup;
1034 	    }
1035 
1036 	  shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1037 	  if (shstrtab_name == NULL)
1038 	    {
1039 	      error (0, 0, "Couldn't get name for old section strings [%zd]",
1040 		     shdrstrndx);
1041 	      goto cleanup;
1042 	    }
1043 
1044 	  shstrtab_size = shdr->sh_size;
1045 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1046 	    shstrtab_compressed = T_COMPRESS_ZLIB;
1047 	  else if (startswith (shstrtab_name, ".zdebug"))
1048 	    shstrtab_compressed = T_COMPRESS_GNU;
1049 	}
1050 
1051       /* Should we (re)compress?  */
1052       if (shstrtab_compressed != T_UNSET)
1053 	{
1054 	  if (compress_section (scn, shstrtab_size, shstrtab_name,
1055 				shstrtab_newname, shdrstrndx,
1056 				shstrtab_compressed == T_COMPRESS_GNU,
1057 				true, verbose > 0) < 0)
1058 	    goto cleanup;
1059 	}
1060     }
1061 
1062   /* Make sure to re-get the new ehdr.  Adding phdrs and shdrs will
1063      have changed it.  */
1064   if (gelf_getehdr (elfnew, &newehdr) == NULL)
1065     {
1066       error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
1067       goto cleanup;
1068     }
1069 
1070   /* Set this after the sections have been created, otherwise section
1071      zero might not exist yet.  */
1072   if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
1073     {
1074       error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
1075       goto cleanup;
1076     }
1077 
1078   /* Fixup pass.  Adjust string table references, symbol table and
1079      layout if necessary.  */
1080   if (layout || adjust_names)
1081     {
1082       scn = NULL;
1083       while ((scn = elf_nextscn (elfnew, scn)) != NULL)
1084 	{
1085 	  size_t ndx = elf_ndxscn (scn);
1086 
1087 	  GElf_Shdr shdr_mem;
1088 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1089 	  if (shdr == NULL)
1090 	    {
1091 	      error (0, 0, "Couldn't get shdr for section %zd", ndx);
1092 	      goto cleanup;
1093 	    }
1094 
1095 	  /* Keep the offset of allocated sections so they are at the
1096 	     same place in the file. Add (possibly changed)
1097 	     unallocated ones after the allocated ones.  */
1098 	  if ((shdr->sh_flags & SHF_ALLOC) == 0)
1099 	    {
1100 	      /* Zero means one.  No alignment constraints.  */
1101 	      size_t addralign = shdr->sh_addralign ?: 1;
1102 	      last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
1103 	      shdr->sh_offset = last_offset;
1104 	      if (shdr->sh_type != SHT_NOBITS)
1105 		last_offset += shdr->sh_size;
1106 	    }
1107 
1108 	  if (adjust_names)
1109 	    shdr->sh_name = dwelf_strent_off (scnstrents[ndx]);
1110 
1111 	  if (gelf_update_shdr (scn, shdr) == 0)
1112 	    {
1113 	      error (0, 0, "Couldn't update section header %zd", ndx);
1114 	      goto cleanup;
1115 	    }
1116 
1117 	  if (adjust_names && ndx == symtabndx)
1118 	    {
1119 	      if (verbose > 0)
1120 		printf ("[%zd] Updating symbol table\n", symtabndx);
1121 
1122 	      Elf_Data *symd = elf_getdata (scn, NULL);
1123 	      if (symd == NULL)
1124 		{
1125 		  error (0, 0, "Couldn't get new symtab data section [%zd]",
1126 			 ndx);
1127 		  goto cleanup;
1128 		}
1129 	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
1130 	      size_t syms = symd->d_size / elsize;
1131 	      for (size_t i = 0; i < syms; i++)
1132 		{
1133 		  GElf_Sym sym_mem;
1134 		  GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
1135 		  if (sym == NULL)
1136 		    {
1137 		      error (0, 0, "2 Couldn't get symbol %zd", i);
1138 		      goto cleanup;
1139 		    }
1140 
1141 		  if (sym->st_name != 0)
1142 		    {
1143 		      sym->st_name = dwelf_strent_off (symstrents[i]);
1144 
1145 		      if (gelf_update_sym (symd, i, sym) == 0)
1146 			{
1147 			  error (0, 0, "Couldn't update symbol %zd", i);
1148 			  goto cleanup;
1149 			}
1150 		    }
1151 		}
1152 
1153 	      /* We might have to compress the data if the user asked
1154 		 us to, or if the section was already compressed (and
1155 		 the user didn't ask for decompression).  Note
1156 		 somewhat identical code for shstrtab above.  */
1157 	      if (symtab_compressed == T_UNSET)
1158 		{
1159 		  /* The user didn't ask for compression, but maybe it was
1160 		     compressed in the original ELF file.  */
1161 		  Elf_Scn *oldscn = elf_getscn (elf, symtabndx);
1162 		  if (oldscn == NULL)
1163 		    {
1164 		      error (0, 0, "Couldn't get symbol table [%zd]",
1165 			     symtabndx);
1166 		      goto cleanup;
1167 		    }
1168 
1169 		  shdr = gelf_getshdr (oldscn, &shdr_mem);
1170 		  if (shdr == NULL)
1171 		    {
1172 		      error (0, 0, "Couldn't get old symbol table shdr [%zd]",
1173 			     symtabndx);
1174 		      goto cleanup;
1175 		    }
1176 
1177 		  symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
1178 		  if (symtab_name == NULL)
1179 		    {
1180 		      error (0, 0, "Couldn't get old symbol table name [%zd]",
1181 			     symtabndx);
1182 		      goto cleanup;
1183 		    }
1184 
1185 		  symtab_size = shdr->sh_size;
1186 		  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1187 		    symtab_compressed = T_COMPRESS_ZLIB;
1188 		  else if (startswith (symtab_name, ".zdebug"))
1189 		    symtab_compressed = T_COMPRESS_GNU;
1190 		}
1191 
1192 	      /* Should we (re)compress?  */
1193 	      if (symtab_compressed != T_UNSET)
1194 		{
1195 		  if (compress_section (scn, symtab_size, symtab_name,
1196 					symtab_newname, symtabndx,
1197 					symtab_compressed == T_COMPRESS_GNU,
1198 					true, verbose > 0) < 0)
1199 		    goto cleanup;
1200 		}
1201 	    }
1202 	}
1203     }
1204 
1205   /* If we have phdrs we want elf_update to layout the SHF_ALLOC
1206      sections precisely as in the original file.  In that case we are
1207      also responsible for setting phoff and shoff */
1208   if (layout)
1209     {
1210       if (gelf_getehdr (elfnew, &newehdr) == NULL)
1211 	{
1212 	  error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
1213 	  goto cleanup;
1214 	}
1215 
1216       /* Position the shdrs after the last (unallocated) section.  */
1217       const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT);
1218       newehdr.e_shoff = ((last_offset + offsize - 1)
1219 			 & ~((GElf_Off) (offsize - 1)));
1220 
1221       /* The phdrs go in the same place as in the original file.
1222 	 Normally right after the ELF header.  */
1223       newehdr.e_phoff = ehdr.e_phoff;
1224 
1225       if (gelf_update_ehdr (elfnew, &newehdr) == 0)
1226 	{
1227 	  error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
1228 	  goto cleanup;
1229 	}
1230     }
1231 
1232   elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0)
1233 				   | (permissive ? ELF_F_PERMISSIVE : 0)));
1234 
1235   if (elf_update (elfnew, ELF_C_WRITE) < 0)
1236     {
1237       error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
1238       goto cleanup;
1239     }
1240 
1241   elf_end (elfnew);
1242   elfnew = NULL;
1243 
1244   /* Try to match mode and owner.group of the original file.
1245      Note to set suid bits we have to make sure the owner is setup
1246      correctly first. Otherwise fchmod will drop them silently
1247      or fchown may clear them.  */
1248   if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
1249     if (verbose >= 0)
1250       error (0, errno, "Couldn't fchown %s", fnew);
1251   if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
1252     if (verbose >= 0)
1253       error (0, errno, "Couldn't fchmod %s", fnew);
1254 
1255   /* Finally replace the old file with the new file.  */
1256   if (foutput == NULL)
1257     if (rename (fnew, fname) != 0)
1258       {
1259 	error (0, errno, "Couldn't rename %s to %s", fnew, fname);
1260 	goto cleanup;
1261       }
1262 
1263   /* We are finally done with the new file, don't unlink it now.  */
1264   free (fnew);
1265   fnew = NULL;
1266   res = 0;
1267 
1268 cleanup:
1269   elf_end (elf);
1270   close (fd);
1271 
1272   elf_end (elfnew);
1273   close (fdnew);
1274 
1275   if (fnew != NULL)
1276     {
1277       unlink (fnew);
1278       free (fnew);
1279       fnew = NULL;
1280     }
1281 
1282   free (snamebuf);
1283   if (names != NULL)
1284     {
1285       dwelf_strtab_free (names);
1286       free (scnstrents);
1287       free (symstrents);
1288       free (namesbuf);
1289       if (scnnames != NULL)
1290 	{
1291 	  for (size_t n = 0; n < shnum; n++)
1292 	    free (scnnames[n]);
1293 	  free (scnnames);
1294 	}
1295     }
1296 
1297   free (sections);
1298   return res;
1299 }
1300 
1301 int
main(int argc,char ** argv)1302 main (int argc, char **argv)
1303 {
1304   const struct argp_option options[] =
1305     {
1306       { "output", 'o', "FILE", 0,
1307 	N_("Place (de)compressed output into FILE"),
1308 	0 },
1309       { "type", 't', "TYPE", 0,
1310 	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)"),
1311 	0 },
1312       { "name", 'n', "SECTION", 0,
1313 	N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"),
1314 	0 },
1315       { "verbose", 'v', NULL, 0,
1316 	N_("Print a message for each section being (de)compressed"),
1317 	0 },
1318       { "force", 'f', NULL, 0,
1319 	N_("Force compression of section even if it would become larger or update/rewrite the file even if no section would be (de)compressed"),
1320 	0 },
1321       { "permissive", 'p', NULL, 0,
1322 	N_("Relax a few rules to handle slightly broken ELF files"),
1323 	0 },
1324       { "quiet", 'q', NULL, 0,
1325 	N_("Be silent when a section cannot be compressed"),
1326 	0 },
1327       { NULL, 0, NULL, 0, NULL, 0 }
1328     };
1329 
1330   const struct argp argp =
1331     {
1332       .options = options,
1333       .parser = parse_opt,
1334       .args_doc = N_("FILE..."),
1335       .doc = N_("Compress or decompress sections in an ELF file.")
1336     };
1337 
1338   int remaining;
1339   if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
1340     return EXIT_FAILURE;
1341 
1342   /* Should already be handled by ARGP_KEY_NO_ARGS case above,
1343      just sanity check.  */
1344   if (remaining >= argc)
1345     error (EXIT_FAILURE, 0, N_("No input file given"));
1346 
1347   /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check.  */
1348   if (foutput != NULL && remaining + 1 < argc)
1349     error (EXIT_FAILURE, 0,
1350 	   N_("Only one input file allowed together with '-o'"));
1351 
1352   elf_version (EV_CURRENT);
1353 
1354   /* Process all the remaining files.  */
1355   int result = 0;
1356   do
1357     result |= process_file (argv[remaining]);
1358   while (++remaining < argc);
1359 
1360   free_patterns ();
1361   return result;
1362 }
1363