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