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