blob: bc8ed5037c005c2e17d6ad571eb09a58805068ec [file] [log] [blame]
Roland McGrath4be15242007-04-25 03:09:33 +00001/* Combine stripped files with separate symbols and debug information.
Mark Wielaarddf7dfab2015-08-11 21:38:38 +02002 Copyright (C) 2007-2012, 2014, 2015 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 {
Josh Stone34254542015-10-09 10:10:37 -0700179 struct stat st;
Roland McGrath4be15242007-04-25 03:09:33 +0000180 error_t fail = 0;
Josh Stone34254542015-10-09 10:10:37 -0700181 if (stat (info->output_dir, &st) < 0)
Roland McGrath4be15242007-04-25 03:09:33 +0000182 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,
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -0700526 _("unexpected section type in [%zu] with sh_link to symtab"),
Roland McGrath4be15242007-04-25 03:09:33 +0000527 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,
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -0700774 _("invalid string offset in symbol [%zu]"), i);
Roland McGrath4be15242007-04-25 03:09:33 +0000775
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)
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -0700932 error (EXIT_FAILURE, 0, _("cannot read section [%zu] name: %s"),
Roland McGrath9aa8ef72007-05-18 08:59:43 +0000933 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
Mark Wielaard86ed7f72015-10-08 00:16:03 +02001016 bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
1017 size_t shsize = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
1018 if (unlikely ((shnum - 1) > SIZE_MAX / shsize))
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001019 error (EXIT_FAILURE, 0, _("overflow with shnum = %zu in '%s' section"),
1020 (size_t) shnum, ".gnu.prelink_undo");
Mark Wielaard86ed7f72015-10-08 00:16:03 +02001021 const size_t shdr_bytes = (shnum - 1) * shsize;
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001022 void *shdr = xmalloc (shdr_bytes);
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001023 dst.d_buf = shdr;
1024 dst.d_size = shdr_bytes;
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001025 ELF_CHECK (gelf_xlatetom (main, &dst, &src,
1026 main_ehdr->e_ident[EI_DATA]) != NULL,
1027 _("cannot read '.gnu.prelink_undo' section: %s"));
1028
1029 undo_sections = xmalloc ((shnum - 1) * sizeof undo_sections[0]);
1030 for (size_t i = 0; i < shnum - 1; ++i)
1031 {
1032 struct section *sec = &undo_sections[undo_nalloc];
Mark Wielaard86ed7f72015-10-08 00:16:03 +02001033 Elf32_Shdr (*s32)[shnum - 1] = shdr;
1034 Elf64_Shdr (*s64)[shnum - 1] = shdr;
1035 if (class32)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001036 {
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001037#define COPY(field) sec->shdr.field = (*s32)[i].field
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001038 COPY (sh_name);
1039 COPY (sh_type);
1040 COPY (sh_flags);
1041 COPY (sh_addr);
1042 COPY (sh_offset);
1043 COPY (sh_size);
1044 COPY (sh_link);
1045 COPY (sh_info);
1046 COPY (sh_addralign);
1047 COPY (sh_entsize);
1048#undef COPY
1049 }
1050 else
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001051 sec->shdr = (*s64)[i];
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001052 if (sec->shdr.sh_flags & SHF_ALLOC)
1053 {
1054 sec->shdr.sh_addr += bias;
1055 sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab);
1056 sec->scn = elf_getscn (main, i + 1); /* Really just for ndx. */
1057 sec->outscn = NULL;
1058 sec->strent = NULL;
1059 ++undo_nalloc;
1060 }
1061 }
1062 qsort (undo_sections, undo_nalloc,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001063 sizeof undo_sections[0], compare_sections_nonrel);
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -07001064 free (shdr);
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001065 }
1066
1067 bool fail = false;
1068 inline void check_match (bool match, Elf_Scn *scn, const char *name)
1069 {
1070 if (!match)
1071 {
1072 fail = true;
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -07001073 error (0, 0, _("cannot find matching section for [%zu] '%s'"),
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001074 elf_ndxscn (scn), name);
1075 }
1076 }
1077
1078 Elf_Scn *scn = NULL;
1079 while ((scn = elf_nextscn (debug, scn)) != NULL)
1080 {
1081 GElf_Shdr shdr_mem;
1082 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1083 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1084
1085 if (!(shdr->sh_flags & SHF_ALLOC))
1086 continue;
1087
1088 const char *name = get_section_name (elf_ndxscn (scn), shdr,
1089 debug_shstrtab);
1090
1091 if (undo_sections != NULL)
1092 {
1093 struct section *sec = find_alloc_section (shdr, 0, name,
1094 undo_sections,
1095 undo_nalloc);
1096 if (sec != NULL)
1097 {
1098 sec->outscn = scn;
1099 continue;
1100 }
1101 }
1102
1103 /* If there is no prelink info, we are just here to find
1104 the sections to give error messages about. */
1105 for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
1106 if (sections[i].outscn == scn)
1107 shdr = NULL;
1108 check_match (shdr == NULL, scn, name);
1109 }
1110
1111 if (fail)
1112 exit (EXIT_FAILURE);
1113
1114 /* Now we have lined up output sections for each of the original sections
1115 before prelinking. Translate those to the prelinked sections.
1116 This matches what prelink's undo_sections does. */
1117 struct section *split_bss = NULL;
1118 for (size_t i = 0; i < undo_nalloc; ++i)
1119 {
1120 const struct section *undo_sec = &undo_sections[i];
1121
1122 const char *name = undo_sec->name;
1123 scn = undo_sec->scn; /* This is just for elf_ndxscn. */
1124
1125 for (size_t j = 0; j < nalloc; ++j)
1126 {
1127 struct section *sec = &sections[j];
1128#define RELA_SCALED(field) \
1129 (2 * sec->shdr.field == 3 * undo_sec->shdr.field)
1130 if (sec->outscn == NULL
1131 && sec->shdr.sh_name == undo_sec->shdr.sh_name
1132 && sec->shdr.sh_flags == undo_sec->shdr.sh_flags
1133 && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign
1134 && (((sec->shdr.sh_type == undo_sec->shdr.sh_type
1135 && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1136 && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1137 || (sec->shdr.sh_size > undo_sec->shdr.sh_size
1138 && main_ehdr->e_type == ET_EXEC
1139 && !strcmp (sec->name, ".dynstr"))))
1140 || (sec->shdr.sh_size == undo_sec->shdr.sh_size
1141 && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1142 && undo_sec->shdr.sh_type == SHT_NOBITS)
1143 || undo_sec->shdr.sh_type == SHT_PROGBITS)
1144 && !strcmp (sec->name, ".plt")))
1145 || (sec->shdr.sh_type == SHT_RELA
1146 && undo_sec->shdr.sh_type == SHT_REL
1147 && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size))
1148 || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
1149 && (sec->shdr.sh_type == undo_sec->shdr.sh_type
1150 || (sec->shdr.sh_type == SHT_PROGBITS
1151 && undo_sec->shdr.sh_type == SHT_NOBITS))
Mark Wielaardbd1a0d12014-05-26 22:35:30 +02001152 && sec->shdr.sh_size <= undo_sec->shdr.sh_size
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001153 && (!strcmp (sec->name, ".bss")
1154 || !strcmp (sec->name, ".sbss"))
Mark Wielaardbd1a0d12014-05-26 22:35:30 +02001155 && (sec->shdr.sh_size == undo_sec->shdr.sh_size
1156 || (split_bss = sec) > sections))))
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001157 {
1158 sec->outscn = undo_sec->outscn;
1159 undo_sec = NULL;
1160 break;
1161 }
1162 }
1163
1164 check_match (undo_sec == NULL, scn, name);
1165 }
1166
1167 free (undo_sections);
1168
1169 if (fail)
1170 exit (EXIT_FAILURE);
1171
1172 return split_bss;
1173}
1174
Roland McGrathcb6d8652007-08-23 08:10:54 +00001175/* Create new .shstrtab contents, subroutine of copy_elided_sections.
1176 This can't be open coded there and still use variable-length auto arrays,
1177 since the end of our block would free other VLAs too. */
1178static Elf_Data *
1179new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
1180 Elf_Data *shstrtab, size_t unstripped_shstrndx,
1181 struct section *sections, size_t stripped_shnum,
1182 struct Ebl_Strtab *strtab)
1183{
1184 if (strtab == NULL)
1185 return NULL;
1186
1187 struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
1188 memset (unstripped_strent, 0, sizeof unstripped_strent);
1189 for (struct section *sec = sections;
1190 sec < &sections[stripped_shnum - 1];
1191 ++sec)
1192 if (sec->outscn != NULL)
1193 {
1194 if (sec->strent == NULL)
1195 {
1196 sec->strent = ebl_strtabadd (strtab, sec->name, 0);
1197 ELF_CHECK (sec->strent != NULL,
1198 _("cannot add section name to string table: %s"));
1199 }
1200 unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
1201 }
1202
1203 /* Add names of sections we aren't touching. */
1204 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1205 if (unstripped_strent[i] == NULL)
1206 {
1207 Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1208 GElf_Shdr shdr_mem;
1209 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1210 const char *name = get_section_name (i + 1, shdr, shstrtab);
1211 unstripped_strent[i] = ebl_strtabadd (strtab, name, 0);
1212 ELF_CHECK (unstripped_strent[i] != NULL,
1213 _("cannot add section name to string table: %s"));
1214 }
1215 else
1216 unstripped_strent[i] = NULL;
1217
1218 /* Now finalize the string table so we can get offsets. */
1219 Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
1220 unstripped_shstrndx), NULL);
1221 ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
1222 _("cannot update section header string table data: %s"));
1223 ebl_strtabfinalize (strtab, strtab_data);
1224
1225 /* Update the sh_name fields of sections we aren't modifying later. */
1226 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1227 if (unstripped_strent[i] != NULL)
1228 {
1229 Elf_Scn *scn = elf_getscn (unstripped, i + 1);
1230 GElf_Shdr shdr_mem;
1231 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1232 shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]);
1233 if (i + 1 == unstripped_shstrndx)
1234 shdr->sh_size = strtab_data->d_size;
Roland McGrathaa32f922010-06-04 02:29:08 -07001235 update_shdr (scn, shdr);
Roland McGrathcb6d8652007-08-23 08:10:54 +00001236 }
1237
1238 return strtab_data;
1239}
1240
Roland McGrath4be15242007-04-25 03:09:33 +00001241/* Fill in any SHT_NOBITS sections in UNSTRIPPED by
1242 copying their contents and sh_type from STRIPPED. */
1243static void
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001244copy_elided_sections (Elf *unstripped, Elf *stripped,
1245 const GElf_Ehdr *stripped_ehdr, GElf_Addr bias)
Roland McGrath4be15242007-04-25 03:09:33 +00001246{
1247 size_t unstripped_shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001248 ELF_CHECK (elf_getshdrstrndx (unstripped, &unstripped_shstrndx) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001249 _("cannot get section header string table section index: %s"));
1250
1251 size_t stripped_shstrndx;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001252 ELF_CHECK (elf_getshdrstrndx (stripped, &stripped_shstrndx) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001253 _("cannot get section header string table section index: %s"));
1254
1255 size_t unstripped_shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001256 ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001257 _("cannot get section count: %s"));
1258
1259 size_t stripped_shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -07001260 ELF_CHECK (elf_getshdrnum (stripped, &stripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001261 _("cannot get section count: %s"));
1262
Roland McGrath3b1b6512010-06-04 02:26:30 -07001263 if (unlikely (stripped_shnum > unstripped_shnum))
1264 error (EXIT_FAILURE, 0, _("\
1265more sections in stripped file than debug file -- arguments reversed?"));
1266
Roland McGrath4be15242007-04-25 03:09:33 +00001267 /* Cache the stripped file's section details. */
1268 struct section sections[stripped_shnum - 1];
1269 Elf_Scn *scn = NULL;
1270 while ((scn = elf_nextscn (stripped, scn)) != NULL)
1271 {
1272 size_t i = elf_ndxscn (scn) - 1;
1273 GElf_Shdr *shdr = gelf_getshdr (scn, &sections[i].shdr);
1274 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1275 sections[i].name = elf_strptr (stripped, stripped_shstrndx,
1276 shdr->sh_name);
1277 if (sections[i].name == NULL)
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -07001278 error (EXIT_FAILURE, 0, _("cannot read section [%zu] name: %s"),
Roland McGrath4be15242007-04-25 03:09:33 +00001279 elf_ndxscn (scn), elf_errmsg (-1));
1280 sections[i].scn = scn;
1281 sections[i].outscn = NULL;
1282 sections[i].strent = NULL;
1283 }
1284
1285 const struct section *stripped_symtab = NULL;
1286
1287 /* Sort the sections, allocated by address and others after. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001288 qsort (sections, stripped_shnum - 1, sizeof sections[0],
1289 stripped_ehdr->e_type == ET_REL
1290 ? compare_sections_rel : compare_sections_nonrel);
Roland McGrath4be15242007-04-25 03:09:33 +00001291 size_t nalloc = stripped_shnum - 1;
1292 while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
1293 {
1294 --nalloc;
1295 if (sections[nalloc].shdr.sh_type == SHT_SYMTAB)
1296 stripped_symtab = &sections[nalloc];
1297 }
1298
Roland McGrath4be15242007-04-25 03:09:33 +00001299 /* Locate a matching unallocated section in SECTIONS. */
1300 inline struct section *find_unalloc_section (const GElf_Shdr *shdr,
1301 const char *name)
1302 {
1303 size_t l = nalloc, u = stripped_shnum - 1;
1304 while (l < u)
1305 {
1306 size_t i = (l + u) / 2;
1307 struct section *sec = &sections[i];
1308 int cmp = compare_unalloc_sections (shdr, &sec->shdr,
1309 name, sec->name);
1310 if (cmp < 0)
1311 u = i;
1312 else if (cmp > 0)
1313 l = i + 1;
1314 else
1315 return sec;
1316 }
1317 return NULL;
1318 }
1319
1320 Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
1321 unstripped_shstrndx), NULL);
1322 ELF_CHECK (shstrtab != NULL,
1323 _("cannot read section header string table: %s"));
Roland McGrath4be15242007-04-25 03:09:33 +00001324
1325 /* Match each debuginfo section with its corresponding stripped section. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001326 bool check_prelink = false;
Roland McGrath4be15242007-04-25 03:09:33 +00001327 Elf_Scn *unstripped_symtab = NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001328 size_t alloc_avail = 0;
Roland McGrath4be15242007-04-25 03:09:33 +00001329 scn = NULL;
1330 while ((scn = elf_nextscn (unstripped, scn)) != NULL)
1331 {
1332 GElf_Shdr shdr_mem;
1333 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1334 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1335
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001336 if (shdr->sh_type == SHT_SYMTAB)
Roland McGrath4be15242007-04-25 03:09:33 +00001337 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001338 unstripped_symtab = scn;
Roland McGrath4be15242007-04-25 03:09:33 +00001339 continue;
1340 }
1341
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001342 const size_t ndx = elf_ndxscn (scn);
1343 if (ndx == unstripped_shstrndx)
1344 continue;
1345
1346 const char *name = get_section_name (ndx, shdr, shstrtab);
Roland McGrath4be15242007-04-25 03:09:33 +00001347
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001348 struct section *sec = NULL;
1349 if (shdr->sh_flags & SHF_ALLOC)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001350 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001351 if (stripped_ehdr->e_type != ET_REL)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001352 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001353 /* Look for the section that matches. */
1354 sec = find_alloc_section (shdr, bias, name, sections, nalloc);
1355 if (sec == NULL)
1356 {
1357 /* We couldn't figure it out. It may be a prelink issue. */
1358 check_prelink = true;
1359 continue;
1360 }
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001361 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001362 else
1363 {
1364 /* The sh_addr of allocated sections does not help us,
1365 but the order usually matches. */
1366 if (likely (sections_match (sections, alloc_avail, shdr, name)))
1367 sec = &sections[alloc_avail++];
1368 else
1369 for (size_t i = alloc_avail + 1; i < nalloc; ++i)
1370 if (sections_match (sections, i, shdr, name))
1371 {
1372 sec = &sections[i];
1373 break;
1374 }
1375 }
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001376 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001377 else
1378 {
1379 /* Look for the section that matches. */
1380 sec = find_unalloc_section (shdr, name);
1381 if (sec == NULL)
1382 {
1383 /* An additional unallocated section is fine if not SHT_NOBITS.
1384 We looked it up anyway in case it's an unallocated section
1385 copied in both files (e.g. SHT_NOTE), and don't keep both. */
1386 if (shdr->sh_type != SHT_NOBITS)
1387 continue;
1388
1389 /* Somehow some old .debug files wound up with SHT_NOBITS
1390 .comment sections, so let those pass. */
1391 if (!strcmp (name, ".comment"))
1392 continue;
1393 }
1394 }
1395
1396 if (sec == NULL)
1397 error (EXIT_FAILURE, 0,
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -07001398 _("cannot find matching section for [%zu] '%s'"),
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001399 elf_ndxscn (scn), name);
Roland McGrath4be15242007-04-25 03:09:33 +00001400
1401 sec->outscn = scn;
1402 }
1403
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001404 /* If that failed due to changes made by prelink, we take another tack.
1405 We keep track of a .bss section that was partly split into .dynbss
1406 so that collect_symbols can update symbols' st_shndx fields. */
1407 struct section *split_bss = NULL;
1408 if (check_prelink)
1409 {
1410 Elf_Data *data = elf_getdata (elf_getscn (stripped, stripped_shstrndx),
1411 NULL);
1412 ELF_CHECK (data != NULL,
1413 _("cannot read section header string table: %s"));
1414 split_bss = find_alloc_sections_prelink (unstripped, shstrtab,
1415 stripped, stripped_ehdr,
1416 data, bias, sections,
1417 nalloc, stripped_shnum - 1);
1418 }
1419
Roland McGrath4be15242007-04-25 03:09:33 +00001420 /* Make sure each main file section has a place to go. */
1421 const struct section *stripped_dynsym = NULL;
1422 size_t debuglink = SHN_UNDEF;
1423 size_t ndx_section[stripped_shnum - 1];
1424 struct Ebl_Strtab *strtab = NULL;
1425 for (struct section *sec = sections;
1426 sec < &sections[stripped_shnum - 1];
1427 ++sec)
1428 {
1429 size_t secndx = elf_ndxscn (sec->scn);
1430
1431 if (sec->outscn == NULL)
1432 {
1433 /* We didn't find any corresponding section for this. */
1434
1435 if (secndx == stripped_shstrndx)
1436 {
1437 /* We only need one .shstrtab. */
1438 ndx_section[secndx - 1] = unstripped_shstrndx;
1439 continue;
1440 }
1441
1442 if (unstripped_symtab != NULL && sec == stripped_symtab)
1443 {
1444 /* We don't need a second symbol table. */
1445 ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab);
1446 continue;
1447 }
1448
1449 if (unstripped_symtab != NULL && stripped_symtab != NULL
1450 && secndx == stripped_symtab->shdr.sh_link)
1451 {
1452 /* ... nor its string table. */
1453 GElf_Shdr shdr_mem;
1454 GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1455 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1456 ndx_section[secndx - 1] = shdr->sh_link;
1457 continue;
1458 }
1459
1460 if (!(sec->shdr.sh_flags & SHF_ALLOC)
1461 && !strcmp (sec->name, ".gnu_debuglink"))
1462 {
1463 /* This was created by stripping. We don't want it. */
1464 debuglink = secndx;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001465 ndx_section[secndx - 1] = SHN_UNDEF;
Roland McGrath4be15242007-04-25 03:09:33 +00001466 continue;
1467 }
1468
1469 sec->outscn = elf_newscn (unstripped);
1470 Elf_Data *newdata = elf_newdata (sec->outscn);
1471 ELF_CHECK (newdata != NULL && gelf_update_shdr (sec->outscn,
1472 &sec->shdr),
1473 _("cannot add new section: %s"));
1474
1475 if (strtab == NULL)
1476 strtab = ebl_strtabinit (true);
1477 sec->strent = ebl_strtabadd (strtab, sec->name, 0);
1478 ELF_CHECK (sec->strent != NULL,
1479 _("cannot add section name to string table: %s"));
1480 }
1481
1482 /* Cache the mapping of original section indices to output sections. */
1483 ndx_section[secndx - 1] = elf_ndxscn (sec->outscn);
1484 }
1485
Roland McGrathcb6d8652007-08-23 08:10:54 +00001486 /* We added some sections, so we need a new shstrtab. */
1487 Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum,
1488 shstrtab, unstripped_shstrndx,
1489 sections, stripped_shnum,
1490 strtab);
Roland McGrath4be15242007-04-25 03:09:33 +00001491
1492 /* Get the updated section count. */
Ulrich Drepperf1894932009-06-13 15:55:42 -07001493 ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
Roland McGrath4be15242007-04-25 03:09:33 +00001494 _("cannot get section count: %s"));
1495
1496 bool placed[unstripped_shnum - 1];
1497 memset (placed, 0, sizeof placed);
1498
1499 /* Now update the output sections and copy in their data. */
1500 GElf_Off offset = 0;
1501 for (const struct section *sec = sections;
1502 sec < &sections[stripped_shnum - 1];
1503 ++sec)
1504 if (sec->outscn != NULL)
1505 {
1506 GElf_Shdr shdr_mem;
1507 GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem);
1508 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1509
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001510 /* In an ET_REL file under --relocate, the sh_addr of SHF_ALLOC
1511 sections will have been set nonzero by relocation. This
1512 touched the shdrs of whichever file had the symtab. sh_addr
1513 is still zero in the corresponding shdr. The relocated
1514 address is what we want to use. */
1515 if (stripped_ehdr->e_type != ET_REL
1516 || !(shdr_mem.sh_flags & SHF_ALLOC)
1517 || shdr_mem.sh_addr == 0)
1518 shdr_mem.sh_addr = sec->shdr.sh_addr;
1519
Roland McGrath4be15242007-04-25 03:09:33 +00001520 shdr_mem.sh_type = sec->shdr.sh_type;
1521 shdr_mem.sh_size = sec->shdr.sh_size;
1522 shdr_mem.sh_info = sec->shdr.sh_info;
1523 shdr_mem.sh_link = sec->shdr.sh_link;
Mark Wielaardf9fc50c2015-07-29 17:51:27 +02001524
1525 /* Buggy binutils objdump might have stripped the SHF_INFO_LINK
1526 put it back if necessary. */
1527 if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
1528 && sec->shdr.sh_flags != shdr_mem.sh_flags
1529 && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
1530 shdr_mem.sh_flags |= SHF_INFO_LINK;
1531
Roland McGrath4be15242007-04-25 03:09:33 +00001532 if (sec->shdr.sh_link != SHN_UNDEF)
1533 shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
Mark Wielaard2e084502015-10-02 16:31:36 +02001534 if (SH_INFO_LINK_P (&sec->shdr) && sec->shdr.sh_info != 0)
Roland McGrath4be15242007-04-25 03:09:33 +00001535 shdr_mem.sh_info = ndx_section[sec->shdr.sh_info - 1];
1536
1537 if (strtab != NULL)
1538 shdr_mem.sh_name = ebl_strtaboffset (sec->strent);
1539
1540 Elf_Data *indata = elf_getdata (sec->scn, NULL);
1541 ELF_CHECK (indata != NULL, _("cannot get section data: %s"));
1542 Elf_Data *outdata = elf_getdata (sec->outscn, NULL);
1543 ELF_CHECK (outdata != NULL, _("cannot copy section data: %s"));
1544 *outdata = *indata;
1545 elf_flagdata (outdata, ELF_C_SET, ELF_F_DIRTY);
1546
1547 /* Preserve the file layout of the allocated sections. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001548 if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
Roland McGrath4be15242007-04-25 03:09:33 +00001549 {
1550 shdr_mem.sh_offset = sec->shdr.sh_offset;
1551 placed[elf_ndxscn (sec->outscn) - 1] = true;
1552
1553 const GElf_Off end_offset = (shdr_mem.sh_offset
1554 + (shdr_mem.sh_type == SHT_NOBITS
1555 ? 0 : shdr_mem.sh_size));
1556 if (end_offset > offset)
1557 offset = end_offset;
1558 }
1559
Roland McGrathaa32f922010-06-04 02:29:08 -07001560 update_shdr (sec->outscn, &shdr_mem);
Roland McGrath4be15242007-04-25 03:09:33 +00001561
1562 if (shdr_mem.sh_type == SHT_SYMTAB || shdr_mem.sh_type == SHT_DYNSYM)
1563 {
1564 /* We must adjust all the section indices in the symbol table. */
1565
1566 Elf_Data *shndxdata = NULL; /* XXX */
1567
1568 for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i)
1569 {
1570 GElf_Sym sym_mem;
1571 GElf_Word shndx = SHN_UNDEF;
1572 GElf_Sym *sym = gelf_getsymshndx (outdata, shndxdata,
1573 i, &sym_mem, &shndx);
1574 ELF_CHECK (sym != NULL,
1575 _("cannot get symbol table entry: %s"));
1576 if (sym->st_shndx != SHN_XINDEX)
1577 shndx = sym->st_shndx;
1578
1579 if (shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
1580 {
1581 if (shndx >= stripped_shnum)
1582 error (EXIT_FAILURE, 0,
Chih-Hung Hsieh2ec95732015-09-04 10:13:02 -07001583 _("symbol [%zu] has invalid section index"), i);
Roland McGrath4be15242007-04-25 03:09:33 +00001584
1585 shndx = ndx_section[shndx - 1];
1586 if (shndx < SHN_LORESERVE)
1587 {
1588 sym->st_shndx = shndx;
1589 shndx = SHN_UNDEF;
1590 }
1591 else
1592 sym->st_shndx = SHN_XINDEX;
1593
1594 ELF_CHECK (gelf_update_symshndx (outdata, shndxdata,
1595 i, sym, shndx),
1596 _("cannot update symbol table: %s"));
1597 }
1598 }
1599
1600 if (shdr_mem.sh_type == SHT_SYMTAB)
1601 stripped_symtab = sec;
1602 if (shdr_mem.sh_type == SHT_DYNSYM)
1603 stripped_dynsym = sec;
1604 }
1605 }
1606
1607 /* We may need to update the symbol table. */
1608 Elf_Data *symdata = NULL;
1609 struct Ebl_Strtab *symstrtab = NULL;
1610 Elf_Data *symstrdata = NULL;
1611 if (unstripped_symtab != NULL && (stripped_symtab != NULL
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001612 || check_prelink /* Section adjustments. */
1613 || (stripped_ehdr->e_type != ET_REL
1614 && bias != 0)))
Roland McGrath4be15242007-04-25 03:09:33 +00001615 {
1616 /* Merge the stripped file's symbol table into the unstripped one. */
1617 const size_t stripped_nsym = (stripped_symtab == NULL ? 1
1618 : (stripped_symtab->shdr.sh_size
1619 / stripped_symtab->shdr.sh_entsize));
1620
1621 GElf_Shdr shdr_mem;
1622 GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1623 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1624 const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize;
1625
1626 /* First collect all the symbols from both tables. */
1627
1628 const size_t total_syms = stripped_nsym - 1 + unstripped_nsym - 1;
1629 struct symbol symbols[total_syms];
1630 size_t symndx_map[total_syms];
1631
1632 if (stripped_symtab != NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001633 collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
1634 stripped_symtab->scn,
Roland McGrath4be15242007-04-25 03:09:33 +00001635 elf_getscn (stripped, stripped_symtab->shdr.sh_link),
1636 stripped_nsym, 0, ndx_section,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001637 symbols, symndx_map, NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001638
1639 Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001640 collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001641 unstripped_symtab, unstripped_strtab, unstripped_nsym,
1642 stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL,
Roland McGrath4be15242007-04-25 03:09:33 +00001643 &symbols[stripped_nsym - 1],
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001644 &symndx_map[stripped_nsym - 1], split_bss);
Roland McGrath4be15242007-04-25 03:09:33 +00001645
1646 /* Next, sort our array of all symbols. */
1647 qsort (symbols, total_syms, sizeof symbols[0], compare_symbols);
1648
1649 /* Now we can weed out the duplicates. Assign remaining symbols
1650 new slots, collecting a map from old indices to new. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001651 size_t nsym = 0;
1652 for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s)
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001653 {
1654 /* Skip a section symbol for a removed section. */
1655 if (s->shndx == SHN_UNDEF
1656 && GELF_ST_TYPE (s->info.info) == STT_SECTION)
1657 {
1658 s->name = NULL; /* Mark as discarded. */
1659 *s->map = STN_UNDEF;
1660 s->duplicate = NULL;
1661 continue;
1662 }
1663
1664 struct symbol *n = s;
1665 while (n + 1 < &symbols[total_syms] && !compare_symbols (s, n + 1))
1666 ++n;
1667
1668 while (s < n)
1669 {
1670 /* This is a duplicate. Its twin will get the next slot. */
1671 s->name = NULL; /* Mark as discarded. */
1672 s->duplicate = n->map;
1673 ++s;
1674 }
1675
1676 /* Allocate the next slot. */
1677 *s->map = ++nsym;
1678 }
Roland McGrath4be15242007-04-25 03:09:33 +00001679
1680 /* Now we sort again, to determine the order in the output. */
1681 qsort (symbols, total_syms, sizeof symbols[0], compare_symbols_output);
1682
1683 if (nsym < total_syms)
1684 /* The discarded symbols are now at the end of the table. */
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001685 assert (symbols[nsym].name == NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001686
1687 /* Now a final pass updates the map with the final order,
1688 and builds up the new string table. */
1689 symstrtab = ebl_strtabinit (true);
1690 for (size_t i = 0; i < nsym; ++i)
1691 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001692 assert (symbols[i].name != NULL);
Roland McGrath4be15242007-04-25 03:09:33 +00001693 assert (*symbols[i].map != 0);
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001694 *symbols[i].map = 1 + i;
Roland McGrath4be15242007-04-25 03:09:33 +00001695 symbols[i].strent = ebl_strtabadd (symstrtab, symbols[i].name, 0);
1696 }
1697
Roland McGrathe4c22ea2007-10-23 13:07:39 +00001698 /* Scan the discarded symbols too, just to update their slots
1699 in SYMNDX_MAP to refer to their live duplicates. */
1700 for (size_t i = nsym; i < total_syms; ++i)
1701 {
1702 assert (symbols[i].name == NULL);
1703 if (symbols[i].duplicate == NULL)
1704 assert (*symbols[i].map == STN_UNDEF);
1705 else
1706 {
1707 assert (*symbols[i].duplicate != STN_UNDEF);
1708 *symbols[i].map = *symbols[i].duplicate;
1709 }
1710 }
1711
Roland McGrath4be15242007-04-25 03:09:33 +00001712 /* Now we are ready to write the new symbol table. */
1713 symdata = elf_getdata (unstripped_symtab, NULL);
1714 symstrdata = elf_getdata (unstripped_strtab, NULL);
1715 Elf_Data *shndxdata = NULL; /* XXX */
1716
Mark Wielaarddf7dfab2015-08-11 21:38:38 +02001717 /* If symtab and the section header table share the string table
1718 add the section names to the strtab and then (after finalizing)
1719 fixup the section header sh_names. Also dispose of the old data. */
1720 struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
1721 if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
1722 {
1723 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1724 {
1725 Elf_Scn *sec = elf_getscn (unstripped, i + 1);
1726 GElf_Shdr mem;
1727 GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
1728 const char *name = get_section_name (i + 1, hdr, shstrtab);
1729 unstripped_strent[i + 1] = ebl_strtabadd (symstrtab, name, 0);
1730 ELF_CHECK (unstripped_strent[i + 1] != NULL,
1731 _("cannot add section name to string table: %s"));
1732 }
1733
1734 if (strtab != NULL)
1735 {
1736 ebl_strtabfree (strtab);
1737 free (strtab_data->d_buf);
1738 strtab = NULL;
1739 }
1740 }
1741
Roland McGrath4be15242007-04-25 03:09:33 +00001742 ebl_strtabfinalize (symstrtab, symstrdata);
1743 elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY);
1744
Mark Wielaarddf7dfab2015-08-11 21:38:38 +02001745 /* And update the section header names if necessary. */
1746 if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
1747 {
1748 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1749 {
1750 Elf_Scn *sec = elf_getscn (unstripped, i + 1);
1751 GElf_Shdr mem;
1752 GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
1753 shdr->sh_name = ebl_strtaboffset (unstripped_strent[i + 1]);
1754 update_shdr (sec, hdr);
1755 }
1756 }
1757
1758 /* Now update the symtab shdr. Reload symtab shdr because sh_name
1759 might have changed above. */
1760 shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
1761 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1762
Roland McGrath4be15242007-04-25 03:09:33 +00001763 shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
1764 symdata->d_buf = xmalloc (symdata->d_size);
1765
1766 GElf_Sym sym;
1767 memset (&sym, 0, sizeof sym);
1768 ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 0, &sym, SHN_UNDEF),
1769 _("cannot update symbol table: %s"));
1770
1771 shdr->sh_info = 1;
1772 for (size_t i = 0; i < nsym; ++i)
1773 {
1774 struct symbol *s = &symbols[i];
1775
1776 /* Fill in the symbol details. */
1777 sym.st_name = ebl_strtaboffset (s->strent);
1778 sym.st_value = s->value; /* Already biased to output address. */
1779 sym.st_size = s->size;
1780 sym.st_shndx = s->shndx; /* Already mapped to output index. */
1781 sym.st_info = s->info.info;
1782 sym.st_other = s->info.other;
1783
1784 /* Keep track of the number of leading local symbols. */
1785 if (GELF_ST_BIND (sym.st_info) == STB_LOCAL)
1786 {
1787 assert (shdr->sh_info == 1 + i);
1788 shdr->sh_info = 1 + i + 1;
1789 }
1790
1791 ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 1 + i,
1792 &sym, SHN_UNDEF),
1793 _("cannot update symbol table: %s"));
1794
1795 }
1796 elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY);
Roland McGrathaa32f922010-06-04 02:29:08 -07001797 update_shdr (unstripped_symtab, shdr);
Roland McGrath4be15242007-04-25 03:09:33 +00001798
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001799 if (stripped_symtab != NULL)
1800 {
1801 /* Adjust any relocations referring to the old symbol table. */
1802 const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn);
1803 for (const struct section *sec = sections;
1804 sec < &sections[stripped_shnum - 1];
1805 ++sec)
1806 if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link)
1807 adjust_relocs (sec->outscn, sec->scn, &sec->shdr,
1808 symndx_map, shdr);
1809 }
Roland McGrath4be15242007-04-25 03:09:33 +00001810
1811 /* Also adjust references to the other old symbol table. */
1812 adjust_all_relocs (unstripped, unstripped_symtab, shdr,
1813 &symndx_map[stripped_nsym - 1]);
1814 }
1815 else if (stripped_symtab != NULL && stripped_shnum != unstripped_shnum)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001816 check_symtab_section_symbols (unstripped,
1817 stripped_ehdr->e_type == ET_REL,
1818 stripped_symtab->scn,
Roland McGrath4be15242007-04-25 03:09:33 +00001819 unstripped_shnum, unstripped_shstrndx,
1820 stripped_symtab->outscn,
1821 stripped_shnum, stripped_shstrndx,
1822 debuglink);
1823
1824 if (stripped_dynsym != NULL)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00001825 (void) check_symtab_section_symbols (unstripped,
1826 stripped_ehdr->e_type == ET_REL,
1827 stripped_dynsym->outscn,
Roland McGrath4be15242007-04-25 03:09:33 +00001828 unstripped_shnum,
1829 unstripped_shstrndx,
1830 stripped_dynsym->scn, stripped_shnum,
1831 stripped_shstrndx, debuglink);
1832
1833 /* We need to preserve the layout of the stripped file so the
1834 phdrs will match up. This requires us to do our own layout of
1835 the added sections. We do manual layout even for ET_REL just
1836 so we can try to match what the original probably had. */
1837
1838 elf_flagelf (unstripped, ELF_C_SET, ELF_F_LAYOUT);
1839
1840 if (offset == 0)
1841 /* For ET_REL we are starting the layout from scratch. */
1842 offset = gelf_fsize (unstripped, ELF_T_EHDR, 1, EV_CURRENT);
1843
1844 bool skip_reloc = false;
1845 do
1846 {
1847 skip_reloc = !skip_reloc;
1848 for (size_t i = 0; i < unstripped_shnum - 1; ++i)
1849 if (!placed[i])
1850 {
1851 scn = elf_getscn (unstripped, 1 + i);
1852
1853 GElf_Shdr shdr_mem;
1854 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1855 ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
1856
Roland McGrathec86e5f2010-06-14 17:44:38 -07001857 /* We must make sure we have read in the data of all sections
1858 beforehand and marked them to be written out. When we're
1859 modifying the existing file in place, we might overwrite
1860 this part of the file before we get to handling the section. */
1861
1862 ELF_CHECK (elf_flagdata (elf_getdata (scn, NULL),
1863 ELF_C_SET, ELF_F_DIRTY),
1864 _("cannot read section data: %s"));
1865
Roland McGrath4be15242007-04-25 03:09:33 +00001866 if (skip_reloc
1867 && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
1868 continue;
1869
1870 GElf_Off align = shdr->sh_addralign ?: 1;
1871 offset = (offset + align - 1) & -align;
1872 shdr->sh_offset = offset;
1873 if (shdr->sh_type != SHT_NOBITS)
1874 offset += shdr->sh_size;
1875
Roland McGrathaa32f922010-06-04 02:29:08 -07001876 update_shdr (scn, shdr);
Roland McGrath4be15242007-04-25 03:09:33 +00001877
1878 if (unstripped_shstrndx == 1 + i)
1879 {
1880 /* Place the section headers immediately after
1881 .shstrtab, and update the ELF header. */
1882
1883 GElf_Ehdr ehdr_mem;
1884 GElf_Ehdr *ehdr = gelf_getehdr (unstripped, &ehdr_mem);
1885 ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
1886
1887 GElf_Off sh_align = gelf_getclass (unstripped) * 4;
1888 offset = (offset + sh_align - 1) & -sh_align;
1889 ehdr->e_shnum = unstripped_shnum;
1890 ehdr->e_shoff = offset;
1891 offset += unstripped_shnum * ehdr->e_shentsize;
1892 ELF_CHECK (gelf_update_ehdr (unstripped, ehdr),
1893 _("cannot update ELF header: %s"));
1894 }
1895
1896 placed[i] = true;
1897 }
Roland McGrathec86e5f2010-06-14 17:44:38 -07001898 }
1899 while (skip_reloc);
Roland McGrath4be15242007-04-25 03:09:33 +00001900
Mark Wielaard712c8fa2014-11-22 23:08:48 +01001901 size_t phnum;
1902 ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
1903 _("cannot get number of program headers: %s"));
1904
1905 if (phnum > 0)
1906 ELF_CHECK (gelf_newphdr (unstripped, phnum),
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001907 _("cannot create program headers: %s"));
1908
Roland McGrath4be15242007-04-25 03:09:33 +00001909 /* Copy each program header from the stripped file. */
Mark Wielaard712c8fa2014-11-22 23:08:48 +01001910 for (size_t i = 0; i < phnum; ++i)
Roland McGrath4be15242007-04-25 03:09:33 +00001911 {
1912 GElf_Phdr phdr_mem;
1913 GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
1914 ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
1915
1916 ELF_CHECK (gelf_update_phdr (unstripped, i, phdr),
1917 _("cannot update program header: %s"));
1918 }
1919
1920 /* Finally, write out the file. */
1921 ELF_CHECK (elf_update (unstripped, ELF_C_WRITE) > 0,
1922 _("cannot write output file: %s"));
1923
1924 if (strtab != NULL)
1925 {
1926 ebl_strtabfree (strtab);
1927 free (strtab_data->d_buf);
1928 }
1929
1930 if (symdata != NULL)
1931 free (symdata->d_buf);
1932 if (symstrtab != NULL)
1933 {
1934 ebl_strtabfree (symstrtab);
1935 free (symstrdata->d_buf);
1936 }
1937}
1938
1939/* Process one pair of files, already opened. */
1940static void
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001941handle_file (const char *output_file, bool create_dirs,
Roland McGrath4be15242007-04-25 03:09:33 +00001942 Elf *stripped, const GElf_Ehdr *stripped_ehdr,
1943 Elf *unstripped)
1944{
Mark Wielaard712c8fa2014-11-22 23:08:48 +01001945 size_t phnum;
1946 ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
1947 _("cannot get number of program headers: %s"));
1948
Roland McGrath4be15242007-04-25 03:09:33 +00001949 /* Determine the address bias between the debuginfo file and the main
1950 file, which may have been modified by prelinking. */
1951 GElf_Addr bias = 0;
1952 if (unstripped != NULL)
Mark Wielaard712c8fa2014-11-22 23:08:48 +01001953 for (size_t i = 0; i < phnum; ++i)
Roland McGrath4be15242007-04-25 03:09:33 +00001954 {
1955 GElf_Phdr phdr_mem;
1956 GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
1957 ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
1958 if (phdr->p_type == PT_LOAD)
1959 {
1960 GElf_Phdr unstripped_phdr_mem;
1961 GElf_Phdr *unstripped_phdr = gelf_getphdr (unstripped, i,
1962 &unstripped_phdr_mem);
1963 ELF_CHECK (unstripped_phdr != NULL,
1964 _("cannot get program header: %s"));
1965 bias = phdr->p_vaddr - unstripped_phdr->p_vaddr;
1966 break;
1967 }
1968 }
1969
1970 /* One day we could adjust all the DWARF data (like prelink itself does). */
1971 if (bias != 0)
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001972 {
1973 if (output_file == NULL)
1974 error (0, 0, _("\
1975DWARF data not adjusted for prelinking bias; consider prelink -u"));
1976 else
1977 error (0, 0, _("\
1978DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"),
1979 output_file);
1980 }
Roland McGrath4be15242007-04-25 03:09:33 +00001981
1982 if (output_file == NULL)
1983 /* Modify the unstripped file in place. */
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001984 copy_elided_sections (unstripped, stripped, stripped_ehdr, bias);
Roland McGrath4be15242007-04-25 03:09:33 +00001985 else
1986 {
Roland McGrath9aa8ef72007-05-18 08:59:43 +00001987 if (create_dirs)
1988 make_directories (output_file);
1989
Roland McGrath4be15242007-04-25 03:09:33 +00001990 /* Copy the unstripped file and then modify it. */
Josh Stone34254542015-10-09 10:10:37 -07001991 int outfd = open (output_file, O_RDWR | O_CREAT,
Roland McGrath4be15242007-04-25 03:09:33 +00001992 stripped_ehdr->e_type == ET_REL ? 0666 : 0777);
1993 if (outfd < 0)
1994 error (EXIT_FAILURE, errno, _("cannot open '%s'"), output_file);
1995 Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
1996 ELF_CHECK (outelf != NULL, _("cannot create ELF descriptor: %s"));
1997
1998 if (unstripped == NULL)
1999 {
2000 /* Actually, we are just copying out the main file as it is. */
2001 copy_elf (outelf, stripped);
2002 if (stripped_ehdr->e_type != ET_REL)
2003 elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);
2004 ELF_CHECK (elf_update (outelf, ELF_C_WRITE) > 0,
2005 _("cannot write output file: %s"));
2006 }
2007 else
2008 {
2009 copy_elf (outelf, unstripped);
Roland McGrath9aa8ef72007-05-18 08:59:43 +00002010 copy_elided_sections (outelf, stripped, stripped_ehdr, bias);
Roland McGrath4be15242007-04-25 03:09:33 +00002011 }
2012
2013 elf_end (outelf);
2014 close (outfd);
2015 }
2016}
2017
2018static int
2019open_file (const char *file, bool writable)
2020{
Josh Stone34254542015-10-09 10:10:37 -07002021 int fd = open (file, writable ? O_RDWR : O_RDONLY);
Roland McGrath4be15242007-04-25 03:09:33 +00002022 if (fd < 0)
2023 error (EXIT_FAILURE, errno, _("cannot open '%s'"), file);
2024 return fd;
2025}
2026
2027/* Handle a pair of files we need to open by name. */
2028static void
Mark Wielaard22497092014-05-26 21:28:05 +02002029handle_explicit_files (const char *output_file, bool create_dirs, bool force,
Roland McGrath4be15242007-04-25 03:09:33 +00002030 const char *stripped_file, const char *unstripped_file)
2031{
Mark Wielaard22497092014-05-26 21:28:05 +02002032
2033 /* Warn, and exit if not forced to continue, if some ELF header
2034 sanity check for the stripped and unstripped files failed. */
2035 void warn (const char *msg)
2036 {
2037 error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
2038 force ? _("WARNING: ") : "",
2039 stripped_file, unstripped_file, msg,
2040 force ? "" : _(", use --force"));
2041 }
2042
Roland McGrath4be15242007-04-25 03:09:33 +00002043 int stripped_fd = open_file (stripped_file, false);
2044 Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
2045 GElf_Ehdr stripped_ehdr;
2046 ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
2047 _("cannot create ELF descriptor: %s"));
2048
2049 int unstripped_fd = -1;
2050 Elf *unstripped = NULL;
2051 if (unstripped_file != NULL)
2052 {
2053 unstripped_fd = open_file (unstripped_file, output_file == NULL);
2054 unstripped = elf_begin (unstripped_fd,
2055 (output_file == NULL ? ELF_C_RDWR : ELF_C_READ),
2056 NULL);
2057 GElf_Ehdr unstripped_ehdr;
2058 ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
2059 _("cannot create ELF descriptor: %s"));
2060
Mark Wielaard22497092014-05-26 21:28:05 +02002061 if (memcmp (stripped_ehdr.e_ident,
2062 unstripped_ehdr.e_ident, EI_NIDENT) != 0)
2063 warn (_("ELF header identification (e_ident) different"));
2064
2065 if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
2066 warn (_("ELF header type (e_type) different"));
2067
2068 if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
2069 warn (_("ELF header machine type (e_machine) different"));
2070
2071 if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
2072 warn (_("stripped program header (e_phnum) smaller than unstripped"));
Roland McGrath4be15242007-04-25 03:09:33 +00002073 }
2074
Roland McGrath9aa8ef72007-05-18 08:59:43 +00002075 handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
Roland McGrath4be15242007-04-25 03:09:33 +00002076
2077 elf_end (stripped);
2078 close (stripped_fd);
2079
2080 elf_end (unstripped);
2081 close (unstripped_fd);
2082}
2083
2084
2085/* Handle a pair of files opened implicitly by libdwfl for one module. */
2086static void
Mark Wielaard22497092014-05-26 21:28:05 +02002087handle_dwfl_module (const char *output_file, bool create_dirs, bool force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002088 Dwfl_Module *mod, bool all, bool ignore, bool relocate)
Roland McGrath4be15242007-04-25 03:09:33 +00002089{
2090 GElf_Addr bias;
2091 Elf *stripped = dwfl_module_getelf (mod, &bias);
2092 if (stripped == NULL)
2093 {
2094 if (ignore)
2095 return;
2096
2097 const char *file;
2098 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2099 NULL, NULL, &file, NULL);
2100 if (file == NULL)
2101 error (EXIT_FAILURE, 0,
2102 _("cannot find stripped file for module '%s': %s"),
2103 modname, dwfl_errmsg (-1));
2104 else
2105 error (EXIT_FAILURE, 0,
2106 _("cannot open stripped file '%s' for module '%s': %s"),
2107 modname, file, dwfl_errmsg (-1));
2108 }
2109
2110 Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias));
2111 if (debug == NULL && !all)
2112 {
2113 if (ignore)
2114 return;
2115
2116 const char *file;
2117 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2118 NULL, NULL, NULL, &file);
2119 if (file == NULL)
2120 error (EXIT_FAILURE, 0,
2121 _("cannot find debug file for module '%s': %s"),
2122 modname, dwfl_errmsg (-1));
2123 else
2124 error (EXIT_FAILURE, 0,
2125 _("cannot open debug file '%s' for module '%s': %s"),
2126 modname, file, dwfl_errmsg (-1));
2127 }
2128
2129 if (debug == stripped)
2130 {
2131 if (all)
2132 debug = NULL;
2133 else
2134 {
2135 const char *file;
2136 const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
2137 NULL, NULL, &file, NULL);
2138 error (EXIT_FAILURE, 0, _("module '%s' file '%s' is not stripped"),
2139 modname, file);
2140 }
2141 }
2142
2143 GElf_Ehdr stripped_ehdr;
2144 ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
2145 _("cannot create ELF descriptor: %s"));
2146
2147 if (stripped_ehdr.e_type == ET_REL)
2148 {
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002149 if (!relocate)
2150 {
2151 /* We can't use the Elf handles already open,
2152 because the DWARF sections have been relocated. */
Roland McGrath4be15242007-04-25 03:09:33 +00002153
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002154 const char *stripped_file = NULL;
2155 const char *unstripped_file = NULL;
2156 (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
2157 &stripped_file, &unstripped_file);
Roland McGrath4be15242007-04-25 03:09:33 +00002158
Mark Wielaard22497092014-05-26 21:28:05 +02002159 handle_explicit_files (output_file, create_dirs, force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002160 stripped_file, unstripped_file);
2161 return;
2162 }
2163
2164 /* Relocation is what we want! This ensures that all sections that can
2165 get sh_addr values assigned have them, even ones not used in DWARF.
2166 They might still be used in the symbol table. */
2167 if (dwfl_module_relocations (mod) < 0)
2168 error (EXIT_FAILURE, 0,
2169 _("cannot cache section addresses for module '%s': %s"),
2170 dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
2171 dwfl_errmsg (-1));
Roland McGrath4be15242007-04-25 03:09:33 +00002172 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002173
2174 handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug);
Roland McGrath4be15242007-04-25 03:09:33 +00002175}
2176
2177/* Handle one module being written to the output directory. */
2178static void
Mark Wielaard22497092014-05-26 21:28:05 +02002179handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002180 bool all, bool ignore, bool modnames, bool relocate)
Roland McGrath4be15242007-04-25 03:09:33 +00002181{
2182 if (! modnames)
2183 {
2184 /* Make sure we've searched for the ELF file. */
2185 GElf_Addr bias;
2186 (void) dwfl_module_getelf (mod, &bias);
2187 }
2188
2189 const char *file;
2190 const char *name = dwfl_module_info (mod, NULL, NULL, NULL,
2191 NULL, NULL, &file, NULL);
2192
2193 if (file == NULL && ignore)
2194 return;
2195
2196 char *output_file;
2197 if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0)
2198 error (EXIT_FAILURE, 0, _("memory exhausted"));
2199
Mark Wielaard22497092014-05-26 21:28:05 +02002200 handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002201}
2202
2203
Roland McGrath59ea7f32007-10-04 08:50:09 +00002204static void
2205list_module (Dwfl_Module *mod)
2206{
2207 /* Make sure we have searched for the files. */
2208 GElf_Addr bias;
2209 bool have_elf = dwfl_module_getelf (mod, &bias) != NULL;
2210 bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL;
2211
2212 const char *file;
2213 const char *debug;
2214 Dwarf_Addr start;
2215 Dwarf_Addr end;
2216 const char *name = dwfl_module_info (mod, NULL, &start, &end,
2217 NULL, NULL, &file, &debug);
2218 if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file)))
2219 debug = ".";
2220
2221 const unsigned char *id;
2222 GElf_Addr id_vaddr;
2223 int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
2224
2225 printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start);
2226
2227 if (id_len > 0)
2228 {
2229 do
2230 printf ("%02" PRIx8, *id++);
2231 while (--id_len > 0);
2232 if (id_vaddr != 0)
2233 printf ("@%#" PRIx64, id_vaddr);
2234 }
2235 else
2236 putchar ('-');
2237
2238 printf (" %s %s %s\n",
2239 file ?: have_elf ? "." : "-",
2240 debug ?: have_dwarf ? "." : "-",
2241 name);
2242}
2243
2244
Roland McGrath4be15242007-04-25 03:09:33 +00002245struct match_module_info
2246{
2247 char **patterns;
2248 Dwfl_Module *found;
2249 bool match_files;
2250};
2251
2252static int
2253match_module (Dwfl_Module *mod,
2254 void **userdata __attribute__ ((unused)),
2255 const char *name,
2256 Dwarf_Addr start __attribute__ ((unused)),
2257 void *arg)
2258{
2259 struct match_module_info *info = arg;
2260
2261 if (info->patterns[0] == NULL) /* Match all. */
2262 {
2263 match:
2264 info->found = mod;
2265 return DWARF_CB_ABORT;
2266 }
2267
2268 if (info->match_files)
2269 {
2270 /* Make sure we've searched for the ELF file. */
2271 GElf_Addr bias;
2272 (void) dwfl_module_getelf (mod, &bias);
2273
2274 const char *file;
2275 const char *check = dwfl_module_info (mod, NULL, NULL, NULL,
2276 NULL, NULL, &file, NULL);
2277 assert (check == name);
2278 if (file == NULL)
2279 return DWARF_CB_OK;
2280
2281 name = file;
2282 }
2283
2284 for (char **p = info->patterns; *p != NULL; ++p)
2285 if (fnmatch (*p, name, 0) == 0)
2286 goto match;
2287
2288 return DWARF_CB_OK;
2289}
2290
2291/* Handle files opened implicitly via libdwfl. */
2292static void
2293handle_implicit_modules (const struct arg_info *info)
2294{
2295 struct match_module_info mmi = { info->args, NULL, info->match_files };
2296 inline ptrdiff_t next (ptrdiff_t offset)
2297 {
2298 return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
2299 }
2300 ptrdiff_t offset = next (0);
2301 if (offset == 0)
2302 error (EXIT_FAILURE, 0, _("no matching modules found"));
2303
Roland McGrath59ea7f32007-10-04 08:50:09 +00002304 if (info->list)
2305 do
2306 list_module (mmi.found);
2307 while ((offset = next (offset)) > 0);
2308 else if (info->output_dir == NULL)
Roland McGrath4be15242007-04-25 03:09:33 +00002309 {
2310 if (next (offset) != 0)
2311 error (EXIT_FAILURE, 0, _("matched more than one module"));
Mark Wielaard22497092014-05-26 21:28:05 +02002312 handle_dwfl_module (info->output_file, false, info->force, mmi.found,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002313 info->all, info->ignore, info->relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002314 }
2315 else
2316 do
Mark Wielaard22497092014-05-26 21:28:05 +02002317 handle_output_dir_module (info->output_dir, mmi.found, info->force,
Ulrich Drepperb597dfa2007-10-16 05:21:27 +00002318 info->all, info->ignore,
2319 info->modnames, info->relocate);
Roland McGrath4be15242007-04-25 03:09:33 +00002320 while ((offset = next (offset)) > 0);
2321}
2322
2323int
2324main (int argc, char **argv)
2325{
Roland McGrath4be15242007-04-25 03:09:33 +00002326 /* We use no threads here which can interfere with handling a stream. */
2327 __fsetlocking (stdin, FSETLOCKING_BYCALLER);
2328 __fsetlocking (stdout, FSETLOCKING_BYCALLER);
2329 __fsetlocking (stderr, FSETLOCKING_BYCALLER);
2330
2331 /* Set locale. */
2332 setlocale (LC_ALL, "");
2333
2334 /* Make sure the message catalog can be found. */
Ulrich Drepperb0243862007-06-06 00:09:36 +00002335 bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
Roland McGrath4be15242007-04-25 03:09:33 +00002336
2337 /* Initialize the message catalog. */
Ulrich Drepperb0243862007-06-06 00:09:36 +00002338 textdomain (PACKAGE_TARNAME);
Roland McGrath4be15242007-04-25 03:09:33 +00002339
2340 /* Parse and process arguments. */
2341 const struct argp_child argp_children[] =
2342 {
2343 {
2344 .argp = dwfl_standard_argp (),
2345 .header = N_("Input selection options:"),
2346 .group = 1,
2347 },
2348 { .argp = NULL },
2349 };
2350 const struct argp argp =
2351 {
2352 .options = options,
2353 .parser = parse_opt,
2354 .children = argp_children,
2355 .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"),
2356 .doc = N_("\
2357Combine stripped files with separate symbols and debug information.\v\
2358The first form puts the result in DEBUG-FILE if -o was not given.\n\
2359\n\
2360MODULE arguments give file name patterns matching modules to process.\n\
2361With -f these match the file name of the main (stripped) file \
2362(slashes are never special), otherwise they match the simple module names. \
2363With no arguments, process all modules found.\n\
2364\n\
2365Multiple modules are written to files under OUTPUT-DIRECTORY, \
2366creating subdirectories as needed. \
2367With -m these files have simple module names, otherwise they have the \
Roland McGrath59ea7f32007-10-04 08:50:09 +00002368name of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\
2369\n\
2370With -n no files are written, but one line to standard output for each module:\
2371\n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\
2372START and SIZE are hexadecimal giving the address bounds of the module. \
2373BUILDID is hexadecimal for the build ID bits, or - if no ID is known; \
2374the hexadecimal may be followed by @0xADDR giving the address where the \
2375ID resides if that is known. \
2376FILE is the file name found for the module, or - if none was found, \
2377or . if an ELF image is available but not from any named file. \
2378DEBUGFILE is the separate debuginfo file name, \
2379or - if no debuginfo was found, or . if FILE contains the debug information.\
2380")
Roland McGrath4be15242007-04-25 03:09:33 +00002381 };
2382
2383 int remaining;
2384 struct arg_info info = { .args = NULL };
2385 error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info);
2386 if (result == ENOSYS)
2387 assert (info.dwfl == NULL);
2388 else if (result)
2389 return EXIT_FAILURE;
2390 assert (info.args != NULL);
2391
2392 /* Tell the library which version we are expecting. */
2393 elf_version (EV_CURRENT);
2394
2395 if (info.dwfl == NULL)
2396 {
2397 assert (result == ENOSYS);
2398
2399 if (info.output_dir != NULL)
2400 {
2401 char *file;
2402 if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0)
2403 error (EXIT_FAILURE, 0, _("memory exhausted"));
Mark Wielaard22497092014-05-26 21:28:05 +02002404 handle_explicit_files (file, true, info.force,
2405 info.args[0], info.args[1]);
Roland McGrath4be15242007-04-25 03:09:33 +00002406 free (file);
2407 }
2408 else
Mark Wielaard22497092014-05-26 21:28:05 +02002409 handle_explicit_files (info.output_file, false, info.force,
Roland McGrath9aa8ef72007-05-18 08:59:43 +00002410 info.args[0], info.args[1]);
Roland McGrath4be15242007-04-25 03:09:33 +00002411 }
2412 else
2413 {
2414 /* parse_opt checked this. */
Roland McGrath59ea7f32007-10-04 08:50:09 +00002415 assert (info.output_file != NULL || info.output_dir != NULL || info.list);
Roland McGrath4be15242007-04-25 03:09:33 +00002416
2417 handle_implicit_modules (&info);
2418
2419 dwfl_end (info.dwfl);
2420 }
2421
2422 return 0;
2423}
Ulrich Drepper3cbdd382008-01-02 17:44:39 +00002424
2425
2426#include "debugpred.h"