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