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