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