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