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