blob: f6af45002a9174222fe25d26ae53e512895f6323 [file] [log] [blame]
Roland McGrath4be15242007-04-25 03:09:33 +00001/* Combine stripped files with separate symbols and debug information.
Mark Wielaard22497092014-05-26 21:28:05 +02002 Copyright (C) 2007-2012, 2014 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Roland McGrath4be15242007-04-25 03:09:33 +00004 Written by Roland McGrath <roland@redhat.com>, 2007.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 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.
Roland McGrath4be15242007-04-25 03:09:33 +000010
Mark Wielaardde2ed972012-06-05 17:15:16 +020011 elfutils is distributed in the hope that it will be useful, but
Roland McGrath4be15242007-04-25 03:09:33 +000012 WITHOUT ANY WARRANTY; without even the implied warranty of
Mark Wielaardde2ed972012-06-05 17:15:16 +020013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
Roland McGrath4be15242007-04-25 03:09:33 +000015
Mark Wielaardde2ed972012-06-05 17:15:16 +020016 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/>. */
Roland McGrath4be15242007-04-25 03:09:33 +000018
19/* TODO:
20
21 * SHX_XINDEX
22
23 * prelink vs .debug_* linked addresses
24
Roland McGrath4be15242007-04-25 03:09:33 +000025 */
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>
Roland McGrath59ea7f32007-10-04 08:50:09 +000043#include <inttypes.h>
Roland McGrath4be15242007-04-25 03:09:33 +000044#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
Roland McGrathb337b1f2010-01-15 01:02:27 -080047#include <sys/stat.h>
Roland McGrath4be15242007-04-25 03:09:33 +000048
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);
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080060ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
Roland McGrath4be15242007-04-25 03:09:33 +000061
62/* Bug report address. */
Ulrich Drepperfdc93e12009-01-17 11:47:10 -080063ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
Roland McGrath4be15242007-04-25 03:09:33 +000064
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 },
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000081 { "relocate", 'R', NULL, 0,
Roland McGrathe4c22ea2007-10-23 13:07:39 +000082 N_("Apply relocations to section contents in ET_REL files"), 0 },
Roland McGrath59ea7f32007-10-04 08:50:09 +000083 { "list-only", 'n', NULL, 0,
84 N_("Only list module and file names, build IDs"), 0 },
Mark Wielaard22497092014-05-26 21:28:05 +020085 { "force", 'F', NULL, 0,
86 N_("Force combining files even if some ELF headers don't seem to match"),
87 0 },
Roland McGrath4be15242007-04-25 03:09:33 +000088 { 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;
Roland McGrath59ea7f32007-10-04 08:50:09 +000097 bool list;
Roland McGrath4be15242007-04-25 03:09:33 +000098 bool all;
99 bool ignore;
100 bool modnames;
101 bool match_files;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000102 bool relocate;
Mark Wielaard22497092014-05-26 21:28:05 +0200103 bool force;
Roland McGrath4be15242007-04-25 03:09:33 +0000104};
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;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000148 case 'n':
149 info->list = true;
150 break;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000151 case 'R':
152 info->relocate = true;
153 break;
Mark Wielaard22497092014-05-26 21:28:05 +0200154 case 'F':
155 info->force = true;
156 break;
Roland McGrath4be15242007-04-25 03:09:33 +0000157
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
Roland McGrath59ea7f32007-10-04 08:50:09 +0000169 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
Roland McGrath4be15242007-04-25 03:09:33 +0000178 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
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000202 if (info->ignore || info->all || info->modnames || info->relocate)
Roland McGrath4be15242007-04-25 03:09:33 +0000203 {
204 argp_error (state, _("\
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000205-m, -a, -R, and -i options not allowed with explicit files"));
Roland McGrath4be15242007-04-25 03:09:33 +0000206 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 }
Roland McGrath59ea7f32007-10-04 08:50:09 +0000213 else if (info->output_file == NULL && info->output_dir == NULL
214 && !info->list)
Roland McGrath4be15242007-04-25 03:09:33 +0000215 {
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{
Ulrich Drepperb0243862007-06-06 00:09:36 +0000232 fprintf (stream, "unstrip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
Roland McGrath4be15242007-04-25 03:09:33 +0000233 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\
Ulrich Drepper3a64a302012-01-21 18:19:24 -0500237"), "2012");
Roland McGrath4be15242007-04-25 03:09:33 +0000238 fprintf (stream, gettext ("Written by %s.\n"), "Roland McGrath");
239}
240
241#define ELF_CHECK(call, msg) \
242 do \
243 { \
244 if (!(call)) \
245 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
260 if (ehdr->e_phnum > 0)
261 {
262 ELF_CHECK (gelf_newphdr (outelf, ehdr->e_phnum),
263 _("cannot create program headers: %s"));
264
265 GElf_Phdr phdr_mem;
266 for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
267 ELF_CHECK (gelf_update_phdr (outelf, i,
268 gelf_getphdr (inelf, i, &phdr_mem)),
269 _("cannot copy program header: %s"));
270 }
271
272 Elf_Scn *scn = NULL;
273 while ((scn = elf_nextscn (inelf, scn)) != NULL)
274 {
275 Elf_Scn *newscn = elf_newscn (outelf);
276
277 GElf_Shdr shdr_mem;
278 ELF_CHECK (gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem)),
279 _("cannot copy section header: %s"));
280
281 Elf_Data *data = elf_getdata (scn, NULL);
282 ELF_CHECK (data != NULL, _("cannot get section data: %s"));
283 Elf_Data *newdata = elf_newdata (newscn);
284 ELF_CHECK (newdata != NULL, _("cannot copy section data: %s"));
285 *newdata = *data;
286 elf_flagdata (newdata, ELF_C_SET, ELF_F_DIRTY);
287 }
288}
289
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000290/* Create directories containing PATH. */
291static void
292make_directories (const char *path)
293{
294 const char *lastslash = strrchr (path, '/');
295 if (lastslash == NULL)
296 return;
297
298 while (lastslash > path && lastslash[-1] == '/')
299 --lastslash;
300 if (lastslash == path)
301 return;
302
303 char *dir = strndupa (path, lastslash - path);
304 while (mkdir (dir, 0777) < 0 && errno != EEXIST)
305 if (errno == ENOENT)
306 make_directories (dir);
307 else
308 error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir);
309}
310
Roland McGrath4be15242007-04-25 03:09:33 +0000311
312/* The binutils linker leaves gratuitous section symbols in .symtab
313 that strip has to remove. Older linkers likewise include a
314 symbol for every section, even unallocated ones, in .dynsym.
315 Because of this, the related sections can shrink in the stripped
316 file from their original size. Older versions of strip do not
317 adjust the sh_size field in the debuginfo file's SHT_NOBITS
318 version of the section header, so it can appear larger. */
319static bool
320section_can_shrink (const GElf_Shdr *shdr)
321{
322 switch (shdr->sh_type)
323 {
324 case SHT_SYMTAB:
325 case SHT_DYNSYM:
326 case SHT_HASH:
327 case SHT_GNU_versym:
328 return true;
329 }
330 return false;
331}
332
333/* See if this symbol table has a leading section symbol for every single
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000334 section, in order. The binutils linker produces this. While we're here,
335 update each section symbol's st_value. */
Roland McGrath4be15242007-04-25 03:09:33 +0000336static size_t
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000337symtab_count_leading_section_symbols (Elf *elf, Elf_Scn *scn, size_t shnum,
338 Elf_Data *newsymdata)
Roland McGrath4be15242007-04-25 03:09:33 +0000339{
340 Elf_Data *data = elf_getdata (scn, NULL);
341 Elf_Data *shndxdata = NULL; /* XXX */
342
343 for (size_t i = 1; i < shnum; ++i)
344 {
345 GElf_Sym sym_mem;
346 GElf_Word shndx = SHN_UNDEF;
347 GElf_Sym *sym = gelf_getsymshndx (data, shndxdata, i, &sym_mem, &shndx);
348 ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000349
350 GElf_Shdr shdr_mem;
351 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, i), &shdr_mem);
352 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
353
Roland McGrath4be15242007-04-25 03:09:33 +0000354 if (sym->st_shndx != SHN_XINDEX)
355 shndx = sym->st_shndx;
356
357 if (shndx != i || GELF_ST_TYPE (sym->st_info) != STT_SECTION)
358 return i;
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000359
360 sym->st_value = shdr->sh_addr;
361 if (sym->st_shndx != SHN_XINDEX)
362 shndx = SHN_UNDEF;
363 ELF_CHECK (gelf_update_symshndx (newsymdata, shndxdata, i, sym, shndx),
364 _("cannot update symbol table: %s"));
Roland McGrath4be15242007-04-25 03:09:33 +0000365 }
366
367 return shnum;
368}
369
Roland McGrathaa32f922010-06-04 02:29:08 -0700370static void
371update_shdr (Elf_Scn *outscn, GElf_Shdr *newshdr)
372{
373 ELF_CHECK (gelf_update_shdr (outscn, newshdr),
374 _("cannot update section header: %s"));
375}
376
Roland McGrath4be15242007-04-25 03:09:33 +0000377/* We expanded the output section, so update its header. */
378static void
379update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
380{
381 GElf_Shdr shdr_mem;
382 GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
383 ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
384
385 newshdr->sh_size = data->d_size;
386
Roland McGrathaa32f922010-06-04 02:29:08 -0700387 update_shdr (outscn, newshdr);
Roland McGrath4be15242007-04-25 03:09:33 +0000388}
389
390/* Update relocation sections using the symbol table. */
391static void
392adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
393 size_t map[], const GElf_Shdr *symshdr)
394{
395 Elf_Data *data = elf_getdata (outscn, NULL);
396
397 inline void adjust_reloc (GElf_Xword *info)
398 {
399 size_t ndx = GELF_R_SYM (*info);
400 if (ndx != STN_UNDEF)
401 *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info));
402 }
403
404 switch (shdr->sh_type)
405 {
406 case SHT_REL:
407 for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
408 {
409 GElf_Rel rel_mem;
410 GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
411 adjust_reloc (&rel->r_info);
412 ELF_CHECK (gelf_update_rel (data, i, rel),
413 _("cannot update relocation: %s"));
414 }
415 break;
416
417 case SHT_RELA:
418 for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
419 {
420 GElf_Rela rela_mem;
421 GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
422 adjust_reloc (&rela->r_info);
423 ELF_CHECK (gelf_update_rela (data, i, rela),
424 _("cannot update relocation: %s"));
425 }
426 break;
427
428 case SHT_GROUP:
429 {
430 GElf_Shdr shdr_mem;
431 GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
432 ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
433 if (newshdr->sh_info != STN_UNDEF)
434 {
435 newshdr->sh_info = map[newshdr->sh_info - 1];
Roland McGrathaa32f922010-06-04 02:29:08 -0700436 update_shdr (outscn, newshdr);
Roland McGrath4be15242007-04-25 03:09:33 +0000437 }
438 break;
439 }
440
441 case SHT_HASH:
442 /* We must expand the table and rejigger its contents. */
443 {
444 const size_t nsym = symshdr->sh_size / symshdr->sh_entsize;
445 const size_t onent = shdr->sh_size / shdr->sh_entsize;
446 assert (data->d_size == shdr->sh_size);
447
448#define CONVERT_HASH(Hash_Word) \
449 { \
450 const Hash_Word *const old_hash = data->d_buf; \
451 const size_t nbucket = old_hash[0]; \
452 const size_t nchain = old_hash[1]; \
453 const Hash_Word *const old_bucket = &old_hash[2]; \
454 const Hash_Word *const old_chain = &old_bucket[nbucket]; \
455 assert (onent == 2 + nbucket + nchain); \
456 \
457 const size_t nent = 2 + nbucket + nsym; \
458 Hash_Word *const new_hash = xcalloc (nent, sizeof new_hash[0]); \
459 Hash_Word *const new_bucket = &new_hash[2]; \
460 Hash_Word *const new_chain = &new_bucket[nbucket]; \
461 \
462 new_hash[0] = nbucket; \
463 new_hash[1] = nsym; \
464 for (size_t i = 0; i < nbucket; ++i) \
465 if (old_bucket[i] != STN_UNDEF) \
466 new_bucket[i] = map[old_bucket[i] - 1]; \
467 \
468 for (size_t i = 1; i < nchain; ++i) \
469 if (old_chain[i] != STN_UNDEF) \
470 new_chain[map[i - 1]] = map[old_chain[i] - 1]; \
471 \
472 data->d_buf = new_hash; \
473 data->d_size = nent * sizeof new_hash[0]; \
474 }
475
476 switch (shdr->sh_entsize)
477 {
478 case 4:
479 CONVERT_HASH (Elf32_Word);
480 break;
481 case 8:
482 CONVERT_HASH (Elf64_Xword);
483 break;
484 default:
485 abort ();
486 }
487
488 elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
489 update_sh_size (outscn, data);
490
491#undef CONVERT_HASH
492 }
493 break;
494
495 case SHT_GNU_versym:
496 /* We must expand the table and move its elements around. */
497 {
498 const size_t nent = symshdr->sh_size / symshdr->sh_entsize;
499 const size_t onent = shdr->sh_size / shdr->sh_entsize;
500 assert (nent >= onent);
501
502 /* We don't bother using gelf_update_versym because there is
503 really no conversion to be done. */
504 assert (sizeof (Elf32_Versym) == sizeof (GElf_Versym));
505 assert (sizeof (Elf64_Versym) == sizeof (GElf_Versym));
506 GElf_Versym *versym = xcalloc (nent, sizeof versym[0]);
507
508 for (size_t i = 1; i < onent; ++i)
509 {
510 GElf_Versym *v = gelf_getversym (data, i, &versym[map[i - 1]]);
511 ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
512 }
513
514 data->d_buf = versym;
515 data->d_size = nent * shdr->sh_entsize;
516 elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
517 update_sh_size (outscn, data);
518 }
519 break;
520
521 default:
522 error (EXIT_FAILURE, 0,
523 _("unexpected section type in [%Zu] with sh_link to symtab"),
524 elf_ndxscn (inscn));
525 }
526}
527
528/* Adjust all the relocation sections in the file. */
529static void
530adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
531 size_t map[])
532{
533 size_t new_sh_link = elf_ndxscn (symtab);
534 Elf_Scn *scn = NULL;
535 while ((scn = elf_nextscn (elf, scn)) != NULL)
536 if (scn != symtab)
537 {
538 GElf_Shdr shdr_mem;
539 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
540 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
541 if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link)
542 adjust_relocs (scn, scn, shdr, map, symshdr);
543 }
544}
545
546/* The original file probably had section symbols for all of its
547 sections, even the unallocated ones. To match it as closely as
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000548 possible, add in section symbols for the added sections. */
Roland McGrath4be15242007-04-25 03:09:33 +0000549static Elf_Data *
550add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000551 Elf *elf, bool rel, Elf_Scn *symscn, size_t shnum)
Roland McGrath4be15242007-04-25 03:09:33 +0000552{
553 const size_t added = shnum - old_shnum;
554
555 GElf_Shdr shdr_mem;
556 GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
557 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
558
559 const size_t nsym = shdr->sh_size / shdr->sh_entsize;
560 size_t symndx_map[nsym - 1];
561
562 shdr->sh_info += added;
563 shdr->sh_size += added * shdr->sh_entsize;
Roland McGrathaa32f922010-06-04 02:29:08 -0700564 update_shdr (symscn, shdr);
Roland McGrath4be15242007-04-25 03:09:33 +0000565
566 Elf_Data *symdata = elf_getdata (symscn, NULL);
567 Elf_Data *shndxdata = NULL; /* XXX */
568
569 symdata->d_size = shdr->sh_size;
570 symdata->d_buf = xmalloc (symdata->d_size);
571
572 /* Copy the existing section symbols. */
573 Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
574 for (size_t i = 0; i < old_shnum; ++i)
575 {
576 GElf_Sym sym_mem;
577 GElf_Word shndx = SHN_UNDEF;
578 GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
579 i, &sym_mem, &shndx);
580 ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
581 sym, shndx),
582 _("cannot update symbol table: %s"));
583
584 if (i > 0)
585 symndx_map[i - 1] = i;
586 }
587
588 /* Add in the new section symbols. */
589 for (size_t i = old_shnum; i < shnum; ++i)
590 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000591 GElf_Shdr i_shdr_mem;
592 GElf_Shdr *i_shdr = gelf_getshdr (elf_getscn (elf, i), &i_shdr_mem);
593 ELF_CHECK (i_shdr != NULL, _("cannot get section header: %s"));
Roland McGrath4be15242007-04-25 03:09:33 +0000594 GElf_Sym sym =
595 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000596 .st_value = rel ? 0 : i_shdr->sh_addr,
Roland McGrath4be15242007-04-25 03:09:33 +0000597 .st_info = GELF_ST_INFO (STB_LOCAL, STT_SECTION),
598 .st_shndx = i < SHN_LORESERVE ? i : SHN_XINDEX
599 };
600 GElf_Word shndx = i < SHN_LORESERVE ? SHN_UNDEF : i;
601 ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
602 &sym, shndx),
603 _("cannot update symbol table: %s"));
604 }
605
606 /* Now copy the rest of the existing symbols. */
607 for (size_t i = old_shnum; i < nsym; ++i)
608 {
609 GElf_Sym sym_mem;
610 GElf_Word shndx = SHN_UNDEF;
611 GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
612 i, &sym_mem, &shndx);
613 ELF_CHECK (gelf_update_symshndx (symdata, shndxdata,
614 i + added, sym, shndx),
615 _("cannot update symbol table: %s"));
616
617 symndx_map[i - 1] = i + added;
618 }
619
620 /* Adjust any relocations referring to the old symbol table. */
621 adjust_all_relocs (elf, symscn, shdr, symndx_map);
622
623 return symdata;
624}
625
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000626/* This has the side effect of updating STT_SECTION symbols' values,
627 in case of prelink adjustments. */
Roland McGrath4be15242007-04-25 03:09:33 +0000628static Elf_Data *
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000629check_symtab_section_symbols (Elf *elf, bool rel, Elf_Scn *scn,
Roland McGrath4be15242007-04-25 03:09:33 +0000630 size_t shnum, size_t shstrndx,
631 Elf_Scn *oscn, size_t oshnum, size_t oshstrndx,
632 size_t debuglink)
633{
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000634 size_t n = symtab_count_leading_section_symbols (elf, oscn, oshnum,
635 elf_getdata (scn, NULL));
Roland McGrath4be15242007-04-25 03:09:33 +0000636
637 if (n == oshnum)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000638 return add_new_section_symbols (oscn, n, elf, rel, scn, shnum);
Roland McGrath4be15242007-04-25 03:09:33 +0000639
640 if (n == oshstrndx || (n == debuglink && n == oshstrndx - 1))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000641 return add_new_section_symbols (oscn, n, elf, rel, scn, shstrndx);
Roland McGrath4be15242007-04-25 03:09:33 +0000642
643 return NULL;
644}
645
646struct section
647{
648 Elf_Scn *scn;
649 const char *name;
650 Elf_Scn *outscn;
651 struct Ebl_Strent *strent;
652 GElf_Shdr shdr;
653};
654
655static int
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000656compare_alloc_sections (const struct section *s1, const struct section *s2,
657 bool rel)
Roland McGrath4be15242007-04-25 03:09:33 +0000658{
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000659 if (!rel)
660 {
661 /* Sort by address. */
662 if (s1->shdr.sh_addr < s2->shdr.sh_addr)
663 return -1;
664 if (s1->shdr.sh_addr > s2->shdr.sh_addr)
665 return 1;
666 }
Roland McGrath4be15242007-04-25 03:09:33 +0000667
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000668 /* At the same address, preserve original section order. */
669 return (ssize_t) elf_ndxscn (s1->scn) - (ssize_t) elf_ndxscn (s2->scn);
Roland McGrath4be15242007-04-25 03:09:33 +0000670}
671
672static int
673compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2,
674 const char *name1, const char *name2)
675{
676 /* Sort by sh_flags as an arbitrary ordering. */
677 if (shdr1->sh_flags < shdr2->sh_flags)
678 return -1;
679 if (shdr1->sh_flags > shdr2->sh_flags)
680 return 1;
681
682 /* Sort by name as last resort. */
683 return strcmp (name1, name2);
684}
685
686static int
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000687compare_sections (const void *a, const void *b, bool rel)
Roland McGrath4be15242007-04-25 03:09:33 +0000688{
689 const struct section *s1 = a;
690 const struct section *s2 = b;
691
692 /* Sort all non-allocated sections last. */
693 if ((s1->shdr.sh_flags ^ s2->shdr.sh_flags) & SHF_ALLOC)
694 return (s1->shdr.sh_flags & SHF_ALLOC) ? -1 : 1;
695
696 return ((s1->shdr.sh_flags & SHF_ALLOC)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000697 ? compare_alloc_sections (s1, s2, rel)
Roland McGrath4be15242007-04-25 03:09:33 +0000698 : compare_unalloc_sections (&s1->shdr, &s2->shdr,
699 s1->name, s2->name));
700}
701
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000702static int
703compare_sections_rel (const void *a, const void *b)
704{
705 return compare_sections (a, b, true);
706}
707
Marek Polacek82f77d72011-05-07 19:26:20 +0200708static int
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000709compare_sections_nonrel (const void *a, const void *b)
710{
711 return compare_sections (a, b, false);
712}
713
Roland McGrath4be15242007-04-25 03:09:33 +0000714
715struct symbol
716{
717 size_t *map;
718
719 union
720 {
721 const char *name;
722 struct Ebl_Strent *strent;
723 };
Roland McGrath4be15242007-04-25 03:09:33 +0000724 union
725 {
726 struct
727 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000728 GElf_Addr value;
729 GElf_Xword size;
730 GElf_Word shndx;
731 union
732 {
733 struct
734 {
735 uint8_t info;
736 uint8_t other;
737 } info;
738 int16_t compare;
739 };
740 };
741
742 /* For a symbol discarded after first sort, this matches its better's
743 map pointer. */
744 size_t *duplicate;
Roland McGrath4be15242007-04-25 03:09:33 +0000745 };
746};
747
748/* Collect input symbols into our internal form. */
749static void
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000750collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, Elf_Scn *strscn,
Roland McGrath4be15242007-04-25 03:09:33 +0000751 const size_t nent, const GElf_Addr bias,
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000752 const size_t scnmap[], struct symbol *table, size_t *map,
753 struct section *split_bss)
Roland McGrath4be15242007-04-25 03:09:33 +0000754{
755 Elf_Data *symdata = elf_getdata (symscn, NULL);
756 Elf_Data *strdata = elf_getdata (strscn, NULL);
757 Elf_Data *shndxdata = NULL; /* XXX */
758
759 for (size_t i = 1; i < nent; ++i)
760 {
761 GElf_Sym sym_mem;
762 GElf_Word shndx = SHN_UNDEF;
763 GElf_Sym *sym = gelf_getsymshndx (symdata, shndxdata, i,
764 &sym_mem, &shndx);
765 ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
766 if (sym->st_shndx != SHN_XINDEX)
767 shndx = sym->st_shndx;
768
Roland McGrath4be15242007-04-25 03:09:33 +0000769 if (sym->st_name >= strdata->d_size)
770 error (EXIT_FAILURE, 0,
771 _("invalid string offset in symbol [%Zu]"), i);
772
773 struct symbol *s = &table[i - 1];
774 s->map = &map[i - 1];
775 s->name = strdata->d_buf + sym->st_name;
776 s->value = sym->st_value + bias;
777 s->size = sym->st_size;
778 s->shndx = shndx;
779 s->info.info = sym->st_info;
780 s->info.other = sym->st_other;
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000781
782 if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
783 s->shndx = scnmap[shndx - 1];
784
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000785 if (GELF_ST_TYPE (s->info.info) == STT_SECTION && !rel)
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000786 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000787 /* Update the value to match the output section. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000788 GElf_Shdr shdr_mem;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000789 GElf_Shdr *shdr = gelf_getshdr (elf_getscn (outelf, s->shndx),
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000790 &shdr_mem);
791 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000792 s->value = shdr->sh_addr;
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000793 }
794 else if (split_bss != NULL
795 && s->value < split_bss->shdr.sh_addr
796 && s->value >= split_bss[-1].shdr.sh_addr
797 && shndx == elf_ndxscn (split_bss->outscn))
798 /* This symbol was in .bss and was split into .dynbss. */
799 s->shndx = elf_ndxscn (split_bss[-1].outscn);
Roland McGrath4be15242007-04-25 03:09:33 +0000800 }
801}
802
803
804#define CMP(value) \
805 if (s1->value < s2->value) \
806 return -1; \
807 if (s1->value > s2->value) \
808 return 1
809
810/* Compare symbols with a consistent ordering,
811 but one only meaningful for equality. */
812static int
813compare_symbols (const void *a, const void *b)
814{
815 const struct symbol *s1 = a;
816 const struct symbol *s2 = b;
817
818 CMP (value);
819 CMP (size);
820 CMP (shndx);
821
822 return (s1->compare - s2->compare) ?: strcmp (s1->name, s2->name);
823}
824
825/* Compare symbols for output order after slots have been assigned. */
826static int
827compare_symbols_output (const void *a, const void *b)
828{
829 const struct symbol *s1 = a;
830 const struct symbol *s2 = b;
831 int cmp;
832
833 /* Sort discarded symbols last. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000834 cmp = (s1->name == NULL) - (s2->name == NULL);
Roland McGrath4be15242007-04-25 03:09:33 +0000835
836 if (cmp == 0)
837 /* Local symbols must come first. */
838 cmp = ((GELF_ST_BIND (s2->info.info) == STB_LOCAL)
839 - (GELF_ST_BIND (s1->info.info) == STB_LOCAL));
840
841 if (cmp == 0)
842 /* binutils always puts section symbols first. */
843 cmp = ((GELF_ST_TYPE (s2->info.info) == STT_SECTION)
844 - (GELF_ST_TYPE (s1->info.info) == STT_SECTION));
845
846 if (cmp == 0)
847 {
848 if (GELF_ST_TYPE (s1->info.info) == STT_SECTION)
849 {
850 /* binutils always puts section symbols in section index order. */
851 CMP (shndx);
852 else
853 assert (s1 == s2);
854 }
855
856 /* Nothing really matters, so preserve the original order. */
857 CMP (map);
858 else
859 assert (s1 == s2);
860 }
861
862 return cmp;
863}
864
865#undef CMP
866
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000867/* Return true iff the flags, size, and name match. */
868static bool
869sections_match (const struct section *sections, size_t i,
870 const GElf_Shdr *shdr, const char *name)
871{
872 return (sections[i].shdr.sh_flags == shdr->sh_flags
873 && (sections[i].shdr.sh_size == shdr->sh_size
874 || (sections[i].shdr.sh_size < shdr->sh_size
875 && section_can_shrink (&sections[i].shdr)))
876 && !strcmp (sections[i].name, name));
877}
878
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000879/* Locate a matching allocated section in SECTIONS. */
880static struct section *
881find_alloc_section (const GElf_Shdr *shdr, GElf_Addr bias, const char *name,
882 struct section sections[], size_t nalloc)
883{
884 const GElf_Addr addr = shdr->sh_addr + bias;
885 size_t l = 0, u = nalloc;
886 while (l < u)
887 {
888 size_t i = (l + u) / 2;
889 if (addr < sections[i].shdr.sh_addr)
890 u = i;
891 else if (addr > sections[i].shdr.sh_addr)
892 l = i + 1;
893 else
894 {
895 /* We've found allocated sections with this address.
896 Find one with matching size, flags, and name. */
897 while (i > 0 && sections[i - 1].shdr.sh_addr == addr)
898 --i;
899 for (; i < nalloc && sections[i].shdr.sh_addr == addr;
900 ++i)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000901 if (sections_match (sections, i, shdr, name))
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000902 return &sections[i];
903 break;
904 }
905 }
906 return NULL;
907}
908
909static inline const char *
910get_section_name (size_t ndx, const GElf_Shdr *shdr, const Elf_Data *shstrtab)
911{
912 if (shdr->sh_name >= shstrtab->d_size)
913 error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"),
914 ndx, elf_errmsg (-1));
915 return shstrtab->d_buf + shdr->sh_name;
916}
917
918/* Fix things up when prelink has moved some allocated sections around
919 and the debuginfo file's section headers no longer match up.
920 This fills in SECTIONS[0..NALLOC-1].outscn or exits.
921 If there was a .bss section that was split into two sections
922 with the new one preceding it in sh_addr, we return that pointer. */
923static struct section *
924find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
925 Elf *main, const GElf_Ehdr *main_ehdr,
926 Elf_Data *main_shstrtab, GElf_Addr bias,
927 struct section *sections,
928 size_t nalloc, size_t nsections)
929{
930 /* Clear assignments that might have been bogus. */
931 for (size_t i = 0; i < nalloc; ++i)
932 sections[i].outscn = NULL;
933
934 Elf_Scn *undo = NULL;
935 for (size_t i = nalloc; i < nsections; ++i)
936 {
937 const struct section *sec = &sections[i];
938 if (sec->shdr.sh_type == SHT_PROGBITS
939 && !(sec->shdr.sh_flags & SHF_ALLOC)
940 && !strcmp (sec->name, ".gnu.prelink_undo"))
941 {
942 undo = sec->scn;
943 break;
944 }
945 }
946
947 /* Find the original allocated sections before prelinking. */
948 struct section *undo_sections = NULL;
949 size_t undo_nalloc = 0;
950 if (undo != NULL)
951 {
952 Elf_Data *undodata = elf_rawdata (undo, NULL);
953 ELF_CHECK (undodata != NULL,
954 _("cannot read '.gnu.prelink_undo' section: %s"));
955
956 union
957 {
958 Elf32_Ehdr e32;
959 Elf64_Ehdr e64;
960 } ehdr;
961 Elf_Data dst =
962 {
963 .d_buf = &ehdr,
964 .d_size = sizeof ehdr,
965 .d_type = ELF_T_EHDR,
966 .d_version = EV_CURRENT
967 };
968 Elf_Data src = *undodata;
969 src.d_size = gelf_fsize (main, ELF_T_EHDR, 1, EV_CURRENT);
970 src.d_type = ELF_T_EHDR;
971 ELF_CHECK (gelf_xlatetom (main, &dst, &src,
972 main_ehdr->e_ident[EI_DATA]) != NULL,
973 _("cannot read '.gnu.prelink_undo' section: %s"));
974
975 uint_fast16_t phnum;
976 uint_fast16_t shnum;
977 if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
978 {
979 phnum = ehdr.e32.e_phnum;
980 shnum = ehdr.e32.e_shnum;
981 }
982 else
983 {
984 phnum = ehdr.e64.e_phnum;
985 shnum = ehdr.e64.e_shnum;
986 }
987
988 size_t phsize = gelf_fsize (main, ELF_T_PHDR, phnum, EV_CURRENT);
989 src.d_buf += src.d_size + phsize;
990 src.d_size = gelf_fsize (main, ELF_T_SHDR, shnum - 1, EV_CURRENT);
991 src.d_type = ELF_T_SHDR;
992 if ((size_t) (src.d_buf - undodata->d_buf) > undodata->d_size
993 || undodata->d_size - (src.d_buf - undodata->d_buf) != src.d_size)
994 error (EXIT_FAILURE, 0, _("invalid contents in '%s' section"),
995 ".gnu.prelink_undo");
996
997 union
998 {
999 Elf32_Shdr s32[shnum - 1];
1000 Elf64_Shdr s64[shnum - 1];
1001 } shdr;
1002 dst.d_buf = &shdr;
1003 dst.d_size = sizeof shdr;
1004 ELF_CHECK (gelf_xlatetom (main, &dst, &src,
1005 main_ehdr->e_ident[EI_DATA]) != NULL,
1006 _("cannot read '.gnu.prelink_undo' section: %s"));
1007
1008 undo_sections = xmalloc ((shnum - 1) * sizeof undo_sections[0]);
1009 for (size_t i = 0; i < shnum - 1; ++i)
1010 {
1011 struct section *sec = &undo_sections[undo_nalloc];
1012 if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
1013 {
1014#define COPY(field) sec->shdr.field = shdr.s32[i].field
1015 COPY (sh_name);
1016 COPY (sh_type);
1017 COPY (sh_flags);
1018 COPY (sh_addr);
1019 COPY (sh_offset);
1020 COPY (sh_size);
1021 COPY (sh_link);
1022 COPY (sh_info);
1023 COPY (sh_addralign);
1024 COPY (sh_entsize);
1025#undef COPY
1026 }
1027 else
1028 sec->shdr = shdr.s64[i];
1029 if (sec->shdr.sh_flags & SHF_ALLOC)
1030 {
1031 sec->shdr.sh_addr += bias;
1032 sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab);
1033 sec->scn = elf_getscn (main, i + 1); /* Really just for ndx. */
1034 sec->outscn = NULL;
1035 sec->strent = NULL;
1036 ++undo_nalloc;
1037 }
1038 }
1039 qsort (undo_sections, undo_nalloc,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001040 sizeof undo_sections[0], compare_sections_nonrel);
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001041 }
1042
1043 bool fail = false;
1044 inline void check_match (bool match, Elf_Scn *scn, const char *name)
1045 {
1046 if (!match)
1047 {
1048 fail = true;
1049 error (0, 0, _("cannot find matching section for [%Zu] '%s'"),
1050 elf_ndxscn (scn), name);
1051 }
1052 }
1053
1054 Elf_Scn *scn = NULL;
1055 while ((scn = elf_nextscn (debug, scn)) != NULL)
1056 {
1057 GElf_Shdr shdr_mem;
1058 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1059 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1060
1061 if (!(shdr->sh_flags & SHF_ALLOC))
1062 continue;
1063
1064 const char *name = get_section_name (elf_ndxscn (scn), shdr,
1065 debug_shstrtab);
1066
1067 if (undo_sections != NULL)
1068 {
1069 struct section *sec = find_alloc_section (shdr, 0, name,
1070 undo_sections,
1071 undo_nalloc);
1072 if (sec != NULL)
1073 {
1074 sec->outscn = scn;
1075 continue;
1076 }
1077 }
1078
1079 /* If there is no prelink info, we are just here to find
1080 the sections to give error messages about. */
1081 for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
1082 if (sections[i].outscn == scn)
1083 shdr = NULL;
1084 check_match (shdr == NULL, scn, name);
1085 }
1086
1087 if (fail)
1088 exit (EXIT_FAILURE);
1089
1090 /* Now we have lined up output sections for each of the original sections
1091 before prelinking. Translate those to the prelinked sections.
1092 This matches what prelink's undo_sections does. */
1093 struct section *split_bss = NULL;
1094 for (size_t i = 0; i < undo_nalloc; ++i)
1095 {
1096 const struct section *undo_sec = &undo_sections[i];
1097
1098 const char *name = undo_sec->name;
1099 scn = undo_sec->scn; /* This is just for elf_ndxscn. */
1100
1101 for (size_t j = 0; j < nalloc; ++j)
1102 {
1103 struct section *sec = &sections[j];
1104#define RELA_SCALED(field) \
1105 (2 * sec->shdr.field == 3 * undo_sec->shdr.field)
1106 if (sec->outscn == NULL
1107 && sec->shdr.sh_name == undo_sec->shdr.sh_name
1108 && sec->shdr.sh_flags == undo_sec->shdr.sh_flags
1109 && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign
1110 && (((sec->shdr.sh_type == undo_sec->shdr.sh_type
1111 && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1112 && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1113 || (sec->shdr.sh_size > undo_sec->shdr.sh_size
1114 && main_ehdr->e_type == ET_EXEC
1115 && !strcmp (sec->name, ".dynstr"))))
1116 || (sec->shdr.sh_size == undo_sec->shdr.sh_size
1117 && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1118 && undo_sec->shdr.sh_type == SHT_NOBITS)
1119 || undo_sec->shdr.sh_type == SHT_PROGBITS)
1120 && !strcmp (sec->name, ".plt")))
1121 || (sec->shdr.sh_type == SHT_RELA
1122 && undo_sec->shdr.sh_type == SHT_REL
1123 && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size))
1124 || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1125 && (sec->shdr.sh_type == undo_sec->shdr.sh_type
1126 || (sec->shdr.sh_type == SHT_PROGBITS
1127 && undo_sec->shdr.sh_type == SHT_NOBITS))
Mark Wielaardbd1a0d12014-05-26 22:35:30 +02001128 && sec->shdr.sh_size <= undo_sec->shdr.sh_size
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001129 && (!strcmp (sec->name, ".bss")
1130 || !strcmp (sec->name, ".sbss"))
Mark Wielaardbd1a0d12014-05-26 22:35:30 +02001131 && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1132 || (split_bss = sec) > sections))))
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001133 {
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
Roland McGrathcb6d8652007-08-23 08:10:54 +00001151/* 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. */
1154static Elf_Data *
1155new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
1156 Elf_Data *shstrtab, size_t unstripped_shstrndx,
1157 struct section *sections, size_t stripped_shnum,
1158 struct Ebl_Strtab *strtab)
1159{
1160 if (strtab == NULL)
1161 return NULL;
1162
1163 struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
1164 memset (unstripped_strent, 0, sizeof unstripped_strent);
1165 for (struct section *sec = sections;
1166 sec < &sections[stripped_shnum - 1];
1167 ++sec)
1168 if (sec->outscn != NULL)
1169 {
1170 if (sec->strent == NULL)
1171 {
1172 sec->strent = ebl_strtabadd (strtab, sec->name, 0);
1173 ELF_CHECK (sec->strent != NULL,
1174 _("cannot add section name to string table: %s"));
1175 }
1176 unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
1177 }
1178
1179 /* Add names of sections we aren't touching. */
1180 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1181 if (unstripped_strent[i] == NULL)
1182 {
1183 Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1184 GElf_Shdr shdr_mem;
1185 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1186 const char *name = get_section_name (i + 1, shdr, shstrtab);
1187 unstripped_strent[i] = ebl_strtabadd (strtab, name, 0);
1188 ELF_CHECK (unstripped_strent[i] != NULL,
1189 _("cannot add section name to string table: %s"));
1190 }
1191 else
1192 unstripped_strent[i] = NULL;
1193
1194 /* Now finalize the string table so we can get offsets. */
1195 Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
1196 unstripped_shstrndx), NULL);
1197 ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
1198 _("cannot update section header string table data: %s"));
1199 ebl_strtabfinalize (strtab, strtab_data);
1200
1201 /* Update the sh_name fields of sections we aren't modifying later. */
1202 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1203 if (unstripped_strent[i] != NULL)
1204 {
1205 Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1206 GElf_Shdr shdr_mem;
1207 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1208 shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]);
1209 if (i + 1 == unstripped_shstrndx)
1210 shdr->sh_size = strtab_data->d_size;
Roland McGrathaa32f922010-06-04 02:29:08 -07001211 update_shdr (scn, shdr);
Roland McGrathcb6d8652007-08-23 08:10:54 +00001212 }
1213
1214 return strtab_data;
1215}
1216
Roland McGrath4be15242007-04-25 03:09:33 +00001217/* Fill in any SHT_NOBITS sections in UNSTRIPPED by
1218 copying their contents and sh_type from STRIPPED. */
1219static void
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001220copy_elided_sections (Elf *unstripped, Elf *stripped,
1221 const GElf_Ehdr *stripped_ehdr, GElf_Addr bias)
Roland McGrath4be15242007-04-25 03:09:33 +00001222{
1223 size_t unstripped_shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001224 ELF_CHECK (elf_getshdrstrndx (unstripped, &unstripped_shstrndx) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001225 _("cannot get section header string table section index: %s"));
1226
1227 size_t stripped_shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001228 ELF_CHECK (elf_getshdrstrndx (stripped, &stripped_shstrndx) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001229 _("cannot get section header string table section index: %s"));
1230
1231 size_t unstripped_shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001232 ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001233 _("cannot get section count: %s"));
1234
1235 size_t stripped_shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001236 ELF_CHECK (elf_getshdrnum (stripped, &stripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001237 _("cannot get section count: %s"));
1238
Roland McGrath3b1b6512010-06-04 02:26:30 -07001239 if (unlikely (stripped_shnum > unstripped_shnum))
1240 error (EXIT_FAILURE, 0, _("\
1241more sections in stripped file than debug file -- arguments reversed?"));
1242
Roland McGrath4be15242007-04-25 03:09:33 +00001243 /* Cache the stripped file's section details. */
1244 struct section sections[stripped_shnum - 1];
1245 Elf_Scn *scn = NULL;
1246 while ((scn = elf_nextscn (stripped, scn)) != NULL)
1247 {
1248 size_t i = elf_ndxscn (scn) - 1;
1249 GElf_Shdr *shdr = gelf_getshdr (scn, &sections[i].shdr);
1250 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1251 sections[i].name = elf_strptr (stripped, stripped_shstrndx,
1252 shdr->sh_name);
1253 if (sections[i].name == NULL)
1254 error (EXIT_FAILURE, 0, _("cannot read section [%Zu] name: %s"),
1255 elf_ndxscn (scn), elf_errmsg (-1));
1256 sections[i].scn = scn;
1257 sections[i].outscn = NULL;
1258 sections[i].strent = NULL;
1259 }
1260
1261 const struct section *stripped_symtab = NULL;
1262
1263 /* Sort the sections, allocated by address and others after. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001264 qsort (sections, stripped_shnum - 1, sizeof sections[0],
1265 stripped_ehdr->e_type == ET_REL
1266 ? compare_sections_rel : compare_sections_nonrel);
Roland McGrath4be15242007-04-25 03:09:33 +00001267 size_t nalloc = stripped_shnum - 1;
1268 while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
1269 {
1270 --nalloc;
1271 if (sections[nalloc].shdr.sh_type == SHT_SYMTAB)
1272 stripped_symtab = &sections[nalloc];
1273 }
1274
Roland McGrath4be15242007-04-25 03:09:33 +00001275 /* Locate a matching unallocated section in SECTIONS. */
1276 inline struct section *find_unalloc_section (const GElf_Shdr *shdr,
1277 const char *name)
1278 {
1279 size_t l = nalloc, u = stripped_shnum - 1;
1280 while (l < u)
1281 {
1282 size_t i = (l + u) / 2;
1283 struct section *sec = &sections[i];
1284 int cmp = compare_unalloc_sections (shdr, &sec->shdr,
1285 name, sec->name);
1286 if (cmp < 0)
1287 u = i;
1288 else if (cmp > 0)
1289 l = i + 1;
1290 else
1291 return sec;
1292 }
1293 return NULL;
1294 }
1295
1296 Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
1297 unstripped_shstrndx), NULL);
1298 ELF_CHECK (shstrtab != NULL,
1299 _("cannot read section header string table: %s"));
Roland McGrath4be15242007-04-25 03:09:33 +00001300
1301 /* Match each debuginfo section with its corresponding stripped section. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001302 bool check_prelink = false;
Roland McGrath4be15242007-04-25 03:09:33 +00001303 Elf_Scn *unstripped_symtab = NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001304 size_t alloc_avail = 0;
Roland McGrath4be15242007-04-25 03:09:33 +00001305 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
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001312 if (shdr->sh_type == SHT_SYMTAB)
Roland McGrath4be15242007-04-25 03:09:33 +00001313 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001314 unstripped_symtab = scn;
Roland McGrath4be15242007-04-25 03:09:33 +00001315 continue;
1316 }
1317
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001318 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);
Roland McGrath4be15242007-04-25 03:09:33 +00001323
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001324 struct section *sec = NULL;
1325 if (shdr->sh_flags & SHF_ALLOC)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001326 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001327 if (stripped_ehdr->e_type != ET_REL)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001328 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001329 /* 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 }
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001337 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001338 else
1339 {
1340 /* The sh_addr of allocated sections does not help us,
1341 but the order usually matches. */
1342 if (likely (sections_match (sections, alloc_avail, shdr, name)))
1343 sec = &sections[alloc_avail++];
1344 else
1345 for (size_t i = alloc_avail + 1; i < nalloc; ++i)
1346 if (sections_match (sections, i, shdr, name))
1347 {
1348 sec = &sections[i];
1349 break;
1350 }
1351 }
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001352 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001353 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);
Roland McGrath4be15242007-04-25 03:09:33 +00001376
1377 sec->outscn = scn;
1378 }
1379
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001380 /* 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
Roland McGrath4be15242007-04-25 03:09:33 +00001396 /* Make sure each main file section has a place to go. */
1397 const struct section *stripped_dynsym = NULL;
1398 size_t debuglink = SHN_UNDEF;
1399 size_t ndx_section[stripped_shnum - 1];
1400 struct Ebl_Strtab *strtab = NULL;
1401 for (struct section *sec = sections;
1402 sec < &sections[stripped_shnum - 1];
1403 ++sec)
1404 {
1405 size_t secndx = elf_ndxscn (sec->scn);
1406
1407 if (sec->outscn == NULL)
1408 {
1409 /* We didn't find any corresponding section for this. */
1410
1411 if (secndx == stripped_shstrndx)
1412 {
1413 /* We only need one .shstrtab. */
1414 ndx_section[secndx - 1] = unstripped_shstrndx;
1415 continue;
1416 }
1417
1418 if (unstripped_symtab != NULL && sec == stripped_symtab)
1419 {
1420 /* We don't need a second symbol table. */
1421 ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab);
1422 continue;
1423 }
1424
1425 if (unstripped_symtab != NULL && stripped_symtab != NULL
1426 && secndx == stripped_symtab->shdr.sh_link)
1427 {
1428 /* ... nor its string table. */
1429 GElf_Shdr shdr_mem;
1430 GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1431 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1432 ndx_section[secndx - 1] = shdr->sh_link;
1433 continue;
1434 }
1435
1436 if (!(sec->shdr.sh_flags & SHF_ALLOC)
1437 && !strcmp (sec->name, ".gnu_debuglink"))
1438 {
1439 /* This was created by stripping. We don't want it. */
1440 debuglink = secndx;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001441 ndx_section[secndx - 1] = SHN_UNDEF;
Roland McGrath4be15242007-04-25 03:09:33 +00001442 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
Roland McGrathcb6d8652007-08-23 08:10:54 +00001462 /* 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);
Roland McGrath4be15242007-04-25 03:09:33 +00001467
1468 /* Get the updated section count. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07001469 ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001470 _("cannot get section count: %s"));
1471
1472 bool placed[unstripped_shnum - 1];
1473 memset (placed, 0, sizeof placed);
1474
1475 /* Now update the output sections and copy in their data. */
1476 GElf_Off offset = 0;
1477 for (const struct section *sec = sections;
1478 sec < &sections[stripped_shnum - 1];
1479 ++sec)
1480 if (sec->outscn != NULL)
1481 {
1482 GElf_Shdr shdr_mem;
1483 GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem);
1484 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1485
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001486 /* 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
Roland McGrath4be15242007-04-25 03:09:33 +00001496 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. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001516 if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
Roland McGrath4be15242007-04-25 03:09:33 +00001517 {
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
Roland McGrathaa32f922010-06-04 02:29:08 -07001528 update_shdr (sec->outscn, &shdr_mem);
Roland McGrath4be15242007-04-25 03:09:33 +00001529
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
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001580 || check_prelink /* Section adjustments. */
1581 || (stripped_ehdr->e_type != ET_REL
1582 && bias != 0)))
Roland McGrath4be15242007-04-25 03:09:33 +00001583 {
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)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001601 collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
1602 stripped_symtab->scn,
Roland McGrath4be15242007-04-25 03:09:33 +00001603 elf_getscn (stripped, stripped_symtab->shdr.sh_link),
1604 stripped_nsym, 0, ndx_section,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001605 symbols, symndx_map, NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001606
1607 Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001608 collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001609 unstripped_symtab, unstripped_strtab, unstripped_nsym,
1610 stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL,
Roland McGrath4be15242007-04-25 03:09:33 +00001611 &symbols[stripped_nsym - 1],
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001612 &symndx_map[stripped_nsym - 1], split_bss);
Roland McGrath4be15242007-04-25 03:09:33 +00001613
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. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001619 size_t nsym = 0;
1620 for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s)
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001621 {
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 }
Roland McGrath4be15242007-04-25 03:09:33 +00001647
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. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001653 assert (symbols[nsym].name == NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001654
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 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001660 assert (symbols[i].name != NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001661 assert (*symbols[i].map != 0);
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001662 *symbols[i].map = 1 + i;
Roland McGrath4be15242007-04-25 03:09:33 +00001663 symbols[i].strent = ebl_strtabadd (symstrtab, symbols[i].name, 0);
1664 }
1665
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001666 /* 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
Roland McGrath4be15242007-04-25 03:09:33 +00001680 /* 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);
Roland McGrathaa32f922010-06-04 02:29:08 -07001722 update_shdr (unstripped_symtab, shdr);
Roland McGrath4be15242007-04-25 03:09:33 +00001723
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001724 if (stripped_symtab != NULL)
1725 {
1726 /* Adjust any relocations referring to the old symbol table. */
1727 const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn);
1728 for (const struct section *sec = sections;
1729 sec < &sections[stripped_shnum - 1];
1730 ++sec)
1731 if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link)
1732 adjust_relocs (sec->outscn, sec->scn, &sec->shdr,
1733 symndx_map, shdr);
1734 }
Roland McGrath4be15242007-04-25 03:09:33 +00001735
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)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001741 check_symtab_section_symbols (unstripped,
1742 stripped_ehdr->e_type == ET_REL,
1743 stripped_symtab->scn,
Roland McGrath4be15242007-04-25 03:09:33 +00001744 unstripped_shnum, unstripped_shstrndx,
1745 stripped_symtab->outscn,
1746 stripped_shnum, stripped_shstrndx,
1747 debuglink);
1748
1749 if (stripped_dynsym != NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001750 (void) check_symtab_section_symbols (unstripped,
1751 stripped_ehdr->e_type == ET_REL,
1752 stripped_dynsym->outscn,
Roland McGrath4be15242007-04-25 03:09:33 +00001753 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
Roland McGrathec86e5f2010-06-14 17:44:38 -07001782 /* 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
Roland McGrath4be15242007-04-25 03:09:33 +00001791 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
Roland McGrathaa32f922010-06-04 02:29:08 -07001801 update_shdr (scn, shdr);
Roland McGrath4be15242007-04-25 03:09:33 +00001802
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 }
Roland McGrathec86e5f2010-06-14 17:44:38 -07001823 }
1824 while (skip_reloc);
Roland McGrath4be15242007-04-25 03:09:33 +00001825
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001826 if (stripped_ehdr->e_phnum > 0)
1827 ELF_CHECK (gelf_newphdr (unstripped, stripped_ehdr->e_phnum),
1828 _("cannot create program headers: %s"));
1829
Roland McGrath4be15242007-04-25 03:09:33 +00001830 /* Copy each program header from the stripped file. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001831 for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i)
Roland McGrath4be15242007-04-25 03:09:33 +00001832 {
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. */
1861static void
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001862handle_file (const char *output_file, bool create_dirs,
Roland McGrath4be15242007-04-25 03:09:33 +00001863 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)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001889 {
1890 if (output_file == NULL)
1891 error (0, 0, _("\
1892DWARF data not adjusted for prelinking bias; consider prelink -u"));
1893 else
1894 error (0, 0, _("\
1895DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"),
1896 output_file);
1897 }
Roland McGrath4be15242007-04-25 03:09:33 +00001898
1899 if (output_file == NULL)
1900 /* Modify the unstripped file in place. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001901 copy_elided_sections (unstripped, stripped, stripped_ehdr, bias);
Roland McGrath4be15242007-04-25 03:09:33 +00001902 else
1903 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001904 if (create_dirs)
1905 make_directories (output_file);
1906
Roland McGrath4be15242007-04-25 03:09:33 +00001907 /* 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);
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001927 copy_elided_sections (outelf, stripped, stripped_ehdr, bias);
Roland McGrath4be15242007-04-25 03:09:33 +00001928 }
1929
1930 elf_end (outelf);
1931 close (outfd);
1932 }
1933}
1934
1935static int
1936open_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. */
1945static void
Mark Wielaard22497092014-05-26 21:28:05 +02001946handle_explicit_files (const char *output_file, bool create_dirs, bool force,
Roland McGrath4be15242007-04-25 03:09:33 +00001947 const char *stripped_file, const char *unstripped_file)
1948{
Mark Wielaard22497092014-05-26 21:28:05 +02001949
1950 /* Warn, and exit if not forced to continue, if some ELF header
1951 sanity check for the stripped and unstripped files failed. */
1952 void warn (const char *msg)
1953 {
1954 error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
1955 force ? _("WARNING: ") : "",
1956 stripped_file, unstripped_file, msg,
1957 force ? "" : _(", use --force"));
1958 }
1959
Roland McGrath4be15242007-04-25 03:09:33 +00001960 int stripped_fd = open_file (stripped_file, false);
1961 Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
1962 GElf_Ehdr stripped_ehdr;
1963 ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
1964 _("cannot create ELF descriptor: %s"));
1965
1966 int unstripped_fd = -1;
1967 Elf *unstripped = NULL;
1968 if (unstripped_file != NULL)
1969 {
1970 unstripped_fd = open_file (unstripped_file, output_file == NULL);
1971 unstripped = elf_begin (unstripped_fd,
1972 (output_file == NULL ? ELF_C_RDWR : ELF_C_READ),
1973 NULL);
1974 GElf_Ehdr unstripped_ehdr;
1975 ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
1976 _("cannot create ELF descriptor: %s"));
1977
Mark Wielaard22497092014-05-26 21:28:05 +02001978 if (memcmp (stripped_ehdr.e_ident,
1979 unstripped_ehdr.e_ident, EI_NIDENT) != 0)
1980 warn (_("ELF header identification (e_ident) different"));
1981
1982 if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
1983 warn (_("ELF header type (e_type) different"));
1984
1985 if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
1986 warn (_("ELF header machine type (e_machine) different"));
1987
1988 if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
1989 warn (_("stripped program header (e_phnum) smaller than unstripped"));
Roland McGrath4be15242007-04-25 03:09:33 +00001990 }
1991
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001992 handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
Roland McGrath4be15242007-04-25 03:09:33 +00001993
1994 elf_end (stripped);
1995 close (stripped_fd);
1996
1997 elf_end (unstripped);
1998 close (unstripped_fd);
1999}
2000
2001
2002/* Handle a pair of files opened implicitly by libdwfl for one module. */
2003static void
Mark Wielaard22497092014-05-26 21:28:05 +02002004handle_dwfl_module (const char *output_file, bool create_dirs, bool force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002005 Dwfl_Module *mod, bool all, bool ignore, bool relocate)
Roland McGrath4be15242007-04-25 03:09:33 +00002006{
2007 GElf_Addr bias;
2008 Elf *stripped = dwfl_module_getelf (mod, &bias);
2009 if (stripped == NULL)
2010 {
2011 if (ignore)
2012 return;
2013
2014 const char *file;
2015 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2016 NULL, NULL, &file, NULL);
2017 if (file == NULL)
2018 error (EXIT_FAILURE, 0,
2019 _("cannot find stripped file for module '%s': %s"),
2020 modname, dwfl_errmsg (-1));
2021 else
2022 error (EXIT_FAILURE, 0,
2023 _("cannot open stripped file '%s' for module '%s': %s"),
2024 modname, file, dwfl_errmsg (-1));
2025 }
2026
2027 Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias));
2028 if (debug == NULL && !all)
2029 {
2030 if (ignore)
2031 return;
2032
2033 const char *file;
2034 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2035 NULL, NULL, NULL, &file);
2036 if (file == NULL)
2037 error (EXIT_FAILURE, 0,
2038 _("cannot find debug file for module '%s': %s"),
2039 modname, dwfl_errmsg (-1));
2040 else
2041 error (EXIT_FAILURE, 0,
2042 _("cannot open debug file '%s' for module '%s': %s"),
2043 modname, file, dwfl_errmsg (-1));
2044 }
2045
2046 if (debug == stripped)
2047 {
2048 if (all)
2049 debug = NULL;
2050 else
2051 {
2052 const char *file;
2053 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2054 NULL, NULL, &file, NULL);
2055 error (EXIT_FAILURE, 0, _("module '%s' file '%s' is not stripped"),
2056 modname, file);
2057 }
2058 }
2059
2060 GElf_Ehdr stripped_ehdr;
2061 ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
2062 _("cannot create ELF descriptor: %s"));
2063
2064 if (stripped_ehdr.e_type == ET_REL)
2065 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002066 if (!relocate)
2067 {
2068 /* We can't use the Elf handles already open,
2069 because the DWARF sections have been relocated. */
Roland McGrath4be15242007-04-25 03:09:33 +00002070
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002071 const char *stripped_file = NULL;
2072 const char *unstripped_file = NULL;
2073 (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
2074 &stripped_file, &unstripped_file);
Roland McGrath4be15242007-04-25 03:09:33 +00002075
Mark Wielaard22497092014-05-26 21:28:05 +02002076 handle_explicit_files (output_file, create_dirs, force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002077 stripped_file, unstripped_file);
2078 return;
2079 }
2080
2081 /* Relocation is what we want! This ensures that all sections that can
2082 get sh_addr values assigned have them, even ones not used in DWARF.
2083 They might still be used in the symbol table. */
2084 if (dwfl_module_relocations (mod) < 0)
2085 error (EXIT_FAILURE, 0,
2086 _("cannot cache section addresses for module '%s': %s"),
2087 dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
2088 dwfl_errmsg (-1));
Roland McGrath4be15242007-04-25 03:09:33 +00002089 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002090
2091 handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug);
Roland McGrath4be15242007-04-25 03:09:33 +00002092}
2093
2094/* Handle one module being written to the output directory. */
2095static void
Mark Wielaard22497092014-05-26 21:28:05 +02002096handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002097 bool all, bool ignore, bool modnames, bool relocate)
Roland McGrath4be15242007-04-25 03:09:33 +00002098{
2099 if (! modnames)
2100 {
2101 /* Make sure we've searched for the ELF file. */
2102 GElf_Addr bias;
2103 (void) dwfl_module_getelf (mod, &bias);
2104 }
2105
2106 const char *file;
2107 const char *name = dwfl_module_info (mod, NULL, NULL, NULL,
2108 NULL, NULL, &file, NULL);
2109
2110 if (file == NULL && ignore)
2111 return;
2112
2113 char *output_file;
2114 if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0)
2115 error (EXIT_FAILURE, 0, _("memory exhausted"));
2116
Mark Wielaard22497092014-05-26 21:28:05 +02002117 handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002118}
2119
2120
Roland McGrath59ea7f32007-10-04 08:50:09 +00002121static void
2122list_module (Dwfl_Module *mod)
2123{
2124 /* Make sure we have searched for the files. */
2125 GElf_Addr bias;
2126 bool have_elf = dwfl_module_getelf (mod, &bias) != NULL;
2127 bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL;
2128
2129 const char *file;
2130 const char *debug;
2131 Dwarf_Addr start;
2132 Dwarf_Addr end;
2133 const char *name = dwfl_module_info (mod, NULL, &start, &end,
2134 NULL, NULL, &file, &debug);
2135 if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file)))
2136 debug = ".";
2137
2138 const unsigned char *id;
2139 GElf_Addr id_vaddr;
2140 int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
2141
2142 printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start);
2143
2144 if (id_len > 0)
2145 {
2146 do
2147 printf ("%02" PRIx8, *id++);
2148 while (--id_len > 0);
2149 if (id_vaddr != 0)
2150 printf ("@%#" PRIx64, id_vaddr);
2151 }
2152 else
2153 putchar ('-');
2154
2155 printf (" %s %s %s\n",
2156 file ?: have_elf ? "." : "-",
2157 debug ?: have_dwarf ? "." : "-",
2158 name);
2159}
2160
2161
Roland McGrath4be15242007-04-25 03:09:33 +00002162struct match_module_info
2163{
2164 char **patterns;
2165 Dwfl_Module *found;
2166 bool match_files;
2167};
2168
2169static int
2170match_module (Dwfl_Module *mod,
2171 void **userdata __attribute__ ((unused)),
2172 const char *name,
2173 Dwarf_Addr start __attribute__ ((unused)),
2174 void *arg)
2175{
2176 struct match_module_info *info = arg;
2177
2178 if (info->patterns[0] == NULL) /* Match all. */
2179 {
2180 match:
2181 info->found = mod;
2182 return DWARF_CB_ABORT;
2183 }
2184
2185 if (info->match_files)
2186 {
2187 /* Make sure we've searched for the ELF file. */
2188 GElf_Addr bias;
2189 (void) dwfl_module_getelf (mod, &bias);
2190
2191 const char *file;
2192 const char *check = dwfl_module_info (mod, NULL, NULL, NULL,
2193 NULL, NULL, &file, NULL);
2194 assert (check == name);
2195 if (file == NULL)
2196 return DWARF_CB_OK;
2197
2198 name = file;
2199 }
2200
2201 for (char **p = info->patterns; *p != NULL; ++p)
2202 if (fnmatch (*p, name, 0) == 0)
2203 goto match;
2204
2205 return DWARF_CB_OK;
2206}
2207
2208/* Handle files opened implicitly via libdwfl. */
2209static void
2210handle_implicit_modules (const struct arg_info *info)
2211{
2212 struct match_module_info mmi = { info->args, NULL, info->match_files };
2213 inline ptrdiff_t next (ptrdiff_t offset)
2214 {
2215 return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
2216 }
2217 ptrdiff_t offset = next (0);
2218 if (offset == 0)
2219 error (EXIT_FAILURE, 0, _("no matching modules found"));
2220
Roland McGrath59ea7f32007-10-04 08:50:09 +00002221 if (info->list)
2222 do
2223 list_module (mmi.found);
2224 while ((offset = next (offset)) > 0);
2225 else if (info->output_dir == NULL)
Roland McGrath4be15242007-04-25 03:09:33 +00002226 {
2227 if (next (offset) != 0)
2228 error (EXIT_FAILURE, 0, _("matched more than one module"));
Mark Wielaard22497092014-05-26 21:28:05 +02002229 handle_dwfl_module (info->output_file, false, info->force, mmi.found,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002230 info->all, info->ignore, info->relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002231 }
2232 else
2233 do
Mark Wielaard22497092014-05-26 21:28:05 +02002234 handle_output_dir_module (info->output_dir, mmi.found, info->force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002235 info->all, info->ignore,
2236 info->modnames, info->relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002237 while ((offset = next (offset)) > 0);
2238}
2239
2240int
2241main (int argc, char **argv)
2242{
2243 /* Make memory leak detection possible. */
2244 mtrace ();
2245
2246 /* We use no threads here which can interfere with handling a stream. */
2247 __fsetlocking (stdin, FSETLOCKING_BYCALLER);
2248 __fsetlocking (stdout, FSETLOCKING_BYCALLER);
2249 __fsetlocking (stderr, FSETLOCKING_BYCALLER);
2250
2251 /* Set locale. */
2252 setlocale (LC_ALL, "");
2253
2254 /* Make sure the message catalog can be found. */
Ulrich Drepperb0243862007-06-06 00:09:36 +00002255 bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Roland McGrath4be15242007-04-25 03:09:33 +00002256
2257 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +00002258 textdomain (PACKAGE_TARNAME);
Roland McGrath4be15242007-04-25 03:09:33 +00002259
2260 /* Parse and process arguments. */
2261 const struct argp_child argp_children[] =
2262 {
2263 {
2264 .argp = dwfl_standard_argp (),
2265 .header = N_("Input selection options:"),
2266 .group = 1,
2267 },
2268 { .argp = NULL },
2269 };
2270 const struct argp argp =
2271 {
2272 .options = options,
2273 .parser = parse_opt,
2274 .children = argp_children,
2275 .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"),
2276 .doc = N_("\
2277Combine stripped files with separate symbols and debug information.\v\
2278The first form puts the result in DEBUG-FILE if -o was not given.\n\
2279\n\
2280MODULE arguments give file name patterns matching modules to process.\n\
2281With -f these match the file name of the main (stripped) file \
2282(slashes are never special), otherwise they match the simple module names. \
2283With no arguments, process all modules found.\n\
2284\n\
2285Multiple modules are written to files under OUTPUT-DIRECTORY, \
2286creating subdirectories as needed. \
2287With -m these files have simple module names, otherwise they have the \
Roland McGrath59ea7f32007-10-04 08:50:09 +00002288name of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\
2289\n\
2290With -n no files are written, but one line to standard output for each module:\
2291\n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\
2292START and SIZE are hexadecimal giving the address bounds of the module. \
2293BUILDID is hexadecimal for the build ID bits, or - if no ID is known; \
2294the hexadecimal may be followed by @0xADDR giving the address where the \
2295ID resides if that is known. \
2296FILE is the file name found for the module, or - if none was found, \
2297or . if an ELF image is available but not from any named file. \
2298DEBUGFILE is the separate debuginfo file name, \
2299or - if no debuginfo was found, or . if FILE contains the debug information.\
2300")
Roland McGrath4be15242007-04-25 03:09:33 +00002301 };
2302
2303 int remaining;
2304 struct arg_info info = { .args = NULL };
2305 error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info);
2306 if (result == ENOSYS)
2307 assert (info.dwfl == NULL);
2308 else if (result)
2309 return EXIT_FAILURE;
2310 assert (info.args != NULL);
2311
2312 /* Tell the library which version we are expecting. */
2313 elf_version (EV_CURRENT);
2314
2315 if (info.dwfl == NULL)
2316 {
2317 assert (result == ENOSYS);
2318
2319 if (info.output_dir != NULL)
2320 {
2321 char *file;
2322 if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0)
2323 error (EXIT_FAILURE, 0, _("memory exhausted"));
Mark Wielaard22497092014-05-26 21:28:05 +02002324 handle_explicit_files (file, true, info.force,
2325 info.args[0], info.args[1]);
Roland McGrath4be15242007-04-25 03:09:33 +00002326 free (file);
2327 }
2328 else
Mark Wielaard22497092014-05-26 21:28:05 +02002329 handle_explicit_files (info.output_file, false, info.force,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00002330 info.args[0], info.args[1]);
Roland McGrath4be15242007-04-25 03:09:33 +00002331 }
2332 else
2333 {
2334 /* parse_opt checked this. */
Roland McGrath59ea7f32007-10-04 08:50:09 +00002335 assert (info.output_file != NULL || info.output_dir != NULL || info.list);
Roland McGrath4be15242007-04-25 03:09:33 +00002336
2337 handle_implicit_modules (&info);
2338
2339 dwfl_end (info.dwfl);
2340 }
2341
2342 return 0;
2343}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002344
2345
2346#include "debugpred.h"