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