Home | History | Annotate | Download | only in src
      1 /* Combine stripped files with separate symbols and debug information.
      2    Copyright (C) 2007 Red Hat, Inc.
      3    This file is part of Red Hat elfutils.
      4    Written by Roland McGrath <roland (at) redhat.com>, 2007.
      5 
      6    Red Hat elfutils is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by the
      8    Free Software Foundation; version 2 of the License.
      9 
     10    Red Hat 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 GNU
     13    General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License along
     16    with Red Hat elfutils; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     18 
     19    Red Hat elfutils is an included package of the Open Invention Network.
     20    An included package of the Open Invention Network is a package for which
     21    Open Invention Network licensees cross-license their patents.  No patent
     22    license is granted, either expressly or impliedly, by designation as an
     23    included package.  Should you wish to participate in the Open Invention
     24    Network licensing program, please visit www.openinventionnetwork.com
     25    <http://www.openinventionnetwork.com>.  */
     26 
     27 /* TODO:
     28 
     29   * SHX_XINDEX
     30 
     31   * prelink vs .debug_* linked addresses
     32 
     33  */
     34 
     35 #ifdef HAVE_CONFIG_H
     36 # include <config.h>
     37 #endif
     38 
     39 #include <argp.h>
     40 #include <assert.h>
     41 #include <errno.h>
     42 #include <error.h>
     43 #include <fcntl.h>
     44 #include <fnmatch.h>
     45 #include <libintl.h>
     46 #include <locale.h>
     47 #include <mcheck.h>
     48 #include <stdbool.h>
     49 #include <stdio.h>
     50 #include <stdio_ext.h>
     51 #include <inttypes.h>
     52 #include <stdlib.h>
     53 #include <string.h>
     54 #include <unistd.h>
     55 
     56 #include <gelf.h>
     57 #include <libebl.h>
     58 #include <libdwfl.h>
     59 #include "system.h"
     60 
     61 #ifndef _
     62 # define _(str) gettext (str)
     63 #endif
     64 
     65 /* Name and version of program.  */
     66 static void print_version (FILE *stream, struct argp_state *state);
     67 void (*argp_program_version_hook) (FILE *, struct argp_state *)
     68   = print_version;
     69 
     70 /* Bug report address.  */
     71 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
     72 
     73 /* Definitions of arguments for argp functions.  */
     74 static const struct argp_option options[] =
     75 {
     76   /* Group 2 will follow group 1 from dwfl_standard_argp.  */
     77   { "match-file-names", 'f', NULL, 0,
     78     N_("Match MODULE against file names, not module names"), 2 },
     79   { "ignore-missing", 'i', NULL, 0, N_("Silently skip unfindable files"), 0 },
     80 
     81   { NULL, 0, NULL, 0, N_("Output options:"), 0 },
     82   { "output", 'o', "FILE", 0, N_("Place output into FILE"), 0 },
     83   { "output-directory", 'd', "DIRECTORY",
     84     0, N_("Create multiple output files under DIRECTORY"), 0 },
     85   { "module-names", 'm', NULL, 0, N_("Use module rather than file names"), 0 },
     86   { "all", 'a', NULL, 0,
     87     N_("Create output for modules that have no separate debug information"),
     88     0 },
     89   { "relocate", 'R', NULL, 0,
     90     N_("Apply relocations to section contents in ET_REL files"), 0 },
     91   { "list-only", 'n', NULL, 0,
     92     N_("Only list module and file names, build IDs"), 0 },
     93   { NULL, 0, NULL, 0, NULL, 0 }
     94 };
     95 
     96 struct arg_info
     97 {
     98   const char *output_file;
     99   const char *output_dir;
    100   Dwfl *dwfl;
    101   char **args;
    102   bool list;
    103   bool all;
    104   bool ignore;
    105   bool modnames;
    106   bool match_files;
    107   bool relocate;
    108 };
    109 
    110 /* Handle program arguments.  */
    111 static error_t
    112 parse_opt (int key, char *arg, struct argp_state *state)
    113 {
    114   struct arg_info *info = state->input;
    115 
    116   switch (key)
    117     {
    118     case ARGP_KEY_INIT:
    119       state->child_inputs[0] = &info->dwfl;
    120       break;
    121 
    122     case 'o':
    123       if (info->output_file != NULL)
    124 	{
    125 	  argp_error (state, _("-o option specified twice"));
    126 	  return EINVAL;
    127 	}
    128       info->output_file = arg;
    129       break;
    130 
    131     case 'd':
    132       if (info->output_dir != NULL)
    133 	{
    134 	  argp_error (state, _("-d option specified twice"));
    135 	  return EINVAL;
    136 	}
    137       info->output_dir = arg;
    138       break;
    139 
    140     case 'm':
    141       info->modnames = true;
    142       break;
    143     case 'f':
    144       info->match_files = true;
    145       break;
    146     case 'a':
    147       info->all = true;
    148       break;
    149     case 'i':
    150       info->ignore = true;
    151       break;
    152     case 'n':
    153       info->list = true;
    154       break;
    155     case 'R':
    156       info->relocate = true;
    157       break;
    158 
    159     case ARGP_KEY_ARGS:
    160     case ARGP_KEY_NO_ARGS:
    161       /* We "consume" all the arguments here.  */
    162       info->args = &state->argv[state->next];
    163 
    164       if (info->output_file != NULL && info->output_dir != NULL)
    165 	{
    166 	  argp_error (state, _("only one of -o or -d allowed"));
    167 	  return EINVAL;
    168 	}
    169 
    170       if (info->list && (info->dwfl == NULL
    171 			 || info->output_dir != NULL
    172 			 || info->output_file != NULL))
    173 	{
    174 	  argp_error (state,
    175 		      _("-n cannot be used with explicit files or -o or -d"));
    176 	  return EINVAL;
    177 	}
    178 
    179       if (info->output_dir != NULL)
    180 	{
    181 	  struct stat64 st;
    182 	  error_t fail = 0;
    183 	  if (stat64 (info->output_dir, &st) < 0)
    184 	    fail = errno;
    185 	  else if (!S_ISDIR (st.st_mode))
    186 	    fail = ENOTDIR;
    187 	  if (fail)
    188 	    {
    189 	      argp_failure (state, EXIT_FAILURE, fail,
    190 			    _("output directory '%s'"), info->output_dir);
    191 	      return fail;
    192 	    }
    193 	}
    194 
    195       if (info->dwfl == NULL)
    196 	{
    197 	  if (state->next + 2 != state->argc)
    198 	    {
    199 	      argp_error (state, _("exactly two file arguments are required"));
    200 	      return EINVAL;
    201 	    }
    202 
    203 	  if (info->ignore || info->all || info->modnames || info->relocate)
    204 	    {
    205 	      argp_error (state, _("\
    206 -m, -a, -R, and -i options not allowed with explicit files"));
    207 	      return EINVAL;
    208 	    }
    209 
    210 	  /* Bail out immediately to prevent dwfl_standard_argp's parser
    211 	     from defaulting to "-e a.out".  */
    212 	  return ENOSYS;
    213 	}
    214       else if (info->output_file == NULL && info->output_dir == NULL
    215 	       && !info->list)
    216 	{
    217 	  argp_error (state,
    218 		      _("-o or -d is required when using implicit files"));
    219 	  return EINVAL;
    220 	}
    221       break;
    222 
    223     default:
    224       return ARGP_ERR_UNKNOWN;
    225     }
    226   return 0;
    227 }
    228 
    229 /* Print the version information.  */
    230 static void
    231 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    232 {
    233   fprintf (stream, "unstrip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    234   fprintf (stream, _("\
    235 Copyright (C) %s Red Hat, Inc.\n\
    236 This is free software; see the source for copying conditions.  There is NO\n\
    237 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    238 "), "2008");
    239   fprintf (stream, gettext ("Written by %s.\n"), "Roland McGrath");
    240 }
    241 
    242 #define ELF_CHECK(call, msg)						      \
    244   do									      \
    245     {									      \
    246       if (!(call)) 							      \
    247 	error (EXIT_FAILURE, 0, msg, elf_errmsg (-1));			      \
    248     } while (0)
    249 
    250 /* Copy INELF to newly-created OUTELF, exit via error for any problems.  */
    251 static void
    252 copy_elf (Elf *outelf, Elf *inelf)
    253 {
    254   ELF_CHECK (gelf_newehdr (outelf, gelf_getclass (inelf)),
    255 	     _("cannot create ELF header: %s"));
    256 
    257   GElf_Ehdr ehdr_mem;
    258   GElf_Ehdr *ehdr = gelf_getehdr (inelf, &ehdr_mem);
    259   ELF_CHECK (gelf_update_ehdr (outelf, ehdr),
    260 	     _("cannot copy ELF header: %s"));
    261 
    262   if (ehdr->e_phnum > 0)
    263     {
    264       ELF_CHECK (gelf_newphdr (outelf, ehdr->e_phnum),
    265 		 _("cannot create program headers: %s"));
    266 
    267       GElf_Phdr phdr_mem;
    268       for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
    269 	ELF_CHECK (gelf_update_phdr (outelf, i,
    270 				     gelf_getphdr (inelf, i, &phdr_mem)),
    271 		   _("cannot copy program header: %s"));
    272     }
    273 
    274   Elf_Scn *scn = NULL;
    275   while ((scn = elf_nextscn (inelf, scn)) != NULL)
    276     {
    277       Elf_Scn *newscn = elf_newscn (outelf);
    278 
    279       GElf_Shdr shdr_mem;
    280       ELF_CHECK (gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem)),
    281 		 _("cannot copy section header: %s"));
    282 
    283       Elf_Data *data = elf_getdata (scn, NULL);
    284       ELF_CHECK (data != NULL, _("cannot get section data: %s"));
    285       Elf_Data *newdata = elf_newdata (newscn);
    286       ELF_CHECK (newdata != NULL, _("cannot copy section data: %s"));
    287       *newdata = *data;
    288       elf_flagdata (newdata, ELF_C_SET, ELF_F_DIRTY);
    289     }
    290 }
    291 
    292 /* Create directories containing PATH.  */
    293 static void
    294 make_directories (const char *path)
    295 {
    296   const char *lastslash = strrchr (path, '/');
    297   if (lastslash == NULL)
    298     return;
    299 
    300   while (lastslash > path && lastslash[-1] == '/')
    301     --lastslash;
    302   if (lastslash == path)
    303     return;
    304 
    305   char *dir = strndupa (path, lastslash - path);
    306   while (mkdir (dir, 0777) < 0 && errno != EEXIST)
    307     if (errno == ENOENT)
    308       make_directories (dir);
    309     else
    310       error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir);
    311 }
    312 
    313 
    314 /* The binutils linker leaves gratuitous section symbols in .symtab
    315    that strip has to remove.  Older linkers likewise include a
    316    symbol for every section, even unallocated ones, in .dynsym.
    317    Because of this, the related sections can shrink in the stripped
    318    file from their original size.  Older versions of strip do not
    319    adjust the sh_size field in the debuginfo file's SHT_NOBITS
    320    version of the section header, so it can appear larger.  */
    321 static bool
    322 section_can_shrink (const GElf_Shdr *shdr)
    323 {
    324   switch (shdr->sh_type)
    325     {
    326     case SHT_SYMTAB:
    327     case SHT_DYNSYM:
    328     case SHT_HASH:
    329     case SHT_GNU_versym:
    330       return true;
    331     }
    332   return false;
    333 }
    334 
    335 /* See if this symbol table has a leading section symbol for every single
    336    section, in order.  The binutils linker produces this.  While we're here,
    337    update each section symbol's st_value.  */
    338 static size_t
    339 symtab_count_leading_section_symbols (Elf *elf, Elf_Scn *scn, size_t shnum,
    340 				      Elf_Data *newsymdata)
    341 {
    342   Elf_Data *data = elf_getdata (scn, NULL);
    343   Elf_Data *shndxdata = NULL;	/* XXX */
    344 
    345   for (size_t i = 1; i < shnum; ++i)
    346     {
    347       GElf_Sym sym_mem;
    348       GElf_Word shndx = SHN_UNDEF;
    349       GElf_Sym *sym = gelf_getsymshndx (data, shndxdata, i, &sym_mem, &shndx);
    350       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
    351 
    352       GElf_Shdr shdr_mem;
    353       GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, i), &shdr_mem);
    354       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
    355 
    356       if (sym->st_shndx != SHN_XINDEX)
    357 	shndx = sym->st_shndx;
    358 
    359       if (shndx != i || GELF_ST_TYPE (sym->st_info) != STT_SECTION)
    360 	return i;
    361 
    362       sym->st_value = shdr->sh_addr;
    363       if (sym->st_shndx != SHN_XINDEX)
    364 	shndx = SHN_UNDEF;
    365       ELF_CHECK (gelf_update_symshndx (newsymdata, shndxdata, i, sym, shndx),
    366 		 _("cannot update symbol table: %s"));
    367     }
    368 
    369   return shnum;
    370 }
    371 
    372 /* We expanded the output section, so update its header.  */
    373 static void
    374 update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
    375 {
    376   GElf_Shdr shdr_mem;
    377   GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
    378   ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
    379 
    380   newshdr->sh_size = data->d_size;
    381 
    382   ELF_CHECK (gelf_update_shdr (outscn, newshdr),
    383 	     _("cannot update section header: %s"));
    384 }
    385 
    386 /* Update relocation sections using the symbol table.  */
    387 static void
    388 adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
    389 	       size_t map[], const GElf_Shdr *symshdr)
    390 {
    391   Elf_Data *data = elf_getdata (outscn, NULL);
    392 
    393   inline void adjust_reloc (GElf_Xword *info)
    394     {
    395       size_t ndx = GELF_R_SYM (*info);
    396       if (ndx != STN_UNDEF)
    397 	*info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info));
    398     }
    399 
    400   switch (shdr->sh_type)
    401     {
    402     case SHT_REL:
    403       for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
    404 	{
    405 	  GElf_Rel rel_mem;
    406 	  GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
    407 	  adjust_reloc (&rel->r_info);
    408 	  ELF_CHECK (gelf_update_rel (data, i, rel),
    409 		     _("cannot update relocation: %s"));
    410 	}
    411       break;
    412 
    413     case SHT_RELA:
    414       for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
    415 	{
    416 	  GElf_Rela rela_mem;
    417 	  GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
    418 	  adjust_reloc (&rela->r_info);
    419 	  ELF_CHECK (gelf_update_rela (data, i, rela),
    420 		     _("cannot update relocation: %s"));
    421 	}
    422       break;
    423 
    424     case SHT_GROUP:
    425       {
    426 	GElf_Shdr shdr_mem;
    427 	GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
    428 	ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
    429 	if (newshdr->sh_info != STN_UNDEF)
    430 	  {
    431 	    newshdr->sh_info = map[newshdr->sh_info - 1];
    432 	    ELF_CHECK (gelf_update_shdr (outscn, newshdr),
    433 		       _("cannot update section header: %s"));
    434 	  }
    435 	break;
    436       }
    437 
    438     case SHT_HASH:
    439       /* We must expand the table and rejigger its contents.  */
    440       {
    441 	const size_t nsym = symshdr->sh_size / symshdr->sh_entsize;
    442 	const size_t onent = shdr->sh_size / shdr->sh_entsize;
    443 	assert (data->d_size == shdr->sh_size);
    444 
    445 #define CONVERT_HASH(Hash_Word)						      \
    446 	{								      \
    447 	  const Hash_Word *const old_hash = data->d_buf;		      \
    448 	  const size_t nbucket = old_hash[0];				      \
    449 	  const size_t nchain = old_hash[1];				      \
    450 	  const Hash_Word *const old_bucket = &old_hash[2];		      \
    451 	  const Hash_Word *const old_chain = &old_bucket[nbucket];	      \
    452 	  assert (onent == 2 + nbucket + nchain);			      \
    453 									      \
    454 	  const size_t nent = 2 + nbucket + nsym;			      \
    455 	  Hash_Word *const new_hash = xcalloc (nent, sizeof new_hash[0]);     \
    456 	  Hash_Word *const new_bucket = &new_hash[2];			      \
    457 	  Hash_Word *const new_chain = &new_bucket[nbucket];		      \
    458 									      \
    459 	  new_hash[0] = nbucket;					      \
    460 	  new_hash[1] = nsym;						      \
    461 	  for (size_t i = 0; i < nbucket; ++i)				      \
    462 	    if (old_bucket[i] != STN_UNDEF)				      \
    463 	      new_bucket[i] = map[old_bucket[i] - 1];			      \
    464 									      \
    465 	  for (size_t i = 1; i < nchain; ++i)				      \
    466 	    if (old_chain[i] != STN_UNDEF)				      \
    467 	      new_chain[map[i - 1]] = map[old_chain[i] - 1];		      \
    468 									      \
    469 	  data->d_buf = new_hash;					      \
    470 	  data->d_size = nent * sizeof new_hash[0];			      \
    471 	}
    472 
    473 	switch (shdr->sh_entsize)
    474 	  {
    475 	  case 4:
    476 	    CONVERT_HASH (Elf32_Word);
    477 	    break;
    478 	  case 8:
    479 	    CONVERT_HASH (Elf64_Xword);
    480 	    break;
    481 	  default:
    482 	    abort ();
    483 	  }
    484 
    485 	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
    486 	update_sh_size (outscn, data);
    487 
    488 #undef	CONVERT_HASH
    489       }
    490       break;
    491 
    492     case SHT_GNU_versym:
    493       /* We must expand the table and move its elements around.  */
    494       {
    495 	const size_t nent = symshdr->sh_size / symshdr->sh_entsize;
    496 	const size_t onent = shdr->sh_size / shdr->sh_entsize;
    497 	assert (nent >= onent);
    498 
    499 	/* We don't bother using gelf_update_versym because there is
    500 	   really no conversion to be done.  */
    501 	assert (sizeof (Elf32_Versym) == sizeof (GElf_Versym));
    502 	assert (sizeof (Elf64_Versym) == sizeof (GElf_Versym));
    503 	GElf_Versym *versym = xcalloc (nent, sizeof versym[0]);
    504 
    505 	for (size_t i = 1; i < onent; ++i)
    506 	  {
    507 	    GElf_Versym *v = gelf_getversym (data, i, &versym[map[i - 1]]);
    508 	    ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
    509 	  }
    510 
    511 	data->d_buf = versym;
    512 	data->d_size = nent * shdr->sh_entsize;
    513 	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
    514 	update_sh_size (outscn, data);
    515       }
    516       break;
    517 
    518     default:
    519       error (EXIT_FAILURE, 0,
    520 	     _("unexpected section type in [%Zu] with sh_link to symtab"),
    521 	     elf_ndxscn (inscn));
    522     }
    523 }
    524 
    525 /* Adjust all the relocation sections in the file.  */
    526 static void
    527 adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
    528 		   size_t map[])
    529 {
    530   size_t new_sh_link = elf_ndxscn (symtab);
    531   Elf_Scn *scn = NULL;
    532   while ((scn = elf_nextscn (elf, scn)) != NULL)
    533     if (scn != symtab)
    534       {
    535 	GElf_Shdr shdr_mem;
    536 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    537 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
    538 	if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link)
    539 	  adjust_relocs (scn, scn, shdr, map, symshdr);
    540       }
    541 }
    542 
    543 /* The original file probably had section symbols for all of its
    544    sections, even the unallocated ones.  To match it as closely as
    545    possible, add in section symbols for the added sections.  */
    546 static Elf_Data *
    547 add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
    548 			 Elf *elf, bool rel, Elf_Scn *symscn, size_t shnum)
    549 {
    550   const size_t added = shnum - old_shnum;
    551 
    552   GElf_Shdr shdr_mem;
    553   GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
    554   ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
    555 
    556   const size_t nsym = shdr->sh_size / shdr->sh_entsize;
    557   size_t symndx_map[nsym - 1];
    558 
    559   shdr->sh_info += added;
    560   shdr->sh_size += added * shdr->sh_entsize;
    561 
    562   ELF_CHECK (gelf_update_shdr (symscn, shdr),
    563 	     _("cannot update section header: %s"));
    564 
    565   Elf_Data *symdata = elf_getdata (symscn, NULL);
    566   Elf_Data *shndxdata = NULL;	/* XXX */
    567 
    568   symdata->d_size = shdr->sh_size;
    569   symdata->d_buf = xmalloc (symdata->d_size);
    570 
    571   /* Copy the existing section symbols.  */
    572   Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
    573   for (size_t i = 0; i < old_shnum; ++i)
    574     {
    575       GElf_Sym sym_mem;
    576       GElf_Word shndx = SHN_UNDEF;
    577       GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
    578 					i, &sym_mem, &shndx);
    579       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
    580 				       sym, shndx),
    581 		 _("cannot update symbol table: %s"));
    582 
    583       if (i > 0)
    584 	symndx_map[i - 1] = i;
    585     }
    586 
    587   /* Add in the new section symbols.  */
    588   for (size_t i = old_shnum; i < shnum; ++i)
    589     {
    590       GElf_Shdr i_shdr_mem;
    591       GElf_Shdr *i_shdr = gelf_getshdr (elf_getscn (elf, i), &i_shdr_mem);
    592       ELF_CHECK (i_shdr != NULL, _("cannot get section header: %s"));
    593       GElf_Sym sym =
    594 	{
    595 	  .st_value = rel ? 0 : i_shdr->sh_addr,
    596 	  .st_info = GELF_ST_INFO (STB_LOCAL, STT_SECTION),
    597 	  .st_shndx = i < SHN_LORESERVE ? i : SHN_XINDEX
    598 	};
    599       GElf_Word shndx = i < SHN_LORESERVE ? SHN_UNDEF : i;
    600       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
    601 				       &sym, shndx),
    602 		 _("cannot update symbol table: %s"));
    603     }
    604 
    605   /* Now copy the rest of the existing symbols.  */
    606   for (size_t i = old_shnum; i < nsym; ++i)
    607     {
    608       GElf_Sym sym_mem;
    609       GElf_Word shndx = SHN_UNDEF;
    610       GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
    611 					i, &sym_mem, &shndx);
    612       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata,
    613 				       i + added, sym, shndx),
    614 		 _("cannot update symbol table: %s"));
    615 
    616       symndx_map[i - 1] = i + added;
    617     }
    618 
    619   /* Adjust any relocations referring to the old symbol table.  */
    620   adjust_all_relocs (elf, symscn, shdr, symndx_map);
    621 
    622   return symdata;
    623 }
    624 
    625 /* This has the side effect of updating STT_SECTION symbols' values,
    626    in case of prelink adjustments.  */
    627 static Elf_Data *
    628 check_symtab_section_symbols (Elf *elf, bool rel, Elf_Scn *scn,
    629 			      size_t shnum, size_t shstrndx,
    630 			      Elf_Scn *oscn, size_t oshnum, size_t oshstrndx,
    631 			      size_t debuglink)
    632 {
    633   size_t n = symtab_count_leading_section_symbols (elf, oscn, oshnum,
    634 						   elf_getdata (scn, NULL));
    635 
    636   if (n == oshnum)
    637     return add_new_section_symbols (oscn, n, elf, rel, scn, shnum);
    638 
    639   if (n == oshstrndx || (n == debuglink && n == oshstrndx - 1))
    640     return add_new_section_symbols (oscn, n, elf, rel, scn, shstrndx);
    641 
    642   return NULL;
    643 }
    644 
    645 struct section
    647 {
    648   Elf_Scn *scn;
    649   const char *name;
    650   Elf_Scn *outscn;
    651   struct Ebl_Strent *strent;
    652   GElf_Shdr shdr;
    653 };
    654 
    655 static int
    656 compare_alloc_sections (const struct section *s1, const struct section *s2,
    657 			bool rel)
    658 {
    659   if (!rel)
    660     {
    661       /* Sort by address.  */
    662       if (s1->shdr.sh_addr < s2->shdr.sh_addr)
    663 	return -1;
    664       if (s1->shdr.sh_addr > s2->shdr.sh_addr)
    665 	return 1;
    666     }
    667 
    668   /* At the same address, preserve original section order.  */
    669   return (ssize_t) elf_ndxscn (s1->scn) - (ssize_t) elf_ndxscn (s2->scn);
    670 }
    671 
    672 static int
    673 compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2,
    674 			  const char *name1, const char *name2)
    675 {
    676   /* Sort by sh_flags as an arbitrary ordering.  */
    677   if (shdr1->sh_flags < shdr2->sh_flags)
    678     return -1;
    679   if (shdr1->sh_flags > shdr2->sh_flags)
    680     return 1;
    681 
    682   /* Sort by name as last resort.  */
    683   return strcmp (name1, name2);
    684 }
    685 
    686 static int
    687 compare_sections (const void *a, const void *b, bool rel)
    688 {
    689   const struct section *s1 = a;
    690   const struct section *s2 = b;
    691 
    692   /* Sort all non-allocated sections last.  */
    693   if ((s1->shdr.sh_flags ^ s2->shdr.sh_flags) & SHF_ALLOC)
    694     return (s1->shdr.sh_flags & SHF_ALLOC) ? -1 : 1;
    695 
    696   return ((s1->shdr.sh_flags & SHF_ALLOC)
    697 	  ? compare_alloc_sections (s1, s2, rel)
    698 	  : compare_unalloc_sections (&s1->shdr, &s2->shdr,
    699 				      s1->name, s2->name));
    700 }
    701 
    702 static int
    703 compare_sections_rel (const void *a, const void *b)
    704 {
    705   return compare_sections (a, b, true);
    706 }
    707 
    708 int
    709 compare_sections_nonrel (const void *a, const void *b)
    710 {
    711   return compare_sections (a, b, false);
    712 }
    713 
    714 
    715 struct symbol
    716 {
    717   size_t *map;
    718 
    719   union
    720   {
    721     const char *name;
    722     struct Ebl_Strent *strent;
    723   };
    724   union
    725   {
    726     struct
    727     {
    728       GElf_Addr value;
    729       GElf_Xword size;
    730       GElf_Word shndx;
    731       union
    732       {
    733 	struct
    734 	{
    735 	  uint8_t info;
    736 	  uint8_t other;
    737 	} info;
    738 	int16_t compare;
    739       };
    740     };
    741 
    742     /* For a symbol discarded after first sort, this matches its better's
    743        map pointer.  */
    744     size_t *duplicate;
    745   };
    746 };
    747 
    748 /* Collect input symbols into our internal form.  */
    749 static void
    750 collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, Elf_Scn *strscn,
    751 		 const size_t nent, const GElf_Addr bias,
    752 		 const size_t scnmap[], struct symbol *table, size_t *map,
    753 		 struct section *split_bss)
    754 {
    755   Elf_Data *symdata = elf_getdata (symscn, NULL);
    756   Elf_Data *strdata = elf_getdata (strscn, NULL);
    757   Elf_Data *shndxdata = NULL;	/* XXX */
    758 
    759   for (size_t i = 1; i < nent; ++i)
    760     {
    761       GElf_Sym sym_mem;
    762       GElf_Word shndx = SHN_UNDEF;
    763       GElf_Sym *sym = gelf_getsymshndx (symdata, shndxdata, i,
    764 					&sym_mem, &shndx);
    765       ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
    766       if (sym->st_shndx != SHN_XINDEX)
    767 	shndx = sym->st_shndx;
    768 
    769       if (sym->st_name >= strdata->d_size)
    770 	error (EXIT_FAILURE, 0,
    771 	       _("invalid string offset in symbol [%Zu]"), i);
    772 
    773       struct symbol *s = &table[i - 1];
    774       s->map = &map[i - 1];
    775       s->name = strdata->d_buf + sym->st_name;
    776       s->value = sym->st_value + bias;
    777       s->size = sym->st_size;
    778       s->shndx = shndx;
    779       s->info.info = sym->st_info;
    780       s->info.other = sym->st_other;
    781 
    782       if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
    783 	s->shndx = scnmap[shndx - 1];
    784 
    785       if (GELF_ST_TYPE (s->info.info) == STT_SECTION && !rel)
    786 	{
    787 	  /* Update the value to match the output section.  */
    788 	  GElf_Shdr shdr_mem;
    789 	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (outelf, s->shndx),
    790 					  &shdr_mem);
    791 	  ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
    792 	  s->value = shdr->sh_addr;
    793 	}
    794       else if (split_bss != NULL
    795 	       && s->value < split_bss->shdr.sh_addr
    796 	       && s->value >= split_bss[-1].shdr.sh_addr
    797 	       && shndx == elf_ndxscn (split_bss->outscn))
    798 	/* This symbol was in .bss and was split into .dynbss.  */
    799 	s->shndx = elf_ndxscn (split_bss[-1].outscn);
    800     }
    801 }
    802 
    803 
    804 #define CMP(value)							      \
    805   if (s1->value < s2->value)						      \
    806     return -1;								      \
    807   if (s1->value > s2->value)						      \
    808     return 1
    809 
    810 /* Compare symbols with a consistent ordering,
    811    but one only meaningful for equality.  */
    812 static int
    813 compare_symbols (const void *a, const void *b)
    814 {
    815   const struct symbol *s1 = a;
    816   const struct symbol *s2 = b;
    817 
    818   CMP (value);
    819   CMP (size);
    820   CMP (shndx);
    821 
    822   return (s1->compare - s2->compare) ?: strcmp (s1->name, s2->name);
    823 }
    824 
    825 /* Compare symbols for output order after slots have been assigned.  */
    826 static int
    827 compare_symbols_output (const void *a, const void *b)
    828 {
    829   const struct symbol *s1 = a;
    830   const struct symbol *s2 = b;
    831   int cmp;
    832 
    833   /* Sort discarded symbols last.  */
    834   cmp = (s1->name == NULL) - (s2->name == NULL);
    835 
    836   if (cmp == 0)
    837     /* Local symbols must come first.  */
    838     cmp = ((GELF_ST_BIND (s2->info.info) == STB_LOCAL)
    839 	   - (GELF_ST_BIND (s1->info.info) == STB_LOCAL));
    840 
    841   if (cmp == 0)
    842     /* binutils always puts section symbols first.  */
    843     cmp = ((GELF_ST_TYPE (s2->info.info) == STT_SECTION)
    844 	   - (GELF_ST_TYPE (s1->info.info) == STT_SECTION));
    845 
    846   if (cmp == 0)
    847     {
    848       if (GELF_ST_TYPE (s1->info.info) == STT_SECTION)
    849 	{
    850 	  /* binutils always puts section symbols in section index order.  */
    851 	  CMP (shndx);
    852 	  else
    853 	    assert (s1 == s2);
    854 	}
    855 
    856       /* Nothing really matters, so preserve the original order.  */
    857       CMP (map);
    858       else
    859 	assert (s1 == s2);
    860     }
    861 
    862   return cmp;
    863 }
    864 
    865 #undef CMP
    866 
    867 /* Return true iff the flags, size, and name match.  */
    868 static bool
    869 sections_match (const struct section *sections, size_t i,
    870 		const GElf_Shdr *shdr, const char *name)
    871 {
    872   return (sections[i].shdr.sh_flags == shdr->sh_flags
    873 	  && (sections[i].shdr.sh_size == shdr->sh_size
    874 	      || (sections[i].shdr.sh_size < shdr->sh_size
    875 		  && section_can_shrink (&sections[i].shdr)))
    876 	  && !strcmp (sections[i].name, name));
    877 }
    878 
    879 /* Locate a matching allocated section in SECTIONS.  */
    880 static struct section *
    881 find_alloc_section (const GElf_Shdr *shdr, GElf_Addr bias, const char *name,
    882 		    struct section sections[], size_t nalloc)
    883 {
    884   const GElf_Addr addr = shdr->sh_addr + bias;
    885   size_t l = 0, u = nalloc;
    886   while (l < u)
    887     {
    888       size_t i = (l + u) / 2;
    889       if (addr < sections[i].shdr.sh_addr)
    890 	u = i;
    891       else if (addr > sections[i].shdr.sh_addr)
    892 	l = i + 1;
    893       else
    894 	{
    895 	  /* We've found allocated sections with this address.
    896 	     Find one with matching size, flags, and name.  */
    897 	  while (i > 0 && sections[i - 1].shdr.sh_addr == addr)
    898 	    --i;
    899 	  for (; i < nalloc && sections[i].shdr.sh_addr == addr;
    900 	       ++i)
    901 	    if (sections_match (sections, i, shdr, name))
    902 	      return &sections[i];
    903 	  break;
    904 	}
    905     }
    906   return NULL;
    907 }
    908 
    909 static inline const char *
    910 get_section_name (size_t ndx, const GElf_Shdr *shdr, const Elf_Data *shstrtab)
    911 {
    912   if (shdr->sh_name >= shstrtab->d_size)
    913     error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"),
    914 	   ndx, elf_errmsg (-1));
    915   return shstrtab->d_buf + shdr->sh_name;
    916 }
    917 
    918 /* Fix things up when prelink has moved some allocated sections around
    919    and the debuginfo file's section headers no longer match up.
    920    This fills in SECTIONS[0..NALLOC-1].outscn or exits.
    921    If there was a .bss section that was split into two sections
    922    with the new one preceding it in sh_addr, we return that pointer.  */
    923 static struct section *
    924 find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
    925 			     Elf *main, const GElf_Ehdr *main_ehdr,
    926 			     Elf_Data *main_shstrtab, GElf_Addr bias,
    927 			     struct section *sections,
    928 			     size_t nalloc, size_t nsections)
    929 {
    930   /* Clear assignments that might have been bogus.  */
    931   for (size_t i = 0; i < nalloc; ++i)
    932     sections[i].outscn = NULL;
    933 
    934   Elf_Scn *undo = NULL;
    935   for (size_t i = nalloc; i < nsections; ++i)
    936     {
    937       const struct section *sec = &sections[i];
    938       if (sec->shdr.sh_type == SHT_PROGBITS
    939 	  && !(sec->shdr.sh_flags & SHF_ALLOC)
    940 	  && !strcmp (sec->name, ".gnu.prelink_undo"))
    941 	{
    942 	  undo = sec->scn;
    943 	  break;
    944 	}
    945     }
    946 
    947   /* Find the original allocated sections before prelinking.  */
    948   struct section *undo_sections = NULL;
    949   size_t undo_nalloc = 0;
    950   if (undo != NULL)
    951     {
    952       Elf_Data *undodata = elf_rawdata (undo, NULL);
    953       ELF_CHECK (undodata != NULL,
    954 		 _("cannot read '.gnu.prelink_undo' section: %s"));
    955 
    956       union
    957       {
    958 	Elf32_Ehdr e32;
    959 	Elf64_Ehdr e64;
    960       } ehdr;
    961       Elf_Data dst =
    962 	{
    963 	  .d_buf = &ehdr,
    964 	  .d_size = sizeof ehdr,
    965 	  .d_type = ELF_T_EHDR,
    966 	  .d_version = EV_CURRENT
    967 	};
    968       Elf_Data src = *undodata;
    969       src.d_size = gelf_fsize (main, ELF_T_EHDR, 1, EV_CURRENT);
    970       src.d_type = ELF_T_EHDR;
    971       ELF_CHECK (gelf_xlatetom (main, &dst, &src,
    972 				main_ehdr->e_ident[EI_DATA]) != NULL,
    973 		 _("cannot read '.gnu.prelink_undo' section: %s"));
    974 
    975       uint_fast16_t phnum;
    976       uint_fast16_t shnum;
    977       if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
    978 	{
    979 	  phnum = ehdr.e32.e_phnum;
    980 	  shnum = ehdr.e32.e_shnum;
    981 	}
    982       else
    983 	{
    984 	  phnum = ehdr.e64.e_phnum;
    985 	  shnum = ehdr.e64.e_shnum;
    986 	}
    987 
    988       size_t phsize = gelf_fsize (main, ELF_T_PHDR, phnum, EV_CURRENT);
    989       src.d_buf += src.d_size + phsize;
    990       src.d_size = gelf_fsize (main, ELF_T_SHDR, shnum - 1, EV_CURRENT);
    991       src.d_type = ELF_T_SHDR;
    992       if ((size_t) (src.d_buf - undodata->d_buf) > undodata->d_size
    993 	  || undodata->d_size - (src.d_buf - undodata->d_buf) != src.d_size)
    994 	error (EXIT_FAILURE, 0, _("invalid contents in '%s' section"),
    995 	       ".gnu.prelink_undo");
    996 
    997       union
    998       {
    999 	Elf32_Shdr s32[shnum - 1];
   1000 	Elf64_Shdr s64[shnum - 1];
   1001       } shdr;
   1002       dst.d_buf = &shdr;
   1003       dst.d_size = sizeof shdr;
   1004       ELF_CHECK (gelf_xlatetom (main, &dst, &src,
   1005 				main_ehdr->e_ident[EI_DATA]) != NULL,
   1006 		 _("cannot read '.gnu.prelink_undo' section: %s"));
   1007 
   1008       undo_sections = xmalloc ((shnum - 1) * sizeof undo_sections[0]);
   1009       for (size_t i = 0; i < shnum - 1; ++i)
   1010 	{
   1011 	  struct section *sec = &undo_sections[undo_nalloc];
   1012 	  if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
   1013 	    {
   1014 #define COPY(field) sec->shdr.field = shdr.s32[i].field
   1015 	      COPY (sh_name);
   1016 	      COPY (sh_type);
   1017 	      COPY (sh_flags);
   1018 	      COPY (sh_addr);
   1019 	      COPY (sh_offset);
   1020 	      COPY (sh_size);
   1021 	      COPY (sh_link);
   1022 	      COPY (sh_info);
   1023 	      COPY (sh_addralign);
   1024 	      COPY (sh_entsize);
   1025 #undef	COPY
   1026 	    }
   1027 	  else
   1028 	    sec->shdr = shdr.s64[i];
   1029 	  if (sec->shdr.sh_flags & SHF_ALLOC)
   1030 	    {
   1031 	      sec->shdr.sh_addr += bias;
   1032 	      sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab);
   1033 	      sec->scn = elf_getscn (main, i + 1); /* Really just for ndx.  */
   1034 	      sec->outscn = NULL;
   1035 	      sec->strent = NULL;
   1036 	      ++undo_nalloc;
   1037 	    }
   1038 	}
   1039       qsort (undo_sections, undo_nalloc,
   1040 	     sizeof undo_sections[0], compare_sections_nonrel);
   1041     }
   1042 
   1043   bool fail = false;
   1044   inline void check_match (bool match, Elf_Scn *scn, const char *name)
   1045     {
   1046       if (!match)
   1047 	{
   1048 	  fail = true;
   1049 	  error (0, 0, _("cannot find matching section for [%Zu] '%s'"),
   1050 		 elf_ndxscn (scn), name);
   1051 	}
   1052     }
   1053 
   1054   Elf_Scn *scn = NULL;
   1055   while ((scn = elf_nextscn (debug, scn)) != NULL)
   1056     {
   1057       GElf_Shdr shdr_mem;
   1058       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1059       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1060 
   1061       if (!(shdr->sh_flags & SHF_ALLOC))
   1062 	continue;
   1063 
   1064       const char *name = get_section_name (elf_ndxscn (scn), shdr,
   1065 					   debug_shstrtab);
   1066 
   1067       if (undo_sections != NULL)
   1068 	{
   1069 	  struct section *sec = find_alloc_section (shdr, 0, name,
   1070 						    undo_sections,
   1071 						    undo_nalloc);
   1072 	  if (sec != NULL)
   1073 	    {
   1074 	      sec->outscn = scn;
   1075 	      continue;
   1076 	    }
   1077 	}
   1078 
   1079       /* If there is no prelink info, we are just here to find
   1080 	 the sections to give error messages about.  */
   1081       for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
   1082 	if (sections[i].outscn == scn)
   1083 	  shdr = NULL;
   1084       check_match (shdr == NULL, scn, name);
   1085     }
   1086 
   1087   if (fail)
   1088     exit (EXIT_FAILURE);
   1089 
   1090   /* Now we have lined up output sections for each of the original sections
   1091      before prelinking.  Translate those to the prelinked sections.
   1092      This matches what prelink's undo_sections does.  */
   1093   struct section *split_bss = NULL;
   1094   for (size_t i = 0; i < undo_nalloc; ++i)
   1095     {
   1096       const struct section *undo_sec = &undo_sections[i];
   1097 
   1098       const char *name = undo_sec->name;
   1099       scn = undo_sec->scn; /* This is just for elf_ndxscn.  */
   1100 
   1101       for (size_t j = 0; j < nalloc; ++j)
   1102 	{
   1103 	  struct section *sec = &sections[j];
   1104 #define RELA_SCALED(field) \
   1105 	  (2 * sec->shdr.field == 3 * undo_sec->shdr.field)
   1106 	  if (sec->outscn == NULL
   1107 	      && sec->shdr.sh_name == undo_sec->shdr.sh_name
   1108 	      && sec->shdr.sh_flags == undo_sec->shdr.sh_flags
   1109 	      && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign
   1110 	      && (((sec->shdr.sh_type == undo_sec->shdr.sh_type
   1111 		    && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
   1112 		    && (sec->shdr.sh_size == undo_sec->shdr.sh_size
   1113 			|| (sec->shdr.sh_size > undo_sec->shdr.sh_size
   1114 			    && main_ehdr->e_type == ET_EXEC
   1115 			    && !strcmp (sec->name, ".dynstr"))))
   1116 		   || (sec->shdr.sh_size == undo_sec->shdr.sh_size
   1117 		       && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
   1118 			    && undo_sec->shdr.sh_type == SHT_NOBITS)
   1119 			   || undo_sec->shdr.sh_type == SHT_PROGBITS)
   1120 		       && !strcmp (sec->name, ".plt")))
   1121 		  || (sec->shdr.sh_type == SHT_RELA
   1122 		      && undo_sec->shdr.sh_type == SHT_REL
   1123 		      && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size))
   1124 		  || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
   1125 		      && (sec->shdr.sh_type == undo_sec->shdr.sh_type
   1126 			  || (sec->shdr.sh_type == SHT_PROGBITS
   1127 			      && undo_sec->shdr.sh_type == SHT_NOBITS))
   1128 		      && sec->shdr.sh_size < undo_sec->shdr.sh_size
   1129 		      && (!strcmp (sec->name, ".bss")
   1130 			  || !strcmp (sec->name, ".sbss"))
   1131 		      && (split_bss = sec) > sections)))
   1132 	    {
   1133 	      sec->outscn = undo_sec->outscn;
   1134 	      undo_sec = NULL;
   1135 	      break;
   1136 	    }
   1137 	}
   1138 
   1139       check_match (undo_sec == NULL, scn, name);
   1140     }
   1141 
   1142   free (undo_sections);
   1143 
   1144   if (fail)
   1145     exit (EXIT_FAILURE);
   1146 
   1147   return split_bss;
   1148 }
   1149 
   1150 /* Create new .shstrtab contents, subroutine of copy_elided_sections.
   1151    This can't be open coded there and still use variable-length auto arrays,
   1152    since the end of our block would free other VLAs too.  */
   1153 static Elf_Data *
   1154 new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
   1155 	      Elf_Data *shstrtab, size_t unstripped_shstrndx,
   1156 	      struct section *sections, size_t stripped_shnum,
   1157 	      struct Ebl_Strtab *strtab)
   1158 {
   1159   if (strtab == NULL)
   1160     return NULL;
   1161 
   1162   struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
   1163   memset (unstripped_strent, 0, sizeof unstripped_strent);
   1164   for (struct section *sec = sections;
   1165        sec < &sections[stripped_shnum - 1];
   1166        ++sec)
   1167     if (sec->outscn != NULL)
   1168       {
   1169 	if (sec->strent == NULL)
   1170 	  {
   1171 	    sec->strent = ebl_strtabadd (strtab, sec->name, 0);
   1172 	    ELF_CHECK (sec->strent != NULL,
   1173 		       _("cannot add section name to string table: %s"));
   1174 	  }
   1175 	unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
   1176       }
   1177 
   1178   /* Add names of sections we aren't touching.  */
   1179   for (size_t i = 0; i < unstripped_shnum - 1; ++i)
   1180     if (unstripped_strent[i] == NULL)
   1181       {
   1182 	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
   1183 	GElf_Shdr shdr_mem;
   1184 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1185 	const char *name = get_section_name (i + 1, shdr, shstrtab);
   1186 	unstripped_strent[i] = ebl_strtabadd (strtab, name, 0);
   1187 	ELF_CHECK (unstripped_strent[i] != NULL,
   1188 		   _("cannot add section name to string table: %s"));
   1189       }
   1190     else
   1191       unstripped_strent[i] = NULL;
   1192 
   1193   /* Now finalize the string table so we can get offsets.  */
   1194   Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
   1195 						   unstripped_shstrndx), NULL);
   1196   ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
   1197 	     _("cannot update section header string table data: %s"));
   1198   ebl_strtabfinalize (strtab, strtab_data);
   1199 
   1200   /* Update the sh_name fields of sections we aren't modifying later.  */
   1201   for (size_t i = 0; i < unstripped_shnum - 1; ++i)
   1202     if (unstripped_strent[i] != NULL)
   1203       {
   1204 	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
   1205 	GElf_Shdr shdr_mem;
   1206 	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1207 	shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]);
   1208 	if (i + 1 == unstripped_shstrndx)
   1209 	  shdr->sh_size = strtab_data->d_size;
   1210 	ELF_CHECK (gelf_update_shdr (scn, shdr),
   1211 		   _("cannot update section header: %s"));
   1212       }
   1213 
   1214   return strtab_data;
   1215 }
   1216 
   1217 /* Fill in any SHT_NOBITS sections in UNSTRIPPED by
   1218    copying their contents and sh_type from STRIPPED.  */
   1219 static void
   1220 copy_elided_sections (Elf *unstripped, Elf *stripped,
   1221 		      const GElf_Ehdr *stripped_ehdr, GElf_Addr bias)
   1222 {
   1223   size_t unstripped_shstrndx;
   1224   ELF_CHECK (elf_getshstrndx (unstripped, &unstripped_shstrndx) == 0,
   1225 	     _("cannot get section header string table section index: %s"));
   1226 
   1227   size_t stripped_shstrndx;
   1228   ELF_CHECK (elf_getshstrndx (stripped, &stripped_shstrndx) == 0,
   1229 	     _("cannot get section header string table section index: %s"));
   1230 
   1231   size_t unstripped_shnum;
   1232   ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0,
   1233 	     _("cannot get section count: %s"));
   1234 
   1235   size_t stripped_shnum;
   1236   ELF_CHECK (elf_getshnum (stripped, &stripped_shnum) == 0,
   1237 	     _("cannot get section count: %s"));
   1238 
   1239   /* Cache the stripped file's section details.  */
   1240   struct section sections[stripped_shnum - 1];
   1241   Elf_Scn *scn = NULL;
   1242   while ((scn = elf_nextscn (stripped, scn)) != NULL)
   1243     {
   1244       size_t i = elf_ndxscn (scn) - 1;
   1245       GElf_Shdr *shdr = gelf_getshdr (scn, &sections[i].shdr);
   1246       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1247       sections[i].name = elf_strptr (stripped, stripped_shstrndx,
   1248 				     shdr->sh_name);
   1249       if (sections[i].name == NULL)
   1250 	error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"),
   1251 	       elf_ndxscn (scn), elf_errmsg (-1));
   1252       sections[i].scn = scn;
   1253       sections[i].outscn = NULL;
   1254       sections[i].strent = NULL;
   1255     }
   1256 
   1257   const struct section *stripped_symtab = NULL;
   1258 
   1259   /* Sort the sections, allocated by address and others after.  */
   1260   qsort (sections, stripped_shnum - 1, sizeof sections[0],
   1261 	 stripped_ehdr->e_type == ET_REL
   1262 	 ? compare_sections_rel : compare_sections_nonrel);
   1263   size_t nalloc = stripped_shnum - 1;
   1264   while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
   1265     {
   1266       --nalloc;
   1267       if (sections[nalloc].shdr.sh_type == SHT_SYMTAB)
   1268 	stripped_symtab = &sections[nalloc];
   1269     }
   1270 
   1271   /* Locate a matching unallocated section in SECTIONS.  */
   1272   inline struct section *find_unalloc_section (const GElf_Shdr *shdr,
   1273 					       const char *name)
   1274     {
   1275       size_t l = nalloc, u = stripped_shnum - 1;
   1276       while (l < u)
   1277 	{
   1278 	  size_t i = (l + u) / 2;
   1279 	  struct section *sec = &sections[i];
   1280 	  int cmp = compare_unalloc_sections (shdr, &sec->shdr,
   1281 					      name, sec->name);
   1282 	  if (cmp < 0)
   1283 	    u = i;
   1284 	  else if (cmp > 0)
   1285 	    l = i + 1;
   1286 	  else
   1287 	    return sec;
   1288 	}
   1289       return NULL;
   1290     }
   1291 
   1292   Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
   1293 						unstripped_shstrndx), NULL);
   1294   ELF_CHECK (shstrtab != NULL,
   1295 	     _("cannot read section header string table: %s"));
   1296 
   1297   /* Match each debuginfo section with its corresponding stripped section.  */
   1298   bool check_prelink = false;
   1299   Elf_Scn *unstripped_symtab = NULL;
   1300   size_t unstripped_strtab_ndx = SHN_UNDEF;
   1301   size_t alloc_avail = 0;
   1302   scn = NULL;
   1303   while ((scn = elf_nextscn (unstripped, scn)) != NULL)
   1304     {
   1305       GElf_Shdr shdr_mem;
   1306       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1307       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1308 
   1309       if (shdr->sh_type == SHT_SYMTAB)
   1310 	{
   1311 	  unstripped_symtab = scn;
   1312 	  unstripped_strtab_ndx = shdr->sh_link;
   1313 	  continue;
   1314 	}
   1315 
   1316       const size_t ndx = elf_ndxscn (scn);
   1317       if (ndx == unstripped_shstrndx)
   1318 	continue;
   1319 
   1320       const char *name = get_section_name (ndx, shdr, shstrtab);
   1321 
   1322       struct section *sec = NULL;
   1323       if (shdr->sh_flags & SHF_ALLOC)
   1324 	{
   1325 	  if (stripped_ehdr->e_type != ET_REL)
   1326 	    {
   1327 	      /* Look for the section that matches.  */
   1328 	      sec = find_alloc_section (shdr, bias, name, sections, nalloc);
   1329 	      if (sec == NULL)
   1330 		{
   1331 		  /* We couldn't figure it out.  It may be a prelink issue.  */
   1332 		  check_prelink = true;
   1333 		  continue;
   1334 		}
   1335 	    }
   1336 	  else
   1337 	    {
   1338 	      /* The sh_addr of allocated sections does not help us,
   1339 		 but the order usually matches.  */
   1340 	      if (likely (sections_match (sections, alloc_avail, shdr, name)))
   1341 		sec = &sections[alloc_avail++];
   1342 	      else
   1343 		for (size_t i = alloc_avail + 1; i < nalloc; ++i)
   1344 		  if (sections_match (sections, i, shdr, name))
   1345 		    {
   1346 		      sec = &sections[i];
   1347 		      break;
   1348 		    }
   1349 	    }
   1350 	}
   1351       else
   1352 	{
   1353 	  /* Look for the section that matches.  */
   1354 	  sec = find_unalloc_section (shdr, name);
   1355 	  if (sec == NULL)
   1356 	    {
   1357 	      /* An additional unallocated section is fine if not SHT_NOBITS.
   1358 		 We looked it up anyway in case it's an unallocated section
   1359 		 copied in both files (e.g. SHT_NOTE), and don't keep both.  */
   1360 	      if (shdr->sh_type != SHT_NOBITS)
   1361 		continue;
   1362 
   1363 	      /* Somehow some old .debug files wound up with SHT_NOBITS
   1364 		 .comment sections, so let those pass.  */
   1365 	      if (!strcmp (name, ".comment"))
   1366 		continue;
   1367 	    }
   1368 	}
   1369 
   1370       if (sec == NULL)
   1371 	error (EXIT_FAILURE, 0,
   1372 	       _("cannot find matching section for [%Zu] '%s'"),
   1373 	       elf_ndxscn (scn), name);
   1374 
   1375       sec->outscn = scn;
   1376     }
   1377 
   1378   /* If that failed due to changes made by prelink, we take another tack.
   1379      We keep track of a .bss section that was partly split into .dynbss
   1380      so that collect_symbols can update symbols' st_shndx fields.  */
   1381   struct section *split_bss = NULL;
   1382   if (check_prelink)
   1383     {
   1384       Elf_Data *data = elf_getdata (elf_getscn (stripped, stripped_shstrndx),
   1385 				    NULL);
   1386       ELF_CHECK (data != NULL,
   1387 		 _("cannot read section header string table: %s"));
   1388       split_bss = find_alloc_sections_prelink (unstripped, shstrtab,
   1389 					       stripped, stripped_ehdr,
   1390 					       data, bias, sections,
   1391 					       nalloc, stripped_shnum - 1);
   1392     }
   1393 
   1394   /* Make sure each main file section has a place to go.  */
   1395   const struct section *stripped_dynsym = NULL;
   1396   size_t debuglink = SHN_UNDEF;
   1397   size_t ndx_section[stripped_shnum - 1];
   1398   struct Ebl_Strtab *strtab = NULL;
   1399   for (struct section *sec = sections;
   1400        sec < &sections[stripped_shnum - 1];
   1401        ++sec)
   1402     {
   1403       size_t secndx = elf_ndxscn (sec->scn);
   1404 
   1405       if (sec->outscn == NULL)
   1406 	{
   1407 	  /* We didn't find any corresponding section for this.  */
   1408 
   1409 	  if (secndx == stripped_shstrndx)
   1410 	    {
   1411 	      /* We only need one .shstrtab.  */
   1412 	      ndx_section[secndx - 1] = unstripped_shstrndx;
   1413 	      continue;
   1414 	    }
   1415 
   1416 	  if (unstripped_symtab != NULL && sec == stripped_symtab)
   1417 	    {
   1418 	      /* We don't need a second symbol table.  */
   1419 	      ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab);
   1420 	      continue;
   1421 	    }
   1422 
   1423 	  if (unstripped_symtab != NULL && stripped_symtab != NULL
   1424 	      && secndx == stripped_symtab->shdr.sh_link)
   1425 	    {
   1426 	      /* ... nor its string table.  */
   1427 	      GElf_Shdr shdr_mem;
   1428 	      GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
   1429 	      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1430 	      ndx_section[secndx - 1] = shdr->sh_link;
   1431 	      continue;
   1432 	    }
   1433 
   1434 	  if (!(sec->shdr.sh_flags & SHF_ALLOC)
   1435 	      && !strcmp (sec->name, ".gnu_debuglink"))
   1436 	    {
   1437 	      /* This was created by stripping.  We don't want it.  */
   1438 	      debuglink = secndx;
   1439 	      ndx_section[secndx - 1] = SHN_UNDEF;
   1440 	      continue;
   1441 	    }
   1442 
   1443 	  sec->outscn = elf_newscn (unstripped);
   1444 	  Elf_Data *newdata = elf_newdata (sec->outscn);
   1445 	  ELF_CHECK (newdata != NULL && gelf_update_shdr (sec->outscn,
   1446 							  &sec->shdr),
   1447 		     _("cannot add new section: %s"));
   1448 
   1449 	  if (strtab == NULL)
   1450 	    strtab = ebl_strtabinit (true);
   1451 	  sec->strent = ebl_strtabadd (strtab, sec->name, 0);
   1452 	  ELF_CHECK (sec->strent != NULL,
   1453 		     _("cannot add section name to string table: %s"));
   1454 	}
   1455 
   1456       /* Cache the mapping of original section indices to output sections.  */
   1457       ndx_section[secndx - 1] = elf_ndxscn (sec->outscn);
   1458     }
   1459 
   1460   /* We added some sections, so we need a new shstrtab.  */
   1461   Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum,
   1462 					shstrtab, unstripped_shstrndx,
   1463 					sections, stripped_shnum,
   1464 					strtab);
   1465 
   1466   /* Get the updated section count.  */
   1467   ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0,
   1468 	     _("cannot get section count: %s"));
   1469 
   1470   bool placed[unstripped_shnum - 1];
   1471   memset (placed, 0, sizeof placed);
   1472 
   1473   /* Now update the output sections and copy in their data.  */
   1474   GElf_Off offset = 0;
   1475   for (const struct section *sec = sections;
   1476        sec < &sections[stripped_shnum - 1];
   1477        ++sec)
   1478     if (sec->outscn != NULL)
   1479       {
   1480 	GElf_Shdr shdr_mem;
   1481 	GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem);
   1482 	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1483 
   1484 	/* In an ET_REL file under --relocate, the sh_addr of SHF_ALLOC
   1485 	   sections will have been set nonzero by relocation.  This
   1486 	   touched the shdrs of whichever file had the symtab.  sh_addr
   1487 	   is still zero in the corresponding shdr.  The relocated
   1488 	   address is what we want to use.  */
   1489 	if (stripped_ehdr->e_type != ET_REL
   1490 	    || !(shdr_mem.sh_flags & SHF_ALLOC)
   1491 	    || shdr_mem.sh_addr == 0)
   1492 	  shdr_mem.sh_addr = sec->shdr.sh_addr;
   1493 
   1494 	shdr_mem.sh_type = sec->shdr.sh_type;
   1495 	shdr_mem.sh_size = sec->shdr.sh_size;
   1496 	shdr_mem.sh_info = sec->shdr.sh_info;
   1497 	shdr_mem.sh_link = sec->shdr.sh_link;
   1498 	if (sec->shdr.sh_link != SHN_UNDEF)
   1499 	  shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
   1500 	if (shdr_mem.sh_flags & SHF_INFO_LINK)
   1501 	  shdr_mem.sh_info = ndx_section[sec->shdr.sh_info - 1];
   1502 
   1503 	if (strtab != NULL)
   1504 	  shdr_mem.sh_name = ebl_strtaboffset (sec->strent);
   1505 
   1506 	Elf_Data *indata = elf_getdata (sec->scn, NULL);
   1507 	ELF_CHECK (indata != NULL, _("cannot get section data: %s"));
   1508 	Elf_Data *outdata = elf_getdata (sec->outscn, NULL);
   1509 	ELF_CHECK (outdata != NULL, _("cannot copy section data: %s"));
   1510 	*outdata = *indata;
   1511 	elf_flagdata (outdata, ELF_C_SET, ELF_F_DIRTY);
   1512 
   1513 	/* Preserve the file layout of the allocated sections.  */
   1514 	if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
   1515 	  {
   1516 	    shdr_mem.sh_offset = sec->shdr.sh_offset;
   1517 	    placed[elf_ndxscn (sec->outscn) - 1] = true;
   1518 
   1519 	    const GElf_Off end_offset = (shdr_mem.sh_offset
   1520 					 + (shdr_mem.sh_type == SHT_NOBITS
   1521 					    ? 0 : shdr_mem.sh_size));
   1522 	    if (end_offset > offset)
   1523 	      offset = end_offset;
   1524 	  }
   1525 
   1526 	ELF_CHECK (gelf_update_shdr (sec->outscn, &shdr_mem),
   1527 		   _("cannot update section header: %s"));
   1528 
   1529 	if (shdr_mem.sh_type == SHT_SYMTAB || shdr_mem.sh_type == SHT_DYNSYM)
   1530 	  {
   1531 	    /* We must adjust all the section indices in the symbol table.  */
   1532 
   1533 	    Elf_Data *shndxdata = NULL;	/* XXX */
   1534 
   1535 	    for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i)
   1536 	      {
   1537 		GElf_Sym sym_mem;
   1538 		GElf_Word shndx = SHN_UNDEF;
   1539 		GElf_Sym *sym = gelf_getsymshndx (outdata, shndxdata,
   1540 						  i, &sym_mem, &shndx);
   1541 		ELF_CHECK (sym != NULL,
   1542 			   _("cannot get symbol table entry: %s"));
   1543 		if (sym->st_shndx != SHN_XINDEX)
   1544 		  shndx = sym->st_shndx;
   1545 
   1546 		if (shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
   1547 		  {
   1548 		    if (shndx >= stripped_shnum)
   1549 		      error (EXIT_FAILURE, 0,
   1550 			     _("symbol [%Zu] has invalid section index"), i);
   1551 
   1552 		    shndx = ndx_section[shndx - 1];
   1553 		    if (shndx < SHN_LORESERVE)
   1554 		      {
   1555 			sym->st_shndx = shndx;
   1556 			shndx = SHN_UNDEF;
   1557 		      }
   1558 		    else
   1559 		      sym->st_shndx = SHN_XINDEX;
   1560 
   1561 		    ELF_CHECK (gelf_update_symshndx (outdata, shndxdata,
   1562 						     i, sym, shndx),
   1563 			       _("cannot update symbol table: %s"));
   1564 		  }
   1565 	      }
   1566 
   1567 	    if (shdr_mem.sh_type == SHT_SYMTAB)
   1568 	      stripped_symtab = sec;
   1569 	    if (shdr_mem.sh_type == SHT_DYNSYM)
   1570 	      stripped_dynsym = sec;
   1571 	  }
   1572       }
   1573 
   1574   /* We may need to update the symbol table.  */
   1575   Elf_Data *symdata = NULL;
   1576   struct Ebl_Strtab *symstrtab = NULL;
   1577   Elf_Data *symstrdata = NULL;
   1578   if (unstripped_symtab != NULL && (stripped_symtab != NULL
   1579 				    || check_prelink /* Section adjustments. */
   1580 				    || (stripped_ehdr->e_type != ET_REL
   1581 					&& bias != 0)))
   1582     {
   1583       /* Merge the stripped file's symbol table into the unstripped one.  */
   1584       const size_t stripped_nsym = (stripped_symtab == NULL ? 1
   1585 				    : (stripped_symtab->shdr.sh_size
   1586 				       / stripped_symtab->shdr.sh_entsize));
   1587 
   1588       GElf_Shdr shdr_mem;
   1589       GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
   1590       ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1591       const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize;
   1592 
   1593       /* First collect all the symbols from both tables.  */
   1594 
   1595       const size_t total_syms = stripped_nsym - 1 + unstripped_nsym - 1;
   1596       struct symbol symbols[total_syms];
   1597       size_t symndx_map[total_syms];
   1598 
   1599       if (stripped_symtab != NULL)
   1600 	collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
   1601 			 stripped_symtab->scn,
   1602 			 elf_getscn (stripped, stripped_symtab->shdr.sh_link),
   1603 			 stripped_nsym, 0, ndx_section,
   1604 			 symbols, symndx_map, NULL);
   1605 
   1606       Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link);
   1607       collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
   1608 		       unstripped_symtab, unstripped_strtab, unstripped_nsym,
   1609 		       stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL,
   1610 		       &symbols[stripped_nsym - 1],
   1611 		       &symndx_map[stripped_nsym - 1], split_bss);
   1612 
   1613       /* Next, sort our array of all symbols.  */
   1614       qsort (symbols, total_syms, sizeof symbols[0], compare_symbols);
   1615 
   1616       /* Now we can weed out the duplicates.  Assign remaining symbols
   1617 	 new slots, collecting a map from old indices to new.  */
   1618       size_t nsym = 0;
   1619       for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s)
   1620 	{
   1621 	  /* Skip a section symbol for a removed section.  */
   1622 	  if (s->shndx == SHN_UNDEF
   1623 	      && GELF_ST_TYPE (s->info.info) == STT_SECTION)
   1624 	    {
   1625 	      s->name = NULL;	/* Mark as discarded. */
   1626 	      *s->map = STN_UNDEF;
   1627 	      s->duplicate = NULL;
   1628 	      continue;
   1629 	    }
   1630 
   1631 	  struct symbol *n = s;
   1632 	  while (n + 1 < &symbols[total_syms] && !compare_symbols (s, n + 1))
   1633 	    ++n;
   1634 
   1635 	  while (s < n)
   1636 	    {
   1637 	      /* This is a duplicate.  Its twin will get the next slot.  */
   1638 	      s->name = NULL;	/* Mark as discarded. */
   1639 	      s->duplicate = n->map;
   1640 	      ++s;
   1641 	    }
   1642 
   1643 	  /* Allocate the next slot.  */
   1644 	  *s->map = ++nsym;
   1645 	}
   1646 
   1647       /* Now we sort again, to determine the order in the output.  */
   1648       qsort (symbols, total_syms, sizeof symbols[0], compare_symbols_output);
   1649 
   1650       if (nsym < total_syms)
   1651 	/* The discarded symbols are now at the end of the table.  */
   1652 	assert (symbols[nsym].name == NULL);
   1653 
   1654       /* Now a final pass updates the map with the final order,
   1655 	 and builds up the new string table.  */
   1656       symstrtab = ebl_strtabinit (true);
   1657       for (size_t i = 0; i < nsym; ++i)
   1658 	{
   1659 	  assert (symbols[i].name != NULL);
   1660 	  assert (*symbols[i].map != 0);
   1661 	  *symbols[i].map = 1 + i;
   1662 	  symbols[i].strent = ebl_strtabadd (symstrtab, symbols[i].name, 0);
   1663 	}
   1664 
   1665       /* Scan the discarded symbols too, just to update their slots
   1666 	 in SYMNDX_MAP to refer to their live duplicates.  */
   1667       for (size_t i = nsym; i < total_syms; ++i)
   1668 	{
   1669 	  assert (symbols[i].name == NULL);
   1670 	  if (symbols[i].duplicate == NULL)
   1671 	    assert (*symbols[i].map == STN_UNDEF);
   1672 	  else
   1673 	    {
   1674 	      assert (*symbols[i].duplicate != STN_UNDEF);
   1675 	      *symbols[i].map = *symbols[i].duplicate;
   1676 	    }
   1677 	}
   1678 
   1679       /* Now we are ready to write the new symbol table.  */
   1680       symdata = elf_getdata (unstripped_symtab, NULL);
   1681       symstrdata = elf_getdata (unstripped_strtab, NULL);
   1682       Elf_Data *shndxdata = NULL;	/* XXX */
   1683 
   1684       ebl_strtabfinalize (symstrtab, symstrdata);
   1685       elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY);
   1686 
   1687       shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
   1688       symdata->d_buf = xmalloc (symdata->d_size);
   1689 
   1690       GElf_Sym sym;
   1691       memset (&sym, 0, sizeof sym);
   1692       ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 0, &sym, SHN_UNDEF),
   1693 		 _("cannot update symbol table: %s"));
   1694 
   1695       shdr->sh_info = 1;
   1696       for (size_t i = 0; i < nsym; ++i)
   1697 	{
   1698 	  struct symbol *s = &symbols[i];
   1699 
   1700 	  /* Fill in the symbol details.  */
   1701 	  sym.st_name = ebl_strtaboffset (s->strent);
   1702 	  sym.st_value = s->value; /* Already biased to output address.  */
   1703 	  sym.st_size = s->size;
   1704 	  sym.st_shndx = s->shndx; /* Already mapped to output index.  */
   1705 	  sym.st_info = s->info.info;
   1706 	  sym.st_other = s->info.other;
   1707 
   1708 	  /* Keep track of the number of leading local symbols.  */
   1709 	  if (GELF_ST_BIND (sym.st_info) == STB_LOCAL)
   1710 	    {
   1711 	      assert (shdr->sh_info == 1 + i);
   1712 	      shdr->sh_info = 1 + i + 1;
   1713 	    }
   1714 
   1715 	  ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 1 + i,
   1716 					   &sym, SHN_UNDEF),
   1717 		     _("cannot update symbol table: %s"));
   1718 
   1719 	}
   1720       elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY);
   1721       ELF_CHECK (gelf_update_shdr (unstripped_symtab, shdr),
   1722 		 _("cannot update section header: %s"));
   1723 
   1724       if (stripped_symtab != NULL)
   1725 	{
   1726 	  /* Adjust any relocations referring to the old symbol table.  */
   1727 	  const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn);
   1728 	  for (const struct section *sec = sections;
   1729 	       sec < &sections[stripped_shnum - 1];
   1730 	       ++sec)
   1731 	    if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link)
   1732 	      adjust_relocs (sec->outscn, sec->scn, &sec->shdr,
   1733 			     symndx_map, shdr);
   1734 	}
   1735 
   1736       /* Also adjust references to the other old symbol table.  */
   1737       adjust_all_relocs (unstripped, unstripped_symtab, shdr,
   1738 			 &symndx_map[stripped_nsym - 1]);
   1739     }
   1740   else if (stripped_symtab != NULL && stripped_shnum != unstripped_shnum)
   1741     check_symtab_section_symbols (unstripped,
   1742 				  stripped_ehdr->e_type == ET_REL,
   1743 				  stripped_symtab->scn,
   1744 				  unstripped_shnum, unstripped_shstrndx,
   1745 				  stripped_symtab->outscn,
   1746 				  stripped_shnum, stripped_shstrndx,
   1747 				  debuglink);
   1748 
   1749   if (stripped_dynsym != NULL)
   1750     (void) check_symtab_section_symbols (unstripped,
   1751 					 stripped_ehdr->e_type == ET_REL,
   1752 					 stripped_dynsym->outscn,
   1753 					 unstripped_shnum,
   1754 					 unstripped_shstrndx,
   1755 					 stripped_dynsym->scn, stripped_shnum,
   1756 					 stripped_shstrndx, debuglink);
   1757 
   1758   /* We need to preserve the layout of the stripped file so the
   1759      phdrs will match up.  This requires us to do our own layout of
   1760      the added sections.  We do manual layout even for ET_REL just
   1761      so we can try to match what the original probably had.  */
   1762 
   1763   elf_flagelf (unstripped, ELF_C_SET, ELF_F_LAYOUT);
   1764 
   1765   if (offset == 0)
   1766     /* For ET_REL we are starting the layout from scratch.  */
   1767     offset = gelf_fsize (unstripped, ELF_T_EHDR, 1, EV_CURRENT);
   1768 
   1769   bool skip_reloc = false;
   1770   do
   1771     {
   1772       skip_reloc = !skip_reloc;
   1773       for (size_t i = 0; i < unstripped_shnum - 1; ++i)
   1774 	if (!placed[i])
   1775 	  {
   1776 	    scn = elf_getscn (unstripped, 1 + i);
   1777 
   1778 	    GElf_Shdr shdr_mem;
   1779 	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
   1780 	    ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
   1781 
   1782 	    if (skip_reloc
   1783 		&& (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
   1784 	      continue;
   1785 
   1786 	    GElf_Off align = shdr->sh_addralign ?: 1;
   1787 	    offset = (offset + align - 1) & -align;
   1788 	    shdr->sh_offset = offset;
   1789 	    if (shdr->sh_type != SHT_NOBITS)
   1790 	      offset += shdr->sh_size;
   1791 
   1792 	    ELF_CHECK (gelf_update_shdr (scn, shdr),
   1793 		       _("cannot update section header: %s"));
   1794 
   1795 	    if (unstripped_shstrndx == 1 + i)
   1796 	      {
   1797 		/* Place the section headers immediately after
   1798 		   .shstrtab, and update the ELF header.  */
   1799 
   1800 		GElf_Ehdr ehdr_mem;
   1801 		GElf_Ehdr *ehdr = gelf_getehdr (unstripped, &ehdr_mem);
   1802 		ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
   1803 
   1804 		GElf_Off sh_align = gelf_getclass (unstripped) * 4;
   1805 		offset = (offset + sh_align - 1) & -sh_align;
   1806 		ehdr->e_shnum = unstripped_shnum;
   1807 		ehdr->e_shoff = offset;
   1808 		offset += unstripped_shnum * ehdr->e_shentsize;
   1809 		ELF_CHECK (gelf_update_ehdr (unstripped, ehdr),
   1810 			   _("cannot update ELF header: %s"));
   1811 	      }
   1812 
   1813 	    placed[i] = true;
   1814 	  }
   1815     } while (skip_reloc);
   1816 
   1817   if (stripped_ehdr->e_phnum > 0)
   1818     ELF_CHECK (gelf_newphdr (unstripped, stripped_ehdr->e_phnum),
   1819 	       _("cannot create program headers: %s"));
   1820 
   1821   /* Copy each program header from the stripped file.  */
   1822   for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i)
   1823     {
   1824       GElf_Phdr phdr_mem;
   1825       GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
   1826       ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
   1827 
   1828       ELF_CHECK (gelf_update_phdr (unstripped, i, phdr),
   1829 		 _("cannot update program header: %s"));
   1830     }
   1831 
   1832   /* Finally, write out the file.  */
   1833   ELF_CHECK (elf_update (unstripped, ELF_C_WRITE) > 0,
   1834 	     _("cannot write output file: %s"));
   1835 
   1836   if (strtab != NULL)
   1837     {
   1838       ebl_strtabfree (strtab);
   1839       free (strtab_data->d_buf);
   1840     }
   1841 
   1842   if (symdata != NULL)
   1843     free (symdata->d_buf);
   1844   if (symstrtab != NULL)
   1845     {
   1846       ebl_strtabfree (symstrtab);
   1847       free (symstrdata->d_buf);
   1848     }
   1849 }
   1850 
   1851 /* Process one pair of files, already opened.  */
   1852 static void
   1853 handle_file (const char *output_file, bool create_dirs,
   1854 	     Elf *stripped, const GElf_Ehdr *stripped_ehdr,
   1855 	     Elf *unstripped)
   1856 {
   1857   /* Determine the address bias between the debuginfo file and the main
   1858      file, which may have been modified by prelinking.  */
   1859   GElf_Addr bias = 0;
   1860   if (unstripped != NULL)
   1861     for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i)
   1862       {
   1863 	GElf_Phdr phdr_mem;
   1864 	GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
   1865 	ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
   1866 	if (phdr->p_type == PT_LOAD)
   1867 	  {
   1868 	    GElf_Phdr unstripped_phdr_mem;
   1869 	    GElf_Phdr *unstripped_phdr = gelf_getphdr (unstripped, i,
   1870 						       &unstripped_phdr_mem);
   1871 	    ELF_CHECK (unstripped_phdr != NULL,
   1872 		       _("cannot get program header: %s"));
   1873 	    bias = phdr->p_vaddr - unstripped_phdr->p_vaddr;
   1874 	    break;
   1875 	  }
   1876       }
   1877 
   1878   /* One day we could adjust all the DWARF data (like prelink itself does).  */
   1879   if (bias != 0)
   1880     {
   1881       if (output_file == NULL)
   1882 	error (0, 0, _("\
   1883 DWARF data not adjusted for prelinking bias; consider prelink -u"));
   1884       else
   1885 	error (0, 0, _("\
   1886 DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"),
   1887 	       output_file);
   1888     }
   1889 
   1890   if (output_file == NULL)
   1891     /* Modify the unstripped file in place.  */
   1892     copy_elided_sections (unstripped, stripped, stripped_ehdr, bias);
   1893   else
   1894     {
   1895       if (create_dirs)
   1896 	make_directories (output_file);
   1897 
   1898       /* Copy the unstripped file and then modify it.  */
   1899       int outfd = open64 (output_file, O_RDWR | O_CREAT,
   1900 			  stripped_ehdr->e_type == ET_REL ? 0666 : 0777);
   1901       if (outfd < 0)
   1902 	error (EXIT_FAILURE, errno, _("cannot open '%s'"), output_file);
   1903       Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
   1904       ELF_CHECK (outelf != NULL, _("cannot create ELF descriptor: %s"));
   1905 
   1906       if (unstripped == NULL)
   1907 	{
   1908 	  /* Actually, we are just copying out the main file as it is.  */
   1909 	  copy_elf (outelf, stripped);
   1910 	  if (stripped_ehdr->e_type != ET_REL)
   1911 	    elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);
   1912 	  ELF_CHECK (elf_update (outelf, ELF_C_WRITE) > 0,
   1913 		     _("cannot write output file: %s"));
   1914 	}
   1915       else
   1916 	{
   1917 	  copy_elf (outelf, unstripped);
   1918 	  copy_elided_sections (outelf, stripped, stripped_ehdr, bias);
   1919 	}
   1920 
   1921       elf_end (outelf);
   1922       close (outfd);
   1923     }
   1924 }
   1925 
   1926 static int
   1927 open_file (const char *file, bool writable)
   1928 {
   1929   int fd = open64 (file, writable ? O_RDWR : O_RDONLY);
   1930   if (fd < 0)
   1931     error (EXIT_FAILURE, errno, _("cannot open '%s'"), file);
   1932   return fd;
   1933 }
   1934 
   1935 /* Handle a pair of files we need to open by name.  */
   1936 static void
   1937 handle_explicit_files (const char *output_file, bool create_dirs,
   1938 		       const char *stripped_file, const char *unstripped_file)
   1939 {
   1940   int stripped_fd = open_file (stripped_file, false);
   1941   Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
   1942   GElf_Ehdr stripped_ehdr;
   1943   ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
   1944 	     _("cannot create ELF descriptor: %s"));
   1945 
   1946   int unstripped_fd = -1;
   1947   Elf *unstripped = NULL;
   1948   if (unstripped_file != NULL)
   1949     {
   1950       unstripped_fd = open_file (unstripped_file, output_file == NULL);
   1951       unstripped = elf_begin (unstripped_fd,
   1952 			      (output_file == NULL ? ELF_C_RDWR : ELF_C_READ),
   1953 			      NULL);
   1954       GElf_Ehdr unstripped_ehdr;
   1955       ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
   1956 		 _("cannot create ELF descriptor: %s"));
   1957 
   1958       if (memcmp (stripped_ehdr.e_ident, unstripped_ehdr.e_ident, EI_NIDENT)
   1959 	  || stripped_ehdr.e_type != unstripped_ehdr.e_type
   1960 	  || stripped_ehdr.e_machine != unstripped_ehdr.e_machine
   1961 	  || stripped_ehdr.e_phnum != unstripped_ehdr.e_phnum)
   1962 	error (EXIT_FAILURE, 0, _("'%s' and '%s' do not seem to match"),
   1963 	       stripped_file, unstripped_file);
   1964     }
   1965 
   1966   handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
   1967 
   1968   elf_end (stripped);
   1969   close (stripped_fd);
   1970 
   1971   elf_end (unstripped);
   1972   close (unstripped_fd);
   1973 }
   1974 
   1975 
   1976 /* Handle a pair of files opened implicitly by libdwfl for one module.  */
   1977 static void
   1978 handle_dwfl_module (const char *output_file, bool create_dirs,
   1979 		    Dwfl_Module *mod, bool all, bool ignore, bool relocate)
   1980 {
   1981   GElf_Addr bias;
   1982   Elf *stripped = dwfl_module_getelf (mod, &bias);
   1983   if (stripped == NULL)
   1984     {
   1985       if (ignore)
   1986 	return;
   1987 
   1988       const char *file;
   1989       const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
   1990 					      NULL, NULL, &file, NULL);
   1991       if (file == NULL)
   1992 	error (EXIT_FAILURE, 0,
   1993 	       _("cannot find stripped file for module '%s': %s"),
   1994 	       modname, dwfl_errmsg (-1));
   1995       else
   1996 	error (EXIT_FAILURE, 0,
   1997 	       _("cannot open stripped file '%s' for module '%s': %s"),
   1998 	       modname, file, dwfl_errmsg (-1));
   1999     }
   2000 
   2001   Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias));
   2002   if (debug == NULL && !all)
   2003     {
   2004       if (ignore)
   2005 	return;
   2006 
   2007       const char *file;
   2008       const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
   2009 					      NULL, NULL, NULL, &file);
   2010       if (file == NULL)
   2011 	error (EXIT_FAILURE, 0,
   2012 	       _("cannot find debug file for module '%s': %s"),
   2013 	       modname, dwfl_errmsg (-1));
   2014       else
   2015 	error (EXIT_FAILURE, 0,
   2016 	       _("cannot open debug file '%s' for module '%s': %s"),
   2017 	       modname, file, dwfl_errmsg (-1));
   2018     }
   2019 
   2020   if (debug == stripped)
   2021     {
   2022       if (all)
   2023 	debug = NULL;
   2024       else
   2025 	{
   2026 	  const char *file;
   2027 	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
   2028 						  NULL, NULL, &file, NULL);
   2029 	  error (EXIT_FAILURE, 0, _("module '%s' file '%s' is not stripped"),
   2030 		 modname, file);
   2031 	}
   2032     }
   2033 
   2034   GElf_Ehdr stripped_ehdr;
   2035   ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
   2036 	     _("cannot create ELF descriptor: %s"));
   2037 
   2038   if (stripped_ehdr.e_type == ET_REL)
   2039     {
   2040       if (!relocate)
   2041 	{
   2042 	  /* We can't use the Elf handles already open,
   2043 	     because the DWARF sections have been relocated.  */
   2044 
   2045 	  const char *stripped_file = NULL;
   2046 	  const char *unstripped_file = NULL;
   2047 	  (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
   2048 				   &stripped_file, &unstripped_file);
   2049 
   2050 	  handle_explicit_files (output_file, create_dirs,
   2051 				 stripped_file, unstripped_file);
   2052 	  return;
   2053 	}
   2054 
   2055       /* Relocation is what we want!  This ensures that all sections that can
   2056 	 get sh_addr values assigned have them, even ones not used in DWARF.
   2057 	 They might still be used in the symbol table.  */
   2058       if (dwfl_module_relocations (mod) < 0)
   2059 	error (EXIT_FAILURE, 0,
   2060 	       _("cannot cache section addresses for module '%s': %s"),
   2061 	       dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
   2062 	       dwfl_errmsg (-1));
   2063     }
   2064 
   2065   handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug);
   2066 }
   2067 
   2068 /* Handle one module being written to the output directory.  */
   2069 static void
   2070 handle_output_dir_module (const char *output_dir, Dwfl_Module *mod,
   2071 			  bool all, bool ignore, bool modnames, bool relocate)
   2072 {
   2073   if (! modnames)
   2074     {
   2075       /* Make sure we've searched for the ELF file.  */
   2076       GElf_Addr bias;
   2077       (void) dwfl_module_getelf (mod, &bias);
   2078     }
   2079 
   2080   const char *file;
   2081   const char *name = dwfl_module_info (mod, NULL, NULL, NULL,
   2082 				       NULL, NULL, &file, NULL);
   2083 
   2084   if (file == NULL && ignore)
   2085     return;
   2086 
   2087   char *output_file;
   2088   if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0)
   2089     error (EXIT_FAILURE, 0, _("memory exhausted"));
   2090 
   2091   handle_dwfl_module (output_file, true, mod, all, ignore, relocate);
   2092 }
   2093 
   2094 
   2095 static void
   2096 list_module (Dwfl_Module *mod)
   2097 {
   2098   /* Make sure we have searched for the files.  */
   2099   GElf_Addr bias;
   2100   bool have_elf = dwfl_module_getelf (mod, &bias) != NULL;
   2101   bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL;
   2102 
   2103   const char *file;
   2104   const char *debug;
   2105   Dwarf_Addr start;
   2106   Dwarf_Addr end;
   2107   const char *name = dwfl_module_info (mod, NULL, &start, &end,
   2108 				       NULL, NULL, &file, &debug);
   2109   if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file)))
   2110     debug = ".";
   2111 
   2112   const unsigned char *id;
   2113   GElf_Addr id_vaddr;
   2114   int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
   2115 
   2116   printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start);
   2117 
   2118   if (id_len > 0)
   2119     {
   2120       do
   2121 	printf ("%02" PRIx8, *id++);
   2122       while (--id_len > 0);
   2123       if (id_vaddr != 0)
   2124 	printf ("@%#" PRIx64, id_vaddr);
   2125     }
   2126   else
   2127     putchar ('-');
   2128 
   2129   printf (" %s %s %s\n",
   2130 	  file ?: have_elf ? "." : "-",
   2131 	  debug ?: have_dwarf ? "." : "-",
   2132 	  name);
   2133 }
   2134 
   2135 
   2136 struct match_module_info
   2137 {
   2138   char **patterns;
   2139   Dwfl_Module *found;
   2140   bool match_files;
   2141 };
   2142 
   2143 static int
   2144 match_module (Dwfl_Module *mod,
   2145 	      void **userdata __attribute__ ((unused)),
   2146 	      const char *name,
   2147 	      Dwarf_Addr start __attribute__ ((unused)),
   2148 	      void *arg)
   2149 {
   2150   struct match_module_info *info = arg;
   2151 
   2152   if (info->patterns[0] == NULL) /* Match all.  */
   2153     {
   2154     match:
   2155       info->found = mod;
   2156       return DWARF_CB_ABORT;
   2157     }
   2158 
   2159   if (info->match_files)
   2160     {
   2161       /* Make sure we've searched for the ELF file.  */
   2162       GElf_Addr bias;
   2163       (void) dwfl_module_getelf (mod, &bias);
   2164 
   2165       const char *file;
   2166       const char *check = dwfl_module_info (mod, NULL, NULL, NULL,
   2167 					    NULL, NULL, &file, NULL);
   2168       assert (check == name);
   2169       if (file == NULL)
   2170 	return DWARF_CB_OK;
   2171 
   2172       name = file;
   2173     }
   2174 
   2175   for (char **p = info->patterns; *p != NULL; ++p)
   2176     if (fnmatch (*p, name, 0) == 0)
   2177       goto match;
   2178 
   2179   return DWARF_CB_OK;
   2180 }
   2181 
   2182 /* Handle files opened implicitly via libdwfl.  */
   2183 static void
   2184 handle_implicit_modules (const struct arg_info *info)
   2185 {
   2186   struct match_module_info mmi = { info->args, NULL, info->match_files };
   2187   inline ptrdiff_t next (ptrdiff_t offset)
   2188     {
   2189       return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
   2190     }
   2191   ptrdiff_t offset = next (0);
   2192   if (offset == 0)
   2193     error (EXIT_FAILURE, 0, _("no matching modules found"));
   2194 
   2195   if (info->list)
   2196     do
   2197       list_module (mmi.found);
   2198     while ((offset = next (offset)) > 0);
   2199   else if (info->output_dir == NULL)
   2200     {
   2201       if (next (offset) != 0)
   2202 	error (EXIT_FAILURE, 0, _("matched more than one module"));
   2203       handle_dwfl_module (info->output_file, false, mmi.found,
   2204 			  info->all, info->ignore, info->relocate);
   2205     }
   2206   else
   2207     do
   2208       handle_output_dir_module (info->output_dir, mmi.found,
   2209 				info->all, info->ignore,
   2210 				info->modnames, info->relocate);
   2211     while ((offset = next (offset)) > 0);
   2212 }
   2213 
   2214 int
   2216 main (int argc, char **argv)
   2217 {
   2218   /* Make memory leak detection possible.  */
   2219   mtrace ();
   2220 
   2221   /* We use no threads here which can interfere with handling a stream.  */
   2222   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
   2223   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
   2224   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
   2225 
   2226   /* Set locale.  */
   2227   setlocale (LC_ALL, "");
   2228 
   2229   /* Make sure the message catalog can be found.  */
   2230   bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
   2231 
   2232   /* Initialize the message catalog.  */
   2233   textdomain (PACKAGE_TARNAME);
   2234 
   2235   /* Parse and process arguments.  */
   2236   const struct argp_child argp_children[] =
   2237     {
   2238       {
   2239 	.argp = dwfl_standard_argp (),
   2240 	.header = N_("Input selection options:"),
   2241 	.group = 1,
   2242       },
   2243       { .argp = NULL },
   2244     };
   2245   const struct argp argp =
   2246     {
   2247       .options = options,
   2248       .parser = parse_opt,
   2249       .children = argp_children,
   2250       .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"),
   2251       .doc = N_("\
   2252 Combine stripped files with separate symbols and debug information.\v\
   2253 The first form puts the result in DEBUG-FILE if -o was not given.\n\
   2254 \n\
   2255 MODULE arguments give file name patterns matching modules to process.\n\
   2256 With -f these match the file name of the main (stripped) file \
   2257 (slashes are never special), otherwise they match the simple module names.  \
   2258 With no arguments, process all modules found.\n\
   2259 \n\
   2260 Multiple modules are written to files under OUTPUT-DIRECTORY, \
   2261 creating subdirectories as needed.  \
   2262 With -m these files have simple module names, otherwise they have the \
   2263 name of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\
   2264 \n\
   2265 With -n no files are written, but one line to standard output for each module:\
   2266 \n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\
   2267 START and SIZE are hexadecimal giving the address bounds of the module.  \
   2268 BUILDID is hexadecimal for the build ID bits, or - if no ID is known; \
   2269 the hexadecimal may be followed by @0xADDR giving the address where the \
   2270 ID resides if that is known.  \
   2271 FILE is the file name found for the module, or - if none was found, \
   2272 or . if an ELF image is available but not from any named file.  \
   2273 DEBUGFILE is the separate debuginfo file name, \
   2274 or - if no debuginfo was found, or . if FILE contains the debug information.\
   2275 ")
   2276     };
   2277 
   2278   int remaining;
   2279   struct arg_info info = { .args = NULL };
   2280   error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info);
   2281   if (result == ENOSYS)
   2282     assert (info.dwfl == NULL);
   2283   else if (result)
   2284     return EXIT_FAILURE;
   2285   assert (info.args != NULL);
   2286 
   2287   /* Tell the library which version we are expecting.  */
   2288   elf_version (EV_CURRENT);
   2289 
   2290   if (info.dwfl == NULL)
   2291     {
   2292       assert (result == ENOSYS);
   2293 
   2294       if (info.output_dir != NULL)
   2295 	{
   2296 	  char *file;
   2297 	  if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0)
   2298 	    error (EXIT_FAILURE, 0, _("memory exhausted"));
   2299 	  handle_explicit_files (file, true, info.args[0], info.args[1]);
   2300 	  free (file);
   2301 	}
   2302       else
   2303 	handle_explicit_files (info.output_file, false,
   2304 			       info.args[0], info.args[1]);
   2305     }
   2306   else
   2307     {
   2308       /* parse_opt checked this.  */
   2309       assert (info.output_file != NULL || info.output_dir != NULL || info.list);
   2310 
   2311       handle_implicit_modules (&info);
   2312 
   2313       dwfl_end (info.dwfl);
   2314     }
   2315 
   2316   return 0;
   2317 }
   2318 
   2319 
   2320 #include "debugpred.h"
   2321