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