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 (§ions[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 §ions[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 = §ions[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 = §ions[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 < §ions[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, §ions[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 = §ions[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 = §ions[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 = §ions[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 = §ions[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 < §ions[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 < §ions[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 < §ions[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