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