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