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