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