Branch data Line data Source code
1 : : /* Discard section not used at runtime from object files.
2 : : Copyright (C) 2000-2012, 2014, 2015, 2016, 2017, 2018 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2000.
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 : : #ifdef HAVE_CONFIG_H
20 : : # include <config.h>
21 : : #endif
22 : :
23 : : #include <argp.h>
24 : : #include <assert.h>
25 : : #include <byteswap.h>
26 : : #include <endian.h>
27 : : #include <fcntl.h>
28 : : #include <fnmatch.h>
29 : : #include <gelf.h>
30 : : #include <libelf.h>
31 : : #include <locale.h>
32 : : #include <stdbool.h>
33 : : #include <stdio.h>
34 : : #include <stdio_ext.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include <unistd.h>
38 : : #include <sys/stat.h>
39 : : #include <sys/time.h>
40 : :
41 : : #include <elf-knowledge.h>
42 : : #include <libebl.h>
43 : : #include "libdwelf.h"
44 : : #include <libeu.h>
45 : : #include <system.h>
46 : : #include <printversion.h>
47 : :
48 : : typedef uint8_t GElf_Byte;
49 : :
50 : : /* Name and version of program. */
51 : : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
52 : :
53 : : /* Bug report address. */
54 : : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
55 : :
56 : :
57 : : /* Values for the parameters which have no short form. */
58 : : #define OPT_REMOVE_COMMENT 0x100
59 : : #define OPT_PERMISSIVE 0x101
60 : : #define OPT_STRIP_SECTIONS 0x102
61 : : #define OPT_RELOC_DEBUG 0x103
62 : : #define OPT_KEEP_SECTION 0x104
63 : : #define OPT_RELOC_DEBUG_ONLY 0x105
64 : :
65 : :
66 : : /* Definitions of arguments for argp functions. */
67 : : static const struct argp_option options[] =
68 : : {
69 : : { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
70 : : { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
71 : : { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
72 : : { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
73 : :
74 : : { NULL, 0, NULL, 0, N_("Output options:"), 0 },
75 : : { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
76 : : { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
77 : : { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
78 : : { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
79 : : { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
80 : : N_("Remove section headers (not recommended)"), 0 },
81 : : { "preserve-dates", 'p', NULL, 0,
82 : : N_("Copy modified/access timestamps to the output"), 0 },
83 : : { "reloc-debug-sections", OPT_RELOC_DEBUG, NULL, 0,
84 : : N_("Resolve all trivial relocations between debug sections if the removed sections are placed in a debug file (only relevant for ET_REL files, operation is not reversible, needs -f)"), 0 },
85 : : { "reloc-debug-sections-only", OPT_RELOC_DEBUG_ONLY, NULL, 0,
86 : : N_("Similar to --reloc-debug-sections, but resolve all trivial relocations between debug sections in place. No other stripping is performed (operation is not reversible, incompatible with -f, -g, --remove-comment and --remove-section)"), 0 },
87 : : { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
88 : : N_("Remove .comment section"), 0 },
89 : : { "remove-section", 'R', "SECTION", 0, N_("Remove the named section. SECTION is an extended wildcard pattern. May be given more than once. Only non-allocated sections can be removed."), 0 },
90 : : { "keep-section", OPT_KEEP_SECTION, "SECTION", 0, N_("Keep the named section. SECTION is an extended wildcard pattern. May be given more than once."), 0 },
91 : : { "permissive", OPT_PERMISSIVE, NULL, 0,
92 : : N_("Relax a few rules to handle slightly broken ELF files"), 0 },
93 : : { NULL, 0, NULL, 0, NULL, 0 }
94 : : };
95 : :
96 : : /* Short description of program. */
97 : : static const char doc[] = N_("Discard symbols from object files.");
98 : :
99 : : /* Strings for arguments in help texts. */
100 : : static const char args_doc[] = N_("[FILE...]");
101 : :
102 : : /* Prototype for option handler. */
103 : : static error_t parse_opt (int key, char *arg, struct argp_state *state);
104 : :
105 : : /* Data structure to communicate with argp functions. */
106 : : static struct argp argp =
107 : : {
108 : : options, parse_opt, args_doc, doc, NULL, NULL, NULL
109 : : };
110 : :
111 : :
112 : : /* Print symbols in file named FNAME. */
113 : : static int process_file (const char *fname);
114 : :
115 : : /* Handle one ELF file. */
116 : : static int handle_elf (int fd, Elf *elf, const char *prefix,
117 : : const char *fname, mode_t mode, struct timespec tvp[2]);
118 : :
119 : : /* Handle all files contained in the archive. */
120 : : static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
121 : : struct timespec tvp[2]) __attribute__ ((unused));
122 : :
123 : : static int debug_fd = -1;
124 : : static char *tmp_debug_fname = NULL;
125 : :
126 : : /* Close debug file descriptor, if opened. And remove temporary debug file. */
127 : : static void cleanup_debug (void);
128 : :
129 : : #define INTERNAL_ERROR(fname) \
130 : : do { \
131 : : cleanup_debug (); \
132 : : error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"), \
133 : : fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1)); \
134 : : } while (0)
135 : :
136 : :
137 : : /* Name of the output file. */
138 : : static const char *output_fname;
139 : :
140 : : /* Name of the debug output file. */
141 : : static const char *debug_fname;
142 : :
143 : : /* Name to pretend the debug output file has. */
144 : : static const char *debug_fname_embed;
145 : :
146 : : /* If true output files shall have same date as the input file. */
147 : : static bool preserve_dates;
148 : :
149 : : /* If true .comment sections will be removed. */
150 : : static bool remove_comment;
151 : :
152 : : /* If true remove all debug sections. */
153 : : static bool remove_debug;
154 : :
155 : : /* If true remove all section headers. */
156 : : static bool remove_shdrs;
157 : :
158 : : /* If true relax some ELF rules for input files. */
159 : : static bool permissive;
160 : :
161 : : /* If true perform relocations between debug sections. */
162 : : static bool reloc_debug;
163 : :
164 : : /* If true perform relocations between debug sections only. */
165 : : static bool reloc_debug_only;
166 : :
167 : : /* Sections the user explicitly wants to keep or remove. */
168 : : struct section_pattern
169 : : {
170 : : char *pattern;
171 : : struct section_pattern *next;
172 : : };
173 : :
174 : : static struct section_pattern *keep_secs = NULL;
175 : : static struct section_pattern *remove_secs = NULL;
176 : :
177 : : static void
178 : 10 : add_pattern (struct section_pattern **patterns, const char *pattern)
179 : : {
180 : 10 : struct section_pattern *p = xmalloc (sizeof *p);
181 : 10 : p->pattern = xstrdup (pattern);
182 : 10 : p->next = *patterns;
183 : 10 : *patterns = p;
184 : 10 : }
185 : :
186 : : static void
187 : 250 : free_sec_patterns (struct section_pattern *patterns)
188 : : {
189 : 250 : struct section_pattern *pattern = patterns;
190 [ + + ]: 260 : while (pattern != NULL)
191 : : {
192 : 10 : struct section_pattern *p = pattern;
193 : 10 : pattern = p->next;
194 : 10 : free (p->pattern);
195 : 10 : free (p);
196 : : }
197 : 250 : }
198 : :
199 : : static void
200 : 125 : free_patterns (void)
201 : : {
202 : 125 : free_sec_patterns (keep_secs);
203 : 125 : free_sec_patterns (remove_secs);
204 : 125 : }
205 : :
206 : : static bool
207 : 400123 : section_name_matches (struct section_pattern *patterns, const char *name)
208 : : {
209 : 400123 : struct section_pattern *pattern = patterns;
210 [ + + ]: 400374 : while (pattern != NULL)
211 : : {
212 [ + + ]: 269 : if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
213 : : return true;
214 : 251 : pattern = pattern->next;
215 : : }
216 : : return false;
217 : : }
218 : :
219 : :
220 : : int
221 : 125 : main (int argc, char *argv[])
222 : : {
223 : 125 : int remaining;
224 : 125 : int result = 0;
225 : :
226 : : /* We use no threads here which can interfere with handling a stream. */
227 : 125 : __fsetlocking (stdin, FSETLOCKING_BYCALLER);
228 : 125 : __fsetlocking (stdout, FSETLOCKING_BYCALLER);
229 : 125 : __fsetlocking (stderr, FSETLOCKING_BYCALLER);
230 : :
231 : : /* Set locale. */
232 : 125 : setlocale (LC_ALL, "");
233 : :
234 : : /* Make sure the message catalog can be found. */
235 : 125 : bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
236 : :
237 : : /* Initialize the message catalog. */
238 : 125 : textdomain (PACKAGE_TARNAME);
239 : :
240 : : /* Parse and process arguments. */
241 [ + - ]: 125 : if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
242 : : return EXIT_FAILURE;
243 : :
244 [ + + - + ]: 125 : if (reloc_debug && debug_fname == NULL)
245 : 0 : error_exit (0, _("--reloc-debug-sections used without -f"));
246 : :
247 [ + + ]: 125 : if (reloc_debug_only &&
248 [ + - + - ]: 16 : (debug_fname != NULL || remove_secs != NULL
249 [ + - - + ]: 16 : || remove_comment == true || remove_debug == true))
250 : 0 : error_exit (0,
251 : : _("--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --remove-section"));
252 : :
253 : : /* Tell the library which version we are expecting. */
254 : 125 : elf_version (EV_CURRENT);
255 : :
256 [ + + ]: 125 : if (remaining == argc)
257 : : /* The user didn't specify a name so we use a.out. */
258 : 5 : result = process_file ("a.out");
259 : : else
260 : : {
261 : : /* If we have seen the '-o' or '-f' option there must be exactly one
262 : : input file. */
263 [ + + + + ]: 120 : if ((output_fname != NULL || debug_fname != NULL)
264 [ - + ]: 90 : && remaining + 1 < argc)
265 : 0 : error_exit (0, _("Only one input file allowed together with '-o' and '-f'"));
266 : :
267 : : /* Process all the remaining files. */
268 : 120 : do
269 : 120 : result |= process_file (argv[remaining]);
270 [ - + ]: 120 : while (++remaining < argc);
271 : : }
272 : :
273 : 125 : free_patterns ();
274 : 125 : return result;
275 : : }
276 : :
277 : :
278 : : /* Handle program arguments. */
279 : : static error_t
280 : 864 : parse_opt (int key, char *arg, struct argp_state *state)
281 : : {
282 [ + + - + : 864 : switch (key)
- + + + +
+ + - - +
+ ]
283 : : {
284 : 72 : case 'f':
285 [ - + ]: 72 : if (debug_fname != NULL)
286 : : {
287 : 0 : error (0, 0, _("-f option specified twice"));
288 : 0 : return EINVAL;
289 : : }
290 : 72 : debug_fname = arg;
291 : 72 : break;
292 : :
293 : 6 : case 'F':
294 [ - + ]: 6 : if (debug_fname_embed != NULL)
295 : : {
296 : 0 : error (0, 0, _("-F option specified twice"));
297 : 0 : return EINVAL;
298 : : }
299 : 6 : debug_fname_embed = arg;
300 : 6 : break;
301 : :
302 : 82 : case 'o':
303 [ - + ]: 82 : if (output_fname != NULL)
304 : : {
305 : 0 : error (0, 0, _("-o option specified twice"));
306 : 0 : return EINVAL;
307 : : }
308 : 82 : output_fname = arg;
309 : 82 : break;
310 : :
311 : 0 : case 'p':
312 : 0 : preserve_dates = true;
313 : 0 : break;
314 : :
315 : 16 : case OPT_RELOC_DEBUG:
316 : 16 : reloc_debug = true;
317 : 16 : break;
318 : :
319 : 16 : case OPT_RELOC_DEBUG_ONLY:
320 : 16 : reloc_debug_only = true;
321 : 16 : break;
322 : :
323 : 1 : case OPT_REMOVE_COMMENT:
324 : 1 : remove_comment = true;
325 : 1 : break;
326 : :
327 : 4 : case 'R':
328 [ - + ]: 4 : if (fnmatch (arg, ".comment", FNM_EXTMATCH) == 0)
329 : 0 : remove_comment = true;
330 : 4 : add_pattern (&remove_secs, arg);
331 : 4 : break;
332 : :
333 : 6 : case OPT_KEEP_SECTION:
334 : 6 : add_pattern (&keep_secs, arg);
335 : 6 : break;
336 : :
337 : 36 : case 'g':
338 : : case 'd':
339 : : case 'S':
340 : 36 : remove_debug = true;
341 : 36 : break;
342 : :
343 : 0 : case OPT_STRIP_SECTIONS:
344 : 0 : remove_shdrs = true;
345 : 0 : break;
346 : :
347 : 0 : case OPT_PERMISSIVE:
348 : 0 : permissive = true;
349 : 0 : break;
350 : :
351 : : case 's': /* Ignored for compatibility. */
352 : : break;
353 : :
354 : 125 : case ARGP_KEY_SUCCESS:
355 [ + + ]: 125 : if (remove_comment == true
356 [ + - ]: 1 : && section_name_matches (keep_secs, ".comment"))
357 : : {
358 : 0 : argp_error (state,
359 : 0 : _("cannot both keep and remove .comment section"));
360 : 0 : return EINVAL;
361 : : }
362 : : break;
363 : :
364 : : default:
365 : : return ARGP_ERR_UNKNOWN;
366 : : }
367 : : return 0;
368 : : }
369 : :
370 : : static const char *
371 : 68484 : secndx_name (Elf *elf, size_t ndx)
372 : : {
373 : 68484 : size_t shstrndx;
374 : 68484 : GElf_Shdr mem;
375 : 68484 : Elf_Scn *sec = elf_getscn (elf, ndx);
376 : 68484 : GElf_Shdr *shdr = gelf_getshdr (sec, &mem);
377 [ + - - + ]: 68484 : if (shdr == NULL || elf_getshdrstrndx (elf, &shstrndx) < 0)
378 : 0 : return "???";
379 [ - + ]: 68484 : return elf_strptr (elf, shstrndx, shdr->sh_name) ?: "???";
380 : : }
381 : :
382 : : /* Get the extended section index table data for a symbol table section. */
383 : : static Elf_Data *
384 : 140 : get_xndxdata (Elf *elf, Elf_Scn *symscn)
385 : : {
386 : 140 : Elf_Data *xndxdata = NULL;
387 : 140 : GElf_Shdr shdr_mem;
388 : 140 : GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
389 [ - + - + ]: 140 : if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
390 : : {
391 : 140 : size_t scnndx = elf_ndxscn (symscn);
392 : 140 : Elf_Scn *xndxscn = NULL;
393 [ + + ]: 4622 : while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
394 : : {
395 : 4482 : GElf_Shdr xndxshdr_mem;
396 : 4482 : GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
397 : :
398 [ + - ]: 4482 : if (xndxshdr != NULL
399 [ - + ]: 4482 : && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
400 [ # # ]: 0 : && xndxshdr->sh_link == scnndx)
401 : : {
402 : 0 : xndxdata = elf_getdata (xndxscn, NULL);
403 : 0 : break;
404 : : }
405 : : }
406 : : }
407 : :
408 : 140 : return xndxdata;
409 : : }
410 : :
411 : : /* Updates the shdrstrndx for the given Elf by updating the Ehdr and
412 : : possibly the section zero extension field. Returns zero on success. */
413 : : static int
414 : 211 : update_shdrstrndx (Elf *elf, size_t shdrstrndx)
415 : : {
416 : 211 : GElf_Ehdr ehdr;
417 [ - + ]: 211 : if (gelf_getehdr (elf, &ehdr) == 0)
418 : : return 1;
419 : :
420 [ + + ]: 211 : if (shdrstrndx < SHN_LORESERVE)
421 : 208 : ehdr.e_shstrndx = shdrstrndx;
422 : : else
423 : : {
424 : 3 : ehdr.e_shstrndx = SHN_XINDEX;
425 : 3 : Elf_Scn *scn0 = elf_getscn (elf, 0);
426 : 3 : GElf_Shdr shdr0_mem;
427 : 3 : GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem);
428 [ + - ]: 3 : if (shdr0 == NULL)
429 : 0 : return 1;
430 : :
431 : 3 : shdr0->sh_link = shdrstrndx;
432 [ + - ]: 3 : if (gelf_update_shdr (scn0, shdr0) == 0)
433 : : return 1;
434 : : }
435 : :
436 [ - + ]: 211 : if (unlikely (gelf_update_ehdr (elf, &ehdr) == 0))
437 : : return 1;
438 : :
439 : : return 0;
440 : : }
441 : :
442 : :
443 : : /* Apply one relocation. Returns true when trivial
444 : : relocation actually done. */
445 : : static bool
446 : 57896 : relocate (Elf *elf, GElf_Addr offset, const GElf_Sxword addend,
447 : : Elf_Data *tdata, unsigned int ei_data, const char *fname,
448 : : bool is_rela, GElf_Sym *sym, int addsub, Elf_Type type)
449 : : {
450 : : /* These are the types we can relocate. */
451 : : #define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
452 : : DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
453 : : DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
454 : :
455 : 57896 : size_t size;
456 : :
457 : : #define DO_TYPE(NAME, Name) GElf_##Name Name;
458 : 57896 : union { TYPES; } tmpbuf;
459 : : #undef DO_TYPE
460 : :
461 [ - - + + : 57896 : switch (type)
- - - ]
462 : : {
463 : : #define DO_TYPE(NAME, Name) \
464 : : case ELF_T_##NAME: \
465 : : size = sizeof (GElf_##Name); \
466 : : tmpbuf.Name = 0; \
467 : : break;
468 : 57896 : TYPES;
469 : : #undef DO_TYPE
470 : : default:
471 : : return false;
472 : : }
473 : :
474 [ + - ]: 57896 : if (offset > tdata->d_size
475 [ - + ]: 57896 : || tdata->d_size - offset < size)
476 : : {
477 : 0 : cleanup_debug ();
478 : 0 : error_exit (0, _("bad relocation"));
479 : : }
480 : :
481 : : /* When the symbol value is zero then for SHT_REL
482 : : sections this is all that needs to be checked.
483 : : The addend is contained in the original data at
484 : : the offset already. So if the (section) symbol
485 : : address is zero and the given addend is zero
486 : : just remove the relocation, it isn't needed
487 : : anymore. */
488 [ + + + + ]: 57896 : if (addend == 0 && sym->st_value == 0)
489 : : return true;
490 : :
491 : 51336 : Elf_Data tmpdata =
492 : : {
493 : : .d_type = type,
494 : : .d_buf = &tmpbuf,
495 : : .d_size = size,
496 : : .d_version = EV_CURRENT,
497 : : };
498 : 51336 : Elf_Data rdata =
499 : : {
500 : : .d_type = type,
501 : 51336 : .d_buf = tdata->d_buf + offset,
502 : : .d_size = size,
503 : : .d_version = EV_CURRENT,
504 : : };
505 : :
506 : 51336 : GElf_Addr value = sym->st_value;
507 [ + - ]: 51336 : if (is_rela)
508 : : {
509 : : /* For SHT_RELA sections we just take the
510 : : given addend and add it to the value. */
511 : 51336 : value += addend;
512 : : /* For ADD/SUB relocations we need to fetch the
513 : : current section contents. */
514 [ - + ]: 51336 : if (addsub != 0)
515 : : {
516 : 0 : Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
517 : : &rdata,
518 : : ei_data);
519 [ # # ]: 0 : if (d == NULL)
520 : 0 : INTERNAL_ERROR (fname);
521 [ # # ]: 0 : assert (d == &tmpdata);
522 : : }
523 : : }
524 : : else
525 : : {
526 : : /* For SHT_REL sections we have to peek at
527 : : what is already in the section at the given
528 : : offset to get the addend. */
529 : 0 : Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
530 : : &rdata,
531 : : ei_data);
532 [ # # ]: 0 : if (d == NULL)
533 : 0 : INTERNAL_ERROR (fname);
534 [ # # ]: 0 : assert (d == &tmpdata);
535 : : }
536 : :
537 [ - - + + : 51336 : switch (type)
- - - ]
538 : : {
539 : : #define DO_TYPE(NAME, Name) \
540 : : case ELF_T_##NAME: \
541 : : if (addsub < 0) \
542 : : tmpbuf.Name -= (GElf_##Name) value; \
543 : : else \
544 : : tmpbuf.Name += (GElf_##Name) value; \
545 : : break;
546 [ - - - - : 51336 : TYPES;
- + - + -
- - - ]
547 : : #undef DO_TYPE
548 : 0 : default:
549 : 0 : abort ();
550 : : }
551 : :
552 : : /* Now finally put in the new value. */
553 : 51336 : Elf_Data *s = gelf_xlatetof (elf, &rdata,
554 : : &tmpdata,
555 : : ei_data);
556 [ - + ]: 51336 : if (s == NULL)
557 : 0 : INTERNAL_ERROR (fname);
558 [ - + ]: 51336 : assert (s == &rdata);
559 : :
560 : : return true;
561 : : }
562 : :
563 : : /* Remove any relocations between debug sections in ET_REL
564 : : for the debug file when requested. These relocations are always
565 : : zero based between the unallocated sections. */
566 : : static void
567 : 31 : remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
568 : : const char *fname, size_t shstrndx)
569 : : {
570 : 31 : Elf_Scn *scn = NULL;
571 [ + + ]: 1006 : while ((scn = elf_nextscn (elf, scn)) != NULL)
572 : : {
573 : : /* We need the actual section and header from the elf
574 : : not just the cached original in shdr_info because we
575 : : might want to change the size. */
576 : 975 : GElf_Shdr shdr_mem;
577 : 975 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
578 [ + - ]: 975 : if (shdr != NULL
579 [ + + ]: 975 : && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
580 : : {
581 : : /* Make sure that this relocation section points to a
582 : : section to relocate with contents, that isn't
583 : : allocated and that is a debug section. */
584 : 140 : Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
585 : 140 : GElf_Shdr tshdr_mem;
586 : 140 : GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
587 [ + - ]: 140 : if (tshdr == NULL
588 [ + - ]: 140 : || tshdr->sh_type == SHT_NOBITS
589 [ + - ]: 140 : || tshdr->sh_size == 0
590 [ - + ]: 140 : || (tshdr->sh_flags & SHF_ALLOC) != 0)
591 : 0 : continue;
592 : :
593 : 280 : const char *tname = elf_strptr (elf, shstrndx,
594 : 140 : tshdr->sh_name);
595 [ + - - + ]: 140 : if (! tname || ! ebl_debugscn_p (ebl, tname))
596 : 0 : continue;
597 : :
598 : : /* OK, lets relocate all trivial cross debug section
599 : : relocations. */
600 : 140 : Elf_Data *reldata = elf_getdata (scn, NULL);
601 [ + - - + ]: 140 : if (reldata == NULL || reldata->d_buf == NULL)
602 : 0 : INTERNAL_ERROR (fname);
603 : :
604 : : /* Make sure we adjust the uncompressed debug data
605 : : (and recompress if necessary at the end). */
606 : 140 : GElf_Chdr tchdr;
607 : 140 : int tcompress_type = 0;
608 : 140 : bool is_gnu_compressed = false;
609 [ + + ]: 140 : if (startswith (tname, ".zdebug"))
610 : : {
611 : 4 : is_gnu_compressed = true;
612 [ - + ]: 4 : if (elf_compress_gnu (tscn, 0, 0) != 1)
613 : 0 : INTERNAL_ERROR (fname);
614 : : }
615 : : else
616 : : {
617 [ + + ]: 136 : if (gelf_getchdr (tscn, &tchdr) != NULL)
618 : : {
619 : 14 : tcompress_type = tchdr.ch_type;
620 [ - + ]: 14 : if (elf_compress (tscn, 0, 0) != 1)
621 : 0 : INTERNAL_ERROR (fname);
622 : : }
623 : : }
624 : :
625 : 140 : Elf_Data *tdata = elf_getdata (tscn, NULL);
626 [ + - + - ]: 140 : if (tdata == NULL || tdata->d_buf == NULL
627 [ - + ]: 140 : || tdata->d_type != ELF_T_BYTE)
628 : 0 : INTERNAL_ERROR (fname);
629 : :
630 : : /* Pick up the symbol table and shndx table to
631 : : resolve relocation symbol indexes. */
632 : 140 : Elf64_Word symt = shdr->sh_link;
633 : 140 : Elf_Data *symdata, *xndxdata;
634 : 140 : Elf_Scn * symscn = elf_getscn (elf, symt);
635 : 140 : symdata = elf_getdata (symscn, NULL);
636 : 140 : xndxdata = get_xndxdata (elf, symscn);
637 [ - + ]: 140 : if (symdata == NULL)
638 : 0 : INTERNAL_ERROR (fname);
639 : :
640 [ - + ]: 140 : if (shdr->sh_entsize == 0)
641 : 0 : INTERNAL_ERROR (fname);
642 : :
643 : 140 : size_t nrels = shdr->sh_size / shdr->sh_entsize;
644 : 140 : size_t next = 0;
645 : 140 : const bool is_rela = (shdr->sh_type == SHT_RELA);
646 : 140 : const unsigned int ei_data = ehdr->e_ident[EI_DATA];
647 : :
648 [ + + ]: 68632 : for (size_t relidx = 0; relidx < nrels; ++relidx)
649 : 57896 : {
650 : 68492 : int rtype, symndx, offset, addend;
651 : 68492 : union { GElf_Rela rela; GElf_Rel rel; } mem;
652 : 68492 : void *rel_p; /* Pointer to either rela or rel above */
653 : :
654 [ + + ]: 68492 : if (is_rela)
655 : : {
656 : 62068 : GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
657 [ - + ]: 62068 : if (r == NULL)
658 : 0 : INTERNAL_ERROR (fname);
659 : 62068 : offset = r->r_offset;
660 : 62068 : addend = r->r_addend;
661 : 62068 : rtype = GELF_R_TYPE (r->r_info);
662 : 62068 : symndx = GELF_R_SYM (r->r_info);
663 : 62068 : rel_p = r;
664 : : }
665 : : else
666 : : {
667 : 6424 : GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
668 [ - + ]: 6424 : if (r == NULL)
669 : 0 : INTERNAL_ERROR (fname);
670 : 6424 : offset = r->r_offset;
671 : 6424 : addend = 0;
672 : 6424 : rtype = GELF_R_TYPE (r->r_info);
673 : 6424 : symndx = GELF_R_SYM (r->r_info);
674 : 6424 : rel_p = r;
675 : : }
676 : :
677 : : /* R_*_NONE relocs can always just be removed. */
678 [ - + ]: 68492 : if (rtype == 0)
679 : 57896 : continue;
680 : :
681 : : /* We only do simple absolute relocations. */
682 : 68492 : int addsub = 0;
683 : 68492 : Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
684 [ + + ]: 68492 : if (type == ELF_T_NUM)
685 : 8 : goto relocate_failed;
686 : :
687 : : /* And only for relocations against other debug sections. */
688 : 68484 : GElf_Sym sym_mem;
689 : 68484 : Elf32_Word xndx;
690 : 68484 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
691 : : symndx, &sym_mem,
692 : : &xndx);
693 [ - + ]: 68484 : if (sym == NULL)
694 : 0 : INTERNAL_ERROR (fname);
695 : 136968 : Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
696 [ + - ]: 68484 : ? xndx : sym->st_shndx);
697 : :
698 : 68484 : bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
699 : :
700 [ + + ]: 68484 : if (!dbg_scn)
701 : 10588 : goto relocate_failed;
702 : :
703 [ - + ]: 57896 : if (! relocate (elf, offset, addend,
704 : : tdata, ei_data, fname, is_rela,
705 : : sym, addsub, type))
706 : 0 : goto relocate_failed;
707 : :
708 : 57896 : continue; /* Next */
709 : :
710 : 10596 : relocate_failed:
711 [ + + ]: 10596 : if (relidx != next)
712 : : {
713 : 7644 : int updated;
714 [ + + ]: 7644 : if (is_rela)
715 : 7612 : updated = gelf_update_rela (reldata, next, rel_p);
716 : : else
717 : 32 : updated = gelf_update_rel (reldata, next, rel_p);
718 [ - + ]: 7644 : if (updated == 0)
719 : 0 : INTERNAL_ERROR (fname);
720 : : }
721 : 10596 : ++next;
722 : : }
723 : :
724 : 140 : nrels = next;
725 : 140 : shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
726 [ - + ]: 140 : if (gelf_update_shdr (scn, shdr) == 0)
727 : 0 : INTERNAL_ERROR (fname);
728 : :
729 [ + + ]: 140 : if (is_gnu_compressed)
730 : : {
731 [ - + ]: 4 : if (elf_compress_gnu (tscn, 1, ELF_CHF_FORCE) != 1)
732 : 0 : INTERNAL_ERROR (fname);
733 : : }
734 [ + + ]: 136 : else if (tcompress_type != 0)
735 : : {
736 [ - + ]: 14 : if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
737 : 140 : INTERNAL_ERROR (fname);
738 : : }
739 : : }
740 : : }
741 : 31 : }
742 : :
743 : : static int
744 : 125 : process_file (const char *fname)
745 : : {
746 : : /* If we have to preserve the modify and access timestamps get them
747 : : now. We cannot use fstat() after opening the file since the open
748 : : would change the access time. */
749 : 125 : struct stat pre_st;
750 : 125 : struct timespec tv[2];
751 : 125 : again:
752 [ - + ]: 125 : if (preserve_dates)
753 : : {
754 [ # # ]: 0 : if (stat (fname, &pre_st) != 0)
755 : : {
756 : 0 : error (0, errno, _("cannot stat input file '%s'"), fname);
757 : 0 : return 1;
758 : : }
759 : :
760 : : /* If we have to preserve the timestamp, we need it in the
761 : : format utimes() understands. */
762 : 0 : tv[0] = pre_st.st_atim;
763 : 0 : tv[1] = pre_st.st_mtim;
764 : : }
765 : :
766 : : /* Open the file. */
767 [ + + ]: 125 : int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
768 [ - + ]: 125 : if (fd == -1)
769 : : {
770 : 0 : error (0, errno, _("while opening '%s'"), fname);
771 : 0 : return 1;
772 : : }
773 : :
774 : : /* We always use fstat() even if we called stat() before. This is
775 : : done to make sure the information returned by stat() is for the
776 : : same file. */
777 : 125 : struct stat st;
778 [ - + ]: 125 : if (fstat (fd, &st) != 0)
779 : : {
780 : 0 : error (0, errno, _("cannot stat input file '%s'"), fname);
781 : 0 : return 1;
782 : : }
783 : : /* Paranoid mode on. */
784 [ - + ]: 125 : if (preserve_dates
785 [ # # # # ]: 0 : && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
786 : : {
787 : : /* We detected a race. Try again. */
788 : 0 : close (fd);
789 : 0 : goto again;
790 : : }
791 : :
792 : : /* Now get the ELF descriptor. */
793 [ + + ]: 207 : Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
794 : : NULL);
795 : 125 : int result;
796 [ + - - ]: 125 : switch (elf_kind (elf))
797 : : {
798 : 125 : case ELF_K_ELF:
799 : 250 : result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
800 [ + - ]: 125 : preserve_dates ? tv : NULL);
801 : 125 : break;
802 : :
803 : 0 : case ELF_K_AR:
804 : : /* It is not possible to strip the content of an archive direct
805 : : the output to a specific file. */
806 [ # # # # ]: 0 : if (unlikely (output_fname != NULL || debug_fname != NULL))
807 : : {
808 : 0 : error (0, 0, _("%s: cannot use -o or -f when stripping archive"),
809 : : fname);
810 : 0 : result = 1;
811 : : }
812 : : else
813 : : {
814 : : /* We would like to support ar archives, but currently it just
815 : : doesn't work at all since we call elf_clone on the members
816 : : which doesn't really support ar members.
817 : : result = handle_ar (fd, elf, NULL, fname,
818 : : preserve_dates ? tv : NULL);
819 : : */
820 : 0 : error (0, 0, _("%s: no support for stripping archive"),
821 : : fname);
822 : 0 : result = 1;
823 : : }
824 : : break;
825 : :
826 : 0 : default:
827 : 0 : error (0, 0, _("%s: File format not recognized"), fname);
828 : 0 : result = 1;
829 : 0 : break;
830 : : }
831 : :
832 [ - + ]: 125 : if (unlikely (elf_end (elf) != 0))
833 : 0 : INTERNAL_ERROR (fname);
834 : :
835 : 125 : close (fd);
836 : :
837 : 125 : return result;
838 : : }
839 : :
840 : : /* Processing for --reloc-debug-sections-only. */
841 : : static int
842 : 16 : handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
843 : : GElf_Ehdr *ehdr, const char *fname, size_t shstrndx,
844 : : GElf_Off *last_offset, GElf_Xword *last_size)
845 : : {
846 : :
847 : : /* Copy over the ELF header. */
848 [ - + ]: 16 : if (gelf_update_ehdr (new_elf, ehdr) == 0)
849 : : {
850 : 0 : error (0, 0, "couldn't update new ehdr: %s", elf_errmsg (-1));
851 : 0 : return 1;
852 : : }
853 : :
854 : : /* Copy over sections and record end of allocated sections. */
855 : : GElf_Off lastoffset = 0;
856 : : Elf_Scn *scn = NULL;
857 [ + + ]: 524 : while ((scn = elf_nextscn (elf, scn)) != NULL)
858 : : {
859 : : /* Get the header. */
860 : 508 : GElf_Shdr shdr;
861 [ - + ]: 508 : if (gelf_getshdr (scn, &shdr) == NULL)
862 : : {
863 : 0 : error (0, 0, "couldn't get shdr: %s", elf_errmsg (-1));
864 : 0 : return 1;
865 : : }
866 : :
867 : : /* Create new section. */
868 : 508 : Elf_Scn *new_scn = elf_newscn (new_elf);
869 [ - + ]: 508 : if (new_scn == NULL)
870 : : {
871 : 0 : error (0, 0, "couldn't create new section: %s", elf_errmsg (-1));
872 : 0 : return 1;
873 : : }
874 : :
875 [ - + ]: 508 : if (gelf_update_shdr (new_scn, &shdr) == 0)
876 : : {
877 : 0 : error (0, 0, "couldn't update shdr: %s", elf_errmsg (-1));
878 : 0 : return 1;
879 : : }
880 : :
881 : : /* Copy over section data. */
882 : : Elf_Data *data = NULL;
883 [ + + ]: 1016 : while ((data = elf_getdata (scn, data)) != NULL)
884 : : {
885 : 508 : Elf_Data *new_data = elf_newdata (new_scn);
886 [ - + ]: 508 : if (new_data == NULL)
887 : : {
888 : 0 : error (0, 0, "couldn't create new section data: %s",
889 : : elf_errmsg (-1));
890 : 0 : return 1;
891 : : }
892 : 508 : *new_data = *data;
893 : : }
894 : :
895 : : /* Record last offset of allocated section. */
896 [ + + ]: 508 : if ((shdr.sh_flags & SHF_ALLOC) != 0)
897 : : {
898 : 358 : GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
899 [ + + ]: 179 : ? shdr.sh_size : 0);
900 : 179 : if (lastoffset < shdr.sh_offset + filesz)
901 : 508 : lastoffset = shdr.sh_offset + filesz;
902 : : }
903 : : }
904 : :
905 : : /* Make sure section header name table is setup correctly, we'll
906 : : need it to determine whether to relocate sections. */
907 [ - + ]: 16 : if (update_shdrstrndx (new_elf, shstrndx) != 0)
908 : : {
909 : 0 : error (0, 0, "error updating shdrstrndx: %s", elf_errmsg (-1));
910 : 0 : return 1;
911 : : }
912 : :
913 : : /* Adjust the relocation sections. */
914 : 16 : remove_debug_relocations (ebl, new_elf, ehdr, fname, shstrndx);
915 : :
916 : : /* Adjust the offsets of the non-allocated sections, so they come after
917 : : the allocated sections. */
918 : 16 : scn = NULL;
919 [ + + ]: 524 : while ((scn = elf_nextscn (new_elf, scn)) != NULL)
920 : : {
921 : : /* Get the header. */
922 : 508 : GElf_Shdr shdr;
923 [ - + ]: 508 : if (gelf_getshdr (scn, &shdr) == NULL)
924 : : {
925 : 0 : error (0, 0, "couldn't get shdr: %s", elf_errmsg (-1));
926 : 0 : return 1;
927 : : }
928 : :
929 : : /* Adjust non-allocated section offsets to be after any allocated. */
930 [ + + ]: 508 : if ((shdr.sh_flags & SHF_ALLOC) == 0)
931 : : {
932 : 329 : shdr.sh_offset = ((lastoffset + shdr.sh_addralign - 1)
933 : 329 : & ~((GElf_Off) (shdr.sh_addralign - 1)));
934 [ - + ]: 329 : if (gelf_update_shdr (scn, &shdr) == 0)
935 : : {
936 : 0 : error (0, 0, "couldn't update shdr: %s", elf_errmsg (-1));
937 : 0 : return 1;
938 : : }
939 : :
940 : 658 : GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
941 [ + + ]: 329 : ? shdr.sh_size : 0);
942 : 329 : lastoffset = shdr.sh_offset + filesz;
943 : 329 : *last_offset = shdr.sh_offset;
944 : 329 : *last_size = filesz;
945 : : }
946 : : }
947 : :
948 : : return 0;
949 : : }
950 : :
951 : : /* Update section headers when the data size has changed.
952 : : We also update the SHT_NOBITS section in the debug
953 : : file so that the section headers match in sh_size. */
954 : : static inline void
955 : 12 : update_section_size (Elf_Scn *scn,
956 : : const Elf_Data *newdata,
957 : : Elf *debugelf,
958 : : size_t cnt,
959 : : const char *fname)
960 : : {
961 : 12 : GElf_Shdr shdr_mem;
962 : 12 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
963 : 12 : shdr->sh_size = newdata->d_size;
964 [ - + ]: 12 : if (gelf_update_shdr (scn, shdr) == 0)
965 : 0 : INTERNAL_ERROR (fname);
966 [ + + ]: 12 : if (debugelf != NULL)
967 : : {
968 : : /* libelf will use d_size to set sh_size. */
969 : 2 : Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
970 : : cnt), NULL);
971 [ - + ]: 2 : if (debugdata == NULL)
972 : 0 : INTERNAL_ERROR (fname);
973 : 2 : debugdata->d_size = newdata->d_size;
974 : : }
975 : 12 : }
976 : :
977 : : /* Maximum size of array allocated on stack. */
978 : : #define MAX_STACK_ALLOC (400 * 1024)
979 : :
980 : : static int
981 : 125 : handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
982 : : mode_t mode, struct timespec tvp[2])
983 : : {
984 [ - + ]: 125 : size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
985 : 125 : size_t fname_len = strlen (fname) + 1;
986 : 125 : char *fullname = alloca (prefix_len + 1 + fname_len);
987 : 125 : char *cp = fullname;
988 : 125 : Elf *debugelf = NULL;
989 : 125 : tmp_debug_fname = NULL;
990 : 125 : int result = 0;
991 : 125 : size_t shdridx = 0;
992 : 125 : GElf_Off lastsec_offset = 0;
993 : 125 : Elf64_Xword lastsec_size = 0;
994 : 125 : size_t shstrndx;
995 : 125 : struct shdr_info
996 : : {
997 : : Elf_Scn *scn;
998 : : GElf_Shdr shdr;
999 : : Elf_Data *data;
1000 : : Elf_Data *debug_data;
1001 : : const char *name;
1002 : : Elf32_Word idx; /* Index in new file. */
1003 : : Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
1004 : : Elf32_Word symtab_idx;
1005 : : Elf32_Word version_idx;
1006 : : Elf32_Word group_idx;
1007 : : Elf32_Word group_cnt;
1008 : : Elf_Scn *newscn;
1009 : : Dwelf_Strent *se;
1010 : : Elf32_Word *newsymidx;
1011 : 125 : } *shdr_info = NULL;
1012 : 125 : Elf_Scn *scn;
1013 : 125 : size_t cnt;
1014 : 125 : size_t idx;
1015 : 125 : bool changes;
1016 : 125 : GElf_Ehdr newehdr_mem;
1017 : 125 : GElf_Ehdr *newehdr;
1018 : 125 : GElf_Ehdr debugehdr_mem;
1019 : 125 : GElf_Ehdr *debugehdr;
1020 : 125 : Dwelf_Strtab *shst = NULL;
1021 : 125 : Elf_Data debuglink_crc_data;
1022 : 125 : bool any_symtab_changes = false;
1023 : 125 : Elf_Data *shstrtab_data = NULL;
1024 : 125 : void *debuglink_buf = NULL;
1025 : :
1026 : : /* Create the full name of the file. */
1027 [ - + ]: 125 : if (prefix != NULL)
1028 : : {
1029 : 0 : cp = mempcpy (cp, prefix, prefix_len);
1030 : 0 : *cp++ = ':';
1031 : : }
1032 [ + + ]: 125 : memcpy (cp, fname, fname_len);
1033 : :
1034 : : /* If we are not replacing the input file open a new file here. */
1035 [ + + ]: 125 : if (output_fname != NULL)
1036 : : {
1037 : 82 : fd = open (output_fname, O_RDWR | O_CREAT, mode);
1038 [ - + ]: 82 : if (unlikely (fd == -1))
1039 : : {
1040 : 0 : error (0, errno, _("cannot open '%s'"), output_fname);
1041 : 0 : return 1;
1042 : : }
1043 : : }
1044 : :
1045 : 125 : debug_fd = -1;
1046 : :
1047 : : /* Get the EBL handling. Removing all debugging symbols with the -g
1048 : : option or resolving all relocations between debug sections with
1049 : : the --reloc-debug-sections option are currently the only reasons
1050 : : we need EBL so don't open the backend unless necessary. */
1051 : 125 : Ebl *ebl = NULL;
1052 [ + + + + : 125 : if (remove_debug || reloc_debug || reloc_debug_only)
+ + ]
1053 : : {
1054 : 68 : ebl = ebl_openbackend (elf);
1055 [ - + ]: 68 : if (ebl == NULL)
1056 : : {
1057 : 0 : error (0, errno, _("cannot open EBL backend"));
1058 : 0 : result = 1;
1059 : 0 : goto fail;
1060 : : }
1061 : : }
1062 : :
1063 : : /* Open the additional file the debug information will be stored in. */
1064 [ + + ]: 125 : if (debug_fname != NULL)
1065 : : {
1066 : : /* Create a temporary file name. We do not want to overwrite
1067 : : the debug file if the file would not contain any
1068 : : information. */
1069 : 72 : size_t debug_fname_len = strlen (debug_fname);
1070 : 72 : tmp_debug_fname = xmalloc (debug_fname_len + sizeof (".XXXXXX"));
1071 : 72 : strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
1072 : : ".XXXXXX");
1073 : :
1074 : 72 : debug_fd = mkstemp (tmp_debug_fname);
1075 [ - + ]: 72 : if (unlikely (debug_fd == -1))
1076 : : {
1077 : 0 : error (0, errno, _("cannot open '%s'"), debug_fname);
1078 : 0 : result = 1;
1079 : 0 : goto fail;
1080 : : }
1081 : : }
1082 : :
1083 : : /* Get the information from the old file. */
1084 : 125 : GElf_Ehdr ehdr_mem;
1085 : 125 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
1086 [ - + ]: 125 : if (ehdr == NULL)
1087 : 0 : INTERNAL_ERROR (fname);
1088 : :
1089 : : /* Get the section header string table index. */
1090 [ - + ]: 125 : if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
1091 : : {
1092 : 0 : cleanup_debug ();
1093 : 0 : error_exit (0, _("cannot get section header string table index"));
1094 : : }
1095 : :
1096 : : /* Get the number of phdrs in the old file. */
1097 : 125 : size_t phnum;
1098 [ - + ]: 125 : if (elf_getphdrnum (elf, &phnum) != 0)
1099 : : {
1100 : 0 : cleanup_debug ();
1101 : 0 : error_exit (0, _("cannot get number of phdrs"));
1102 : : }
1103 : :
1104 : : /* We now create a new ELF descriptor for the same file. We
1105 : : construct it almost exactly in the same way with some information
1106 : : dropped. */
1107 : 125 : Elf *newelf;
1108 [ + + ]: 125 : if (output_fname != NULL)
1109 : 82 : newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
1110 : : else
1111 : 43 : newelf = elf_clone (elf, ELF_C_EMPTY);
1112 : :
1113 [ - + ]: 125 : if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0))
1114 : : {
1115 : 0 : error (0, 0, _("cannot create new ehdr for file '%s': %s"),
1116 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
1117 : 0 : goto fail;
1118 : : }
1119 : :
1120 : : /* Copy over the old program header if needed. */
1121 [ + + ]: 125 : if (phnum > 0)
1122 : : {
1123 [ - + ]: 65 : if (unlikely (gelf_newphdr (newelf, phnum) == 0))
1124 : : {
1125 : 0 : error (0, 0, _("cannot create new phdr for file '%s': %s"),
1126 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
1127 : 0 : goto fail;
1128 : : }
1129 : :
1130 [ + + ]: 628 : for (cnt = 0; cnt < phnum; ++cnt)
1131 : : {
1132 : 563 : GElf_Phdr phdr_mem;
1133 : 563 : GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
1134 [ + - ]: 563 : if (phdr == NULL
1135 [ - + ]: 563 : || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
1136 : 563 : INTERNAL_ERROR (fname);
1137 : : }
1138 : : }
1139 : :
1140 [ + + ]: 125 : if (reloc_debug_only)
1141 : : {
1142 [ - + ]: 16 : if (handle_debug_relocs (elf, ebl, newelf, ehdr, fname, shstrndx,
1143 : : &lastsec_offset, &lastsec_size) != 0)
1144 : : {
1145 : 0 : result = 1;
1146 : 0 : goto fail_close;
1147 : : }
1148 : 16 : idx = shstrndx;
1149 : 16 : goto done; /* Skip all actual stripping operations. */
1150 : : }
1151 : :
1152 [ + + ]: 109 : if (debug_fname != NULL)
1153 : : {
1154 : : /* Also create an ELF descriptor for the debug file */
1155 : 72 : debugelf = elf_begin (debug_fd, ELF_C_WRITE, NULL);
1156 [ - + ]: 72 : if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0))
1157 : : {
1158 : 0 : error (0, 0, _("cannot create new ehdr for file '%s': %s"),
1159 : : debug_fname, elf_errmsg (-1));
1160 : 0 : goto fail_close;
1161 : : }
1162 : :
1163 : : /* Copy over the old program header if needed. */
1164 [ + + ]: 72 : if (phnum > 0)
1165 : : {
1166 [ - + ]: 35 : if (unlikely (gelf_newphdr (debugelf, phnum) == 0))
1167 : : {
1168 : 0 : error (0, 0, _("cannot create new phdr for file '%s': %s"),
1169 : : debug_fname, elf_errmsg (-1));
1170 : 0 : goto fail_close;
1171 : : }
1172 : :
1173 [ + + ]: 366 : for (cnt = 0; cnt < phnum; ++cnt)
1174 : : {
1175 : 331 : GElf_Phdr phdr_mem;
1176 : 331 : GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
1177 [ + - ]: 331 : if (phdr == NULL
1178 [ - + ]: 331 : || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
1179 : 331 : INTERNAL_ERROR (fname);
1180 : : }
1181 : : }
1182 : : }
1183 : :
1184 : : /* Number of sections. */
1185 : 109 : size_t shnum;
1186 [ - + ]: 109 : if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
1187 : : {
1188 : 0 : error (0, 0, _("cannot determine number of sections: %s"),
1189 : : elf_errmsg (-1));
1190 : 0 : goto fail_close;
1191 : : }
1192 : :
1193 [ - + ]: 109 : if (shstrndx >= shnum)
1194 : 0 : goto illformed;
1195 : :
1196 : : #define elf_assert(test) do { if (!(test)) goto illformed; } while (0)
1197 : :
1198 : : /* Storage for section information. We leave room for two more
1199 : : entries since we unconditionally create a section header string
1200 : : table. Maybe some weird tool created an ELF file without one.
1201 : : The other one is used for the debug link section. */
1202 [ + + ]: 109 : if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1203 : 3 : shdr_info = xcalloc (shnum + 2, sizeof (struct shdr_info));
1204 : : else
1205 : : {
1206 : 106 : shdr_info = (struct shdr_info *) alloca ((shnum + 2)
1207 : : * sizeof (struct shdr_info));
1208 : 106 : memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
1209 : : }
1210 : :
1211 : : /* Track whether allocated sections all come before non-allocated ones. */
1212 : 109 : bool seen_allocated = false;
1213 : 109 : bool seen_unallocated = false;
1214 : 109 : bool mixed_allocated_unallocated = false;
1215 : :
1216 : : /* Prepare section information data structure. */
1217 : 109 : scn = NULL;
1218 : 109 : cnt = 1;
1219 [ + + ]: 200164 : while ((scn = elf_nextscn (elf, scn)) != NULL)
1220 : : {
1221 : : /* This should always be true (i.e., there should not be any
1222 : : holes in the numbering). */
1223 [ - + ]: 200055 : elf_assert (elf_ndxscn (scn) == cnt);
1224 : :
1225 : 200055 : shdr_info[cnt].scn = scn;
1226 : :
1227 : : /* Get the header. */
1228 [ - + ]: 200055 : if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
1229 : 0 : INTERNAL_ERROR (fname);
1230 : :
1231 : : /* Normally (in non-ET_REL files) we see all allocated sections first,
1232 : : then all non-allocated. */
1233 [ + + ]: 200055 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
1234 : : seen_unallocated = true;
1235 : : else
1236 : : {
1237 [ + + ]: 1870 : if (seen_unallocated && seen_allocated)
1238 : 313 : mixed_allocated_unallocated = true;
1239 : : seen_allocated = true;
1240 : : }
1241 : :
1242 : : /* Get the name of the section. */
1243 : 400110 : shdr_info[cnt].name = elf_strptr (elf, shstrndx,
1244 : 200055 : shdr_info[cnt].shdr.sh_name);
1245 [ - + ]: 200055 : if (shdr_info[cnt].name == NULL)
1246 : : {
1247 : 0 : illformed:
1248 : 0 : error (0, 0, _("illformed file '%s'"), fname);
1249 : 0 : goto fail_close;
1250 : : }
1251 : :
1252 : : /* Sanity check the user. */
1253 [ + + ]: 200055 : if (section_name_matches (remove_secs, shdr_info[cnt].name))
1254 : : {
1255 [ - + ]: 6 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
1256 : : {
1257 : 0 : error (0, 0,
1258 : 0 : _("Cannot remove allocated section '%s'"),
1259 : : shdr_info[cnt].name);
1260 : 0 : result = 1;
1261 : 0 : goto fail_close;
1262 : : }
1263 : :
1264 [ - + ]: 6 : if (section_name_matches (keep_secs, shdr_info[cnt].name))
1265 : : {
1266 : 0 : error (0, 0,
1267 : 0 : _("Cannot both keep and remove section '%s'"),
1268 : : shdr_info[cnt].name);
1269 : 0 : result = 1;
1270 : 0 : goto fail_close;
1271 : : }
1272 : : }
1273 : :
1274 : : /* Mark them as present but not yet investigated. */
1275 : 200055 : shdr_info[cnt].idx = 1;
1276 : :
1277 : : /* Remember the shdr.sh_link value. */
1278 : 200055 : shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
1279 [ - + ]: 200055 : if (shdr_info[cnt].old_sh_link >= shnum)
1280 : 0 : goto illformed;
1281 : :
1282 : : /* Sections in files other than relocatable object files which
1283 : : not loaded can be freely moved by us. In theory we can also
1284 : : freely move around allocated nobits sections. But we don't
1285 : : to keep the layout of all allocated sections as similar as
1286 : : possible to the original file. In relocatable object files
1287 : : everything can be moved. */
1288 [ + + ]: 200055 : if (phnum == 0
1289 [ + + ]: 198733 : || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
1290 : 198576 : shdr_info[cnt].shdr.sh_offset = 0;
1291 : :
1292 : : /* If this is an extended section index table store an
1293 : : appropriate reference. */
1294 [ - + ]: 200055 : if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
1295 : : {
1296 [ # # ]: 0 : elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
1297 : 0 : shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
1298 : : }
1299 [ + + ]: 200055 : else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
1300 : : {
1301 : : /* Cross-reference the sections contained in the section
1302 : : group. */
1303 : 10 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1304 [ + - ]: 10 : if (shdr_info[cnt].data == NULL
1305 [ - + ]: 10 : || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
1306 : 0 : INTERNAL_ERROR (fname);
1307 : :
1308 : : /* XXX Fix for unaligned access. */
1309 : 10 : Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1310 : 10 : size_t inner;
1311 : 10 : for (inner = 1;
1312 [ + + ]: 28 : inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1313 : 18 : ++inner)
1314 : : {
1315 [ + - ]: 18 : if (grpref[inner] < shnum)
1316 : 18 : shdr_info[grpref[inner]].group_idx = cnt;
1317 : : else
1318 : 0 : goto illformed;
1319 : : }
1320 : :
1321 [ + - + + : 10 : if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
+ + ]
1322 : : /* If the section group contains only one element and this
1323 : : is n COMDAT section we can drop it right away. */
1324 : 2 : shdr_info[cnt].idx = 0;
1325 : : else
1326 : 8 : shdr_info[cnt].group_cnt = inner - 1;
1327 : : }
1328 [ + + ]: 200045 : else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
1329 : : {
1330 [ - + ]: 63 : elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
1331 : 63 : shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
1332 : : }
1333 : :
1334 : : /* If this section is part of a group make sure it is not
1335 : : discarded right away. */
1336 [ + + ]: 200055 : if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
1337 : : {
1338 [ - + ]: 18 : elf_assert (shdr_info[cnt].group_idx != 0);
1339 : :
1340 [ + + ]: 18 : if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
1341 : : {
1342 : : /* The section group section might be removed.
1343 : : Don't remove the SHF_GROUP flag. The section is
1344 : : either also removed, in which case the flag doesn't matter.
1345 : : Or it moves with the group into the debug file, then
1346 : : it will be reconnected with the new group and should
1347 : : still have the flag set. */
1348 : 2 : shdr_info[cnt].group_idx = 0;
1349 : : }
1350 : : }
1351 : :
1352 : : /* Increment the counter. */
1353 : 200055 : ++cnt;
1354 : : }
1355 : :
1356 : : /* Now determine which sections can go away. The general rule is that
1357 : : all sections which are not used at runtime are stripped out. But
1358 : : there are a few exceptions:
1359 : :
1360 : : - special sections named ".comment" and ".note" are kept
1361 : : - OS or architecture specific sections are kept since we might not
1362 : : know how to handle them
1363 : : - if a section is referred to from a section which is not removed
1364 : : in the sh_link or sh_info element it cannot be removed either
1365 : : - the user might have explicitly said to remove or keep a section
1366 : : */
1367 [ + + ]: 200164 : for (cnt = 1; cnt < shnum; ++cnt)
1368 : : /* Check whether the section can be removed. Since we will create
1369 : : a new .shstrtab assume it will be removed too. */
1370 [ - + - - ]: 200055 : if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
1371 : 200055 : : (ebl_section_strip_p (ebl, &shdr_info[cnt].shdr,
1372 : 200055 : shdr_info[cnt].name, remove_comment,
1373 : : remove_debug)
1374 [ + + ]: 67642 : || cnt == shstrndx
1375 [ + + + + ]: 267661 : || section_name_matches (remove_secs, shdr_info[cnt].name)))
1376 : : {
1377 : : /* The user might want to explicitly keep this one. */
1378 [ + + ]: 132455 : if (section_name_matches (keep_secs, shdr_info[cnt].name))
1379 : 6 : continue;
1380 : :
1381 : : /* For now assume this section will be removed. */
1382 : 132449 : shdr_info[cnt].idx = 0;
1383 : :
1384 : 132449 : idx = shdr_info[cnt].group_idx;
1385 [ + + ]: 132450 : while (idx != 0)
1386 : : {
1387 : : /* The section group data is already loaded. */
1388 [ + - + - : 5 : elf_assert (shdr_info[idx].data != NULL
- + ]
1389 : : && shdr_info[idx].data->d_buf != NULL
1390 : : && shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
1391 : :
1392 : : /* If the references section group is a normal section
1393 : : group and has one element remaining, or if it is an
1394 : : empty COMDAT section group it is removed. */
1395 : 5 : bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
1396 : 5 : & GRP_COMDAT) != 0;
1397 : :
1398 : 5 : --shdr_info[idx].group_cnt;
1399 [ + + - + ]: 5 : if ((!is_comdat && shdr_info[idx].group_cnt == 1)
1400 [ + - ]: 1 : || (is_comdat && shdr_info[idx].group_cnt == 0))
1401 : : {
1402 : 1 : shdr_info[idx].idx = 0;
1403 : : /* Continue recursively. */
1404 : 1 : idx = shdr_info[idx].group_idx;
1405 : : }
1406 : : else
1407 : : break;
1408 : : }
1409 : : }
1410 : :
1411 : : /* Mark the SHT_NULL section as handled. */
1412 : 109 : shdr_info[0].idx = 2;
1413 : :
1414 : :
1415 : : /* Handle exceptions: section groups and cross-references. We might
1416 : : have to repeat this a few times since the resetting of the flag
1417 : : might propagate. */
1418 : 109 : do
1419 : : {
1420 : 109 : changes = false;
1421 : :
1422 [ + + ]: 200164 : for (cnt = 1; cnt < shnum; ++cnt)
1423 : : {
1424 [ + + ]: 200055 : if (shdr_info[cnt].idx == 0)
1425 : : {
1426 : : /* If a relocation section is marked as being removed make
1427 : : sure the section it is relocating is removed, too. */
1428 : 132365 : if (shdr_info[cnt].shdr.sh_type == SHT_REL
1429 [ + + ]: 132365 : || shdr_info[cnt].shdr.sh_type == SHT_RELA)
1430 : : {
1431 [ - + ]: 376 : if (shdr_info[cnt].shdr.sh_info >= shnum)
1432 : 0 : goto illformed;
1433 [ + + ]: 376 : else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
1434 : 168 : shdr_info[cnt].idx = 1;
1435 : : }
1436 : :
1437 : : /* If a group section is marked as being removed make
1438 : : sure all the sections it contains are being removed, too. */
1439 [ + + ]: 132365 : if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1440 : : {
1441 : 10 : Elf32_Word *grpref;
1442 : 10 : grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1443 : 10 : for (size_t in = 1;
1444 [ + + ]: 11 : in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1445 : 1 : ++in)
1446 [ + - ]: 10 : if (grpref[in] < shnum)
1447 : : {
1448 [ + + ]: 10 : if (shdr_info[grpref[in]].idx != 0)
1449 : : {
1450 : 9 : shdr_info[cnt].idx = 1;
1451 : 9 : break;
1452 : : }
1453 : : }
1454 : : else
1455 : 0 : goto illformed;
1456 : : }
1457 : : }
1458 : :
1459 [ + + ]: 200055 : if (shdr_info[cnt].idx == 1)
1460 : : {
1461 : : /* The content of symbol tables we don't remove must not
1462 : : reference any section which we do remove. Otherwise
1463 : : we cannot remove the section. */
1464 [ + + ]: 67867 : if (debug_fname != NULL
1465 [ + + ]: 67065 : && shdr_info[cnt].debug_data == NULL
1466 : 66987 : && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1467 [ + + ]: 66987 : || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
1468 : : {
1469 : : /* Make sure the data is loaded. */
1470 [ + - ]: 51 : if (shdr_info[cnt].data == NULL)
1471 : : {
1472 : 51 : shdr_info[cnt].data
1473 : 51 : = elf_getdata (shdr_info[cnt].scn, NULL);
1474 [ - + ]: 51 : if (shdr_info[cnt].data == NULL)
1475 : 0 : INTERNAL_ERROR (fname);
1476 : : }
1477 : 51 : Elf_Data *symdata = shdr_info[cnt].data;
1478 : :
1479 : : /* If there is an extended section index table load it
1480 : : as well. */
1481 [ - + ]: 51 : if (shdr_info[cnt].symtab_idx != 0
1482 [ # # ]: 0 : && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
1483 : : {
1484 [ # # ]: 0 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
1485 : :
1486 : 0 : shdr_info[shdr_info[cnt].symtab_idx].data
1487 : 0 : = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1488 : : NULL);
1489 [ # # ]: 0 : if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
1490 : 0 : INTERNAL_ERROR (fname);
1491 : : }
1492 : 51 : Elf_Data *xndxdata
1493 : 51 : = shdr_info[shdr_info[cnt].symtab_idx].data;
1494 : :
1495 : : /* Go through all symbols and make sure the section they
1496 : : reference is not removed. */
1497 : 51 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1498 : :
1499 : 51 : for (size_t inner = 0;
1500 [ + + ]: 1552 : inner < shdr_info[cnt].data->d_size / elsize;
1501 : 1501 : ++inner)
1502 : : {
1503 : 1501 : GElf_Sym sym_mem;
1504 : 1501 : Elf32_Word xndx;
1505 : 1501 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1506 : : inner, &sym_mem,
1507 : : &xndx);
1508 [ - + ]: 1501 : if (sym == NULL)
1509 : 0 : INTERNAL_ERROR (fname);
1510 : :
1511 : 1501 : size_t scnidx = sym->st_shndx;
1512 [ + + + + ]: 1501 : if (scnidx == SHN_UNDEF || scnidx >= shnum
1513 : 780 : || (scnidx >= SHN_LORESERVE
1514 : : && scnidx <= SHN_HIRESERVE
1515 [ + + ]: 780 : && scnidx != SHN_XINDEX)
1516 : : /* Don't count in the section symbols. */
1517 [ + + ]: 769 : || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
1518 : : /* This is no section index, leave it alone. */
1519 : 928 : continue;
1520 [ - + ]: 573 : else if (scnidx == SHN_XINDEX)
1521 : 0 : scnidx = xndx;
1522 : :
1523 [ - + ]: 573 : if (scnidx >= shnum)
1524 : 0 : goto illformed;
1525 : :
1526 [ + + ]: 573 : if (shdr_info[scnidx].idx == 0)
1527 : : /* This symbol table has a real symbol in
1528 : : a discarded section. So preserve the
1529 : : original table in the debug file. Unless
1530 : : it is a redundant data marker to a debug
1531 : : (data only) section. */
1532 [ + - - + ]: 8 : if (! (ebl_section_strip_p (ebl,
1533 : 4 : &shdr_info[scnidx].shdr,
1534 : : shdr_info[scnidx].name,
1535 : : remove_comment,
1536 : : remove_debug)
1537 : 4 : && ebl_data_marker_symbol (ebl, sym,
1538 : 4 : elf_strptr (elf,
1539 : 4 : shdr_info[cnt].shdr.sh_link,
1540 : 4 : sym->st_name))))
1541 : 0 : shdr_info[cnt].debug_data = symdata;
1542 : : }
1543 : : }
1544 : :
1545 : : /* Cross referencing happens:
1546 : : - for the cases the ELF specification says. That are
1547 : : + SHT_DYNAMIC in sh_link to string table
1548 : : + SHT_HASH in sh_link to symbol table
1549 : : + SHT_REL and SHT_RELA in sh_link to symbol table
1550 : : + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
1551 : : + SHT_GROUP in sh_link to symbol table
1552 : : + SHT_SYMTAB_SHNDX in sh_link to symbol table
1553 : : Other (OS or architecture-specific) sections might as
1554 : : well use this field so we process it unconditionally.
1555 : : - references inside section groups
1556 : : - specially marked references in sh_info if the SHF_INFO_LINK
1557 : : flag is set
1558 : : */
1559 : :
1560 [ + + ]: 67867 : if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
1561 : : {
1562 : 84 : shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
1563 : 84 : changes |= shdr_info[cnt].shdr.sh_link < cnt;
1564 : : }
1565 : :
1566 : : /* Handle references through sh_info. */
1567 [ + + - + ]: 67867 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1568 : : {
1569 [ - + ]: 282 : if (shdr_info[cnt].shdr.sh_info >= shnum)
1570 : 0 : goto illformed;
1571 [ - + ]: 282 : else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
1572 : : {
1573 : 0 : shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
1574 : 0 : changes |= shdr_info[cnt].shdr.sh_info < cnt;
1575 : : }
1576 : : }
1577 : :
1578 : : /* Mark the section as investigated. */
1579 : 67867 : shdr_info[cnt].idx = 2;
1580 : : }
1581 : :
1582 [ + + ]: 200055 : if (debug_fname != NULL
1583 [ + + + + ]: 133361 : && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
1584 : : {
1585 : : /* This section is being preserved in the debug file.
1586 : : Sections it refers to must be preserved there too.
1587 : :
1588 : : In this pass we mark sections to be preserved in both
1589 : : files by setting the .debug_data pointer to the original
1590 : : file's .data pointer. Below, we'll copy the section
1591 : : contents. */
1592 : 66374 : size_t shdr_indices[2] = { shdr_info[cnt].shdr.sh_link, 0 };
1593 : 66374 : int n = 1;
1594 : :
1595 [ + + - + ]: 66374 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1596 : : {
1597 : 173 : shdr_indices[1] = shdr_info[cnt].shdr.sh_info;
1598 : 173 : n++;
1599 : : }
1600 : :
1601 [ + + ]: 132921 : for (int j = 0; j < n; j++)
1602 : : {
1603 : 66547 : size_t i = shdr_indices[j];
1604 [ + + + - : 66547 : if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
+ + ]
1605 [ + + ]: 215 : && shdr_info[i].debug_data == NULL)
1606 : : {
1607 [ + - ]: 78 : if (shdr_info[i].data == NULL)
1608 : 78 : shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
1609 [ - + ]: 78 : if (shdr_info[i].data == NULL)
1610 : 0 : INTERNAL_ERROR (fname);
1611 : :
1612 : 78 : shdr_info[i].debug_data = shdr_info[i].data;
1613 : 78 : changes |= i < cnt;
1614 : : }
1615 : : }
1616 : : }
1617 : : }
1618 : : }
1619 [ - + ]: 109 : while (changes);
1620 : :
1621 : : /* Copy the removed sections to the debug output file.
1622 : : The ones that are not removed in the stripped file are SHT_NOBITS. */
1623 [ + + ]: 109 : if (debug_fname != NULL)
1624 : : {
1625 [ + + ]: 133433 : for (cnt = 1; cnt < shnum; ++cnt)
1626 : : {
1627 : 133361 : scn = elf_newscn (debugelf);
1628 [ - + ]: 133361 : if (scn == NULL)
1629 : : {
1630 : 0 : cleanup_debug ();
1631 : 0 : error_exit (0, _("while generating output file: %s"),
1632 : : elf_errmsg (-1));
1633 : : }
1634 : :
1635 : 266722 : bool discard_section = (shdr_info[cnt].idx > 0
1636 [ + + ]: 67065 : && shdr_info[cnt].debug_data == NULL
1637 [ + + ]: 66987 : && shdr_info[cnt].shdr.sh_type != SHT_NOTE
1638 [ + + ]: 66878 : && shdr_info[cnt].shdr.sh_type != SHT_GROUP
1639 [ + + - + ]: 200230 : && cnt != shstrndx);
1640 : :
1641 : : /* Set the section header in the new file. */
1642 : 133361 : GElf_Shdr debugshdr = shdr_info[cnt].shdr;
1643 [ + + ]: 133361 : if (discard_section)
1644 : 66869 : debugshdr.sh_type = SHT_NOBITS;
1645 : :
1646 [ - + ]: 133361 : if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
1647 : : /* There cannot be any overflows. */
1648 : 0 : INTERNAL_ERROR (fname);
1649 : :
1650 : : /* Get the data from the old file if necessary. */
1651 [ + + ]: 133361 : if (shdr_info[cnt].data == NULL)
1652 : : {
1653 : 133222 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1654 [ - + ]: 133222 : if (shdr_info[cnt].data == NULL)
1655 : 0 : INTERNAL_ERROR (fname);
1656 : : }
1657 : :
1658 : : /* Set the data. This is done by copying from the old file. */
1659 : 133361 : Elf_Data *debugdata = elf_newdata (scn);
1660 [ - + ]: 133361 : if (debugdata == NULL)
1661 : 0 : INTERNAL_ERROR (fname);
1662 : :
1663 : : /* Copy the structure. This data may be modified in place
1664 : : before we write out the file. */
1665 : 133361 : *debugdata = *shdr_info[cnt].data;
1666 [ + + ]: 133361 : if (discard_section)
1667 : 66869 : debugdata->d_buf = NULL;
1668 [ + + ]: 66492 : else if (shdr_info[cnt].debug_data != NULL
1669 [ + + ]: 66414 : || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1670 : : {
1671 : : /* Copy the original data before it gets modified. */
1672 : 88 : shdr_info[cnt].debug_data = debugdata;
1673 [ - + ]: 88 : if (debugdata->d_buf == NULL)
1674 : 0 : INTERNAL_ERROR (fname);
1675 : 88 : debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
1676 : : debugdata->d_buf, debugdata->d_size);
1677 : : }
1678 : : }
1679 : :
1680 : : /* Finish the ELF header. Fill in the fields not handled by
1681 : : libelf from the old file. */
1682 : 72 : debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
1683 [ - + ]: 72 : if (debugehdr == NULL)
1684 : 0 : INTERNAL_ERROR (fname);
1685 : :
1686 : 72 : memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1687 : 72 : debugehdr->e_type = ehdr->e_type;
1688 : 72 : debugehdr->e_machine = ehdr->e_machine;
1689 : 72 : debugehdr->e_version = ehdr->e_version;
1690 : 72 : debugehdr->e_entry = ehdr->e_entry;
1691 : 72 : debugehdr->e_flags = ehdr->e_flags;
1692 : :
1693 [ - + ]: 72 : if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
1694 : : {
1695 : 0 : error (0, 0, _("%s: error while updating ELF header: %s"),
1696 : : debug_fname, elf_errmsg (-1));
1697 : 0 : result = 1;
1698 : 0 : goto fail_close;
1699 : : }
1700 : :
1701 : 72 : size_t shdrstrndx;
1702 [ - + ]: 72 : if (elf_getshdrstrndx (elf, &shdrstrndx) < 0)
1703 : : {
1704 : 0 : error (0, 0, _("%s: error while getting shdrstrndx: %s"),
1705 : : fname, elf_errmsg (-1));
1706 : 0 : result = 1;
1707 : 0 : goto fail_close;
1708 : : }
1709 : :
1710 [ - + ]: 72 : if (update_shdrstrndx (debugelf, shdrstrndx) != 0)
1711 : : {
1712 : 0 : error (0, 0, _("%s: error updating shdrstrndx: %s"),
1713 : : debug_fname, elf_errmsg (-1));
1714 : 0 : result = 1;
1715 : 0 : goto fail_close;
1716 : : }
1717 : : }
1718 : :
1719 : : /* Although we always create a new section header string table we
1720 : : don't explicitly mark the existing one as unused. It can still
1721 : : be used through a symbol table section we are keeping. If not it
1722 : : will already be marked as unused. */
1723 : :
1724 : : /* We need a string table for the section headers. */
1725 : 109 : shst = dwelf_strtab_init (true);
1726 [ - + ]: 109 : if (shst == NULL)
1727 : : {
1728 : 0 : cleanup_debug ();
1729 [ # # ]: 0 : error_exit (errno, _("while preparing output for '%s'"),
1730 : : output_fname ?: fname);
1731 : : }
1732 : :
1733 : : /* Assign new section numbers. */
1734 : 109 : shdr_info[0].idx = 0;
1735 [ + + ]: 200164 : for (cnt = idx = 1; cnt < shnum; ++cnt)
1736 [ + + ]: 200055 : if (shdr_info[cnt].idx > 0)
1737 : : {
1738 : 67867 : shdr_info[cnt].idx = idx++;
1739 : :
1740 : : /* Create a new section. */
1741 : 67867 : shdr_info[cnt].newscn = elf_newscn (newelf);
1742 [ - + ]: 67867 : if (shdr_info[cnt].newscn == NULL)
1743 : : {
1744 : 0 : cleanup_debug ();
1745 : 0 : error_exit (0,
1746 : : _("while generating output file: %s"),
1747 : : elf_errmsg (-1));
1748 : : }
1749 : :
1750 [ - + ]: 67867 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1751 : :
1752 : : /* Add this name to the section header string table. */
1753 : 67867 : shdr_info[cnt].se = dwelf_strtab_add (shst, shdr_info[cnt].name);
1754 : : }
1755 : :
1756 : : /* Test whether we are doing anything at all. Either all removable
1757 : : sections are already gone. Or the only section we would remove is
1758 : : the .shstrtab section which we would add again. */
1759 [ + - ]: 109 : bool removing_sections = !(cnt == idx
1760 [ + + ]: 109 : || (cnt == idx + 1
1761 [ - + ]: 4 : && shdr_info[shstrndx].idx == 0));
1762 [ + + + + ]: 109 : if (output_fname == NULL && !removing_sections)
1763 : 2 : goto fail_close;
1764 : :
1765 : : /* Create the reference to the file with the debug info (if any). */
1766 [ + + + - : 107 : if (debug_fname != NULL && !remove_shdrs && removing_sections)
+ + ]
1767 : : {
1768 : : /* Add the section header string table section name. */
1769 : 70 : shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".gnu_debuglink", 15);
1770 : 70 : shdr_info[cnt].idx = idx++;
1771 : :
1772 : : /* Create the section header. */
1773 : 70 : shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
1774 : 70 : shdr_info[cnt].shdr.sh_flags = 0;
1775 : 70 : shdr_info[cnt].shdr.sh_addr = 0;
1776 : 70 : shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1777 : 70 : shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1778 : 70 : shdr_info[cnt].shdr.sh_entsize = 0;
1779 : 70 : shdr_info[cnt].shdr.sh_addralign = 4;
1780 : : /* We set the offset to zero here. Before we write the ELF file the
1781 : : field must have the correct value. This is done in the final
1782 : : loop over all section. Then we have all the information needed. */
1783 : 70 : shdr_info[cnt].shdr.sh_offset = 0;
1784 : :
1785 : : /* Create the section. */
1786 : 70 : shdr_info[cnt].newscn = elf_newscn (newelf);
1787 [ - + ]: 70 : if (shdr_info[cnt].newscn == NULL)
1788 : : {
1789 : 0 : cleanup_debug ();
1790 : 0 : error_exit (0, _("while create section header section: %s"),
1791 : : elf_errmsg (-1));
1792 : : }
1793 [ - + ]: 70 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1794 : :
1795 : 70 : shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
1796 [ - + ]: 70 : if (shdr_info[cnt].data == NULL)
1797 : : {
1798 : 0 : cleanup_debug ();
1799 : 0 : error_exit (0, _("cannot allocate section data: %s"),
1800 : : elf_errmsg (-1));
1801 : : }
1802 : :
1803 [ + + ]: 70 : char *debug_basename = basename (debug_fname_embed ?: debug_fname);
1804 : 70 : off_t crc_offset = strlen (debug_basename) + 1;
1805 : : /* Align to 4 byte boundary */
1806 : 70 : crc_offset = ((crc_offset - 1) & ~3) + 4;
1807 : :
1808 : 70 : shdr_info[cnt].data->d_align = 4;
1809 : 70 : shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1810 : 70 : = crc_offset + 4;
1811 : 70 : debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1812 : 70 : shdr_info[cnt].data->d_buf = debuglink_buf;
1813 : :
1814 : 70 : strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1815 : :
1816 : : /* Cache this Elf_Data describing the CRC32 word in the section.
1817 : : We'll fill this in when we have written the debug file. */
1818 : 70 : debuglink_crc_data = *shdr_info[cnt].data;
1819 : 70 : debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1820 : 70 : + crc_offset);
1821 : 70 : debuglink_crc_data.d_size = 4;
1822 : :
1823 : : /* One more section done. */
1824 : 70 : ++cnt;
1825 : : }
1826 : :
1827 : : /* Index of the section header table in the shdr_info array. */
1828 : 107 : shdridx = cnt;
1829 : :
1830 : : /* Add the section header string table section name. */
1831 : 107 : shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".shstrtab", 10);
1832 : 107 : shdr_info[cnt].idx = idx;
1833 : :
1834 : : /* Create the section header. */
1835 : 107 : shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1836 : 107 : shdr_info[cnt].shdr.sh_flags = 0;
1837 : 107 : shdr_info[cnt].shdr.sh_addr = 0;
1838 : 107 : shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1839 : 107 : shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1840 : 107 : shdr_info[cnt].shdr.sh_entsize = 0;
1841 : : /* We set the offset to zero here. Before we write the ELF file the
1842 : : field must have the correct value. This is done in the final
1843 : : loop over all section. Then we have all the information needed. */
1844 : 107 : shdr_info[cnt].shdr.sh_offset = 0;
1845 : 107 : shdr_info[cnt].shdr.sh_addralign = 1;
1846 : :
1847 : : /* Create the section. */
1848 : 107 : shdr_info[cnt].newscn = elf_newscn (newelf);
1849 [ - + ]: 107 : if (shdr_info[cnt].newscn == NULL)
1850 : : {
1851 : 0 : cleanup_debug ();
1852 : 0 : error_exit (0, _("while create section header section: %s"),
1853 : : elf_errmsg (-1));
1854 : : }
1855 [ - + ]: 107 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1856 : :
1857 : : /* Finalize the string table and fill in the correct indices in the
1858 : : section headers. */
1859 : 107 : shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1860 [ - + ]: 107 : if (shstrtab_data == NULL)
1861 : : {
1862 : 0 : cleanup_debug ();
1863 : 0 : error_exit (0, _("while create section header string table: %s"),
1864 : : elf_errmsg (-1));
1865 : : }
1866 [ - + ]: 107 : if (dwelf_strtab_finalize (shst, shstrtab_data) == NULL)
1867 : : {
1868 : 0 : cleanup_debug ();
1869 : 0 : error_exit (0, _("no memory to create section header string table"));
1870 : : }
1871 : :
1872 : : /* We have to set the section size. */
1873 : 107 : shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1874 : :
1875 : : /* Update the section information. */
1876 : 107 : GElf_Off lastoffset = 0;
1877 [ + + ]: 200285 : for (cnt = 1; cnt <= shdridx; ++cnt)
1878 [ + + ]: 200178 : if (shdr_info[cnt].idx > 0)
1879 : : {
1880 : 67992 : Elf_Data *newdata;
1881 : :
1882 : 67992 : scn = elf_getscn (newelf, shdr_info[cnt].idx);
1883 [ - + ]: 67992 : elf_assert (scn != NULL);
1884 : :
1885 : : /* Update the name. */
1886 : 67992 : shdr_info[cnt].shdr.sh_name = dwelf_strent_off (shdr_info[cnt].se);
1887 : :
1888 : : /* Update the section header from the input file. Some fields
1889 : : might be section indices which now have to be adjusted. Keep
1890 : : the index to the "current" sh_link in case we need it to lookup
1891 : : symbol table names. */
1892 : 67992 : size_t sh_link = shdr_info[cnt].shdr.sh_link;
1893 [ + + ]: 67992 : if (shdr_info[cnt].shdr.sh_link != 0)
1894 : 673 : shdr_info[cnt].shdr.sh_link =
1895 : 673 : shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1896 : :
1897 [ + + ]: 67992 : if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1898 : : {
1899 [ + - - + ]: 9 : elf_assert (shdr_info[cnt].data != NULL
1900 : : && shdr_info[cnt].data->d_buf != NULL);
1901 : :
1902 : : Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1903 : : /* First word is the section group flag.
1904 : : Followed by section indexes, that need to be renumbered. */
1905 : : for (size_t inner = 1;
1906 [ + + ]: 26 : inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1907 : 17 : ++inner)
1908 [ + - ]: 17 : if (grpref[inner] < shnum)
1909 : 17 : grpref[inner] = shdr_info[grpref[inner]].idx;
1910 : : else
1911 : 0 : goto illformed;
1912 : : }
1913 : :
1914 : : /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
1915 [ + + - + ]: 67992 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1916 : 280 : shdr_info[cnt].shdr.sh_info =
1917 : 280 : shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1918 : :
1919 : : /* Get the data from the old file if necessary. We already
1920 : : created the data for the section header string table. */
1921 [ + + ]: 67992 : if (cnt < shnum)
1922 : : {
1923 [ + + ]: 67815 : if (shdr_info[cnt].data == NULL)
1924 : : {
1925 : 776 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1926 [ - + ]: 776 : if (shdr_info[cnt].data == NULL)
1927 : 0 : INTERNAL_ERROR (fname);
1928 : : }
1929 : :
1930 : : /* Set the data. This is done by copying from the old file. */
1931 : 67815 : newdata = elf_newdata (scn);
1932 [ - + ]: 67815 : if (newdata == NULL)
1933 : 0 : INTERNAL_ERROR (fname);
1934 : :
1935 : : /* Copy the structure. */
1936 : 67815 : *newdata = *shdr_info[cnt].data;
1937 : :
1938 : : /* We know the size. */
1939 : 67815 : shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1940 : :
1941 : : /* We have to adjust symbol tables. The st_shndx member might
1942 : : have to be updated. */
1943 : 67815 : if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1944 [ + + ]: 67815 : || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1945 : : {
1946 : 132 : Elf_Data *versiondata = NULL;
1947 : 132 : Elf_Data *shndxdata = NULL;
1948 : :
1949 : 132 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1950 : :
1951 [ - + ]: 132 : if (shdr_info[cnt].symtab_idx != 0)
1952 : : {
1953 [ # # ]: 0 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1954 : : /* This section has extended section information.
1955 : : We have to modify that information, too. */
1956 : 0 : shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1957 : : NULL);
1958 : :
1959 [ # # # # : 0 : elf_assert (shndxdata != NULL
# # ]
1960 : : && shndxdata->d_buf != NULL
1961 : : && ((shndxdata->d_size / sizeof (Elf32_Word))
1962 : : >= shdr_info[cnt].data->d_size / elsize));
1963 : : }
1964 : :
1965 [ + + ]: 132 : if (shdr_info[cnt].version_idx != 0)
1966 : : {
1967 [ - + ]: 61 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1968 : : /* This section has associated version
1969 : : information. We have to modify that
1970 : : information, too. */
1971 : 61 : versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1972 : : NULL);
1973 : :
1974 [ + - + - : 61 : elf_assert (versiondata != NULL
- + ]
1975 : : && versiondata->d_buf != NULL
1976 : : && ((versiondata->d_size / sizeof (GElf_Versym))
1977 : : >= shdr_info[cnt].data->d_size / elsize));
1978 : : }
1979 : :
1980 : 132 : shdr_info[cnt].newsymidx
1981 : 132 : = xcalloc (shdr_info[cnt].data->d_size / elsize,
1982 : : sizeof (Elf32_Word));
1983 : :
1984 : 132 : bool last_was_local = true;
1985 : 132 : size_t destidx;
1986 : 132 : size_t inner;
1987 : 132 : for (destidx = inner = 1;
1988 [ + + ]: 19769 : inner < shdr_info[cnt].data->d_size / elsize;
1989 : 19637 : ++inner)
1990 : : {
1991 : 19637 : Elf32_Word sec;
1992 : 19637 : GElf_Sym sym_mem;
1993 : 19637 : Elf32_Word xshndx;
1994 : 19637 : GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1995 : : shndxdata, inner,
1996 : : &sym_mem, &xshndx);
1997 [ - + ]: 19637 : if (sym == NULL)
1998 : 0 : INTERNAL_ERROR (fname);
1999 : :
2000 : 21781 : if (sym->st_shndx == SHN_UNDEF
2001 [ + + ]: 19637 : || (sym->st_shndx >= SHN_LORESERVE
2002 : : && sym->st_shndx != SHN_XINDEX))
2003 : : {
2004 : : /* This is no section index, leave it alone
2005 : : unless it is moved. */
2006 [ + + ]: 2144 : if (destidx != inner
2007 [ - + ]: 1404 : && gelf_update_symshndx (shdr_info[cnt].data,
2008 : : shndxdata,
2009 : : destidx, sym,
2010 : : xshndx) == 0)
2011 : 0 : INTERNAL_ERROR (fname);
2012 : :
2013 : 2144 : shdr_info[cnt].newsymidx[inner] = destidx++;
2014 : :
2015 [ + + ]: 2144 : if (last_was_local
2016 [ + + ]: 347 : && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
2017 : : {
2018 : 82 : last_was_local = false;
2019 : 82 : shdr_info[cnt].shdr.sh_info = destidx - 1;
2020 : : }
2021 : :
2022 : 2144 : continue;
2023 : : }
2024 : :
2025 : : /* Get the full section index, if necessary from the
2026 : : XINDEX table. */
2027 [ - + ]: 17493 : if (sym->st_shndx == SHN_XINDEX)
2028 [ # # # # ]: 0 : elf_assert (shndxdata != NULL
2029 : : && shndxdata->d_buf != NULL);
2030 : 34986 : size_t sidx = (sym->st_shndx != SHN_XINDEX
2031 [ + - ]: 17493 : ? sym->st_shndx : xshndx);
2032 [ - + ]: 17493 : elf_assert (sidx < shnum);
2033 : 17493 : sec = shdr_info[sidx].idx;
2034 : :
2035 [ + + ]: 17493 : if (sec != 0)
2036 : : {
2037 : 3145 : GElf_Section nshndx;
2038 : 3145 : Elf32_Word nxshndx;
2039 : :
2040 [ + - ]: 3145 : if (sec < SHN_LORESERVE)
2041 : : {
2042 : 3145 : nshndx = sec;
2043 : 3145 : nxshndx = 0;
2044 : : }
2045 : : else
2046 : : {
2047 : : nshndx = SHN_XINDEX;
2048 : : nxshndx = sec;
2049 : : }
2050 : :
2051 [ - + ]: 3145 : elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
2052 : :
2053 [ + + + + ]: 3145 : if ((inner != destidx || nshndx != sym->st_shndx
2054 [ - + - - ]: 2158 : || (shndxdata != NULL && nxshndx != xshndx))
2055 [ - + ]: 987 : && (sym->st_shndx = nshndx,
2056 : 987 : gelf_update_symshndx (shdr_info[cnt].data,
2057 : : shndxdata,
2058 : : destidx, sym,
2059 : : nxshndx) == 0))
2060 : 0 : INTERNAL_ERROR (fname);
2061 : :
2062 : 3145 : shdr_info[cnt].newsymidx[inner] = destidx++;
2063 : :
2064 [ + + ]: 3145 : if (last_was_local
2065 [ + + ]: 2584 : && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
2066 : : {
2067 : 50 : last_was_local = false;
2068 : 50 : shdr_info[cnt].shdr.sh_info = destidx - 1;
2069 : : }
2070 : : }
2071 [ + + ]: 14348 : else if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0
2072 [ - + ]: 48 : && GELF_ST_TYPE (sym->st_info) != STT_SECTION
2073 [ # # ]: 0 : && shdr_info[sidx].shdr.sh_type != SHT_GROUP)
2074 : : {
2075 : : /* Removing a real symbol from an allocated
2076 : : symbol table is hard and probably a
2077 : : mistake. Really removing it means
2078 : : rewriting the dynamic segment and hash
2079 : : sections. Just warn and set the symbol
2080 : : section to UNDEF. */
2081 : 0 : error (0, 0,
2082 : 0 : _("Cannot remove symbol [%zd] from allocated symbol table [%zd]"), inner, cnt);
2083 : 0 : sym->st_shndx = SHN_UNDEF;
2084 [ # # ]: 0 : if (gelf_update_sym (shdr_info[cnt].data, destidx,
2085 : : sym) == 0)
2086 : 0 : INTERNAL_ERROR (fname);
2087 : 0 : shdr_info[cnt].newsymidx[inner] = destidx++;
2088 : : }
2089 [ + + ]: 14348 : else if (debug_fname != NULL
2090 [ + + ]: 14170 : && shdr_info[cnt].debug_data == NULL)
2091 : : /* The symbol points to a section that is discarded
2092 : : but isn't preserved in the debug file. Check that
2093 : : this is a section or group signature symbol
2094 : : for a section which has been removed. Or a special
2095 : : data marker symbol to a debug section. */
2096 : : {
2097 [ + + - + : 17538 : elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
- - + - ]
2098 : : || ((shdr_info[sidx].shdr.sh_type
2099 : : == SHT_GROUP)
2100 : : && (shdr_info[sidx].shdr.sh_info
2101 : : == inner))
2102 : : || ebl_data_marker_symbol (ebl, sym,
2103 : : elf_strptr (elf, sh_link,
2104 : : sym->st_name)));
2105 : : }
2106 : : }
2107 : :
2108 [ + + ]: 132 : if (destidx != inner)
2109 : : {
2110 : : /* The size of the symbol table changed. */
2111 : 65 : shdr_info[cnt].shdr.sh_size = newdata->d_size
2112 : 65 : = destidx * elsize;
2113 : 65 : any_symtab_changes = true;
2114 : : }
2115 : : else
2116 : : {
2117 : : /* The symbol table didn't really change. */
2118 : 67 : free (shdr_info[cnt].newsymidx);
2119 : 67 : shdr_info[cnt].newsymidx = NULL;
2120 : : }
2121 : : }
2122 : : }
2123 : :
2124 : : /* If we have to, compute the offset of the section.
2125 : : If allocate and unallocated sections are mixed, we only update
2126 : : the allocated ones now. The unallocated ones come second. */
2127 [ + + ]: 67992 : if (! mixed_allocated_unallocated
2128 [ + + ]: 66501 : || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
2129 : : {
2130 [ + + ]: 2043 : if (shdr_info[cnt].shdr.sh_offset == 0)
2131 : 614 : shdr_info[cnt].shdr.sh_offset
2132 : 614 : = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
2133 : 614 : & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
2134 : :
2135 : : /* Set the section header in the new file. */
2136 [ - + ]: 2043 : if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
2137 : : /* There cannot be any overflows. */
2138 : 0 : INTERNAL_ERROR (fname);
2139 : :
2140 : : /* Remember the last section written so far. */
2141 : 4086 : GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
2142 [ + + ]: 2043 : ? shdr_info[cnt].shdr.sh_size : 0);
2143 [ + + ]: 2043 : if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
2144 : 200178 : lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
2145 : : }
2146 : : }
2147 : :
2148 : : /* We might have to update the unallocated sections after we done the
2149 : : allocated ones. lastoffset is set to right after the last allocated
2150 : : section. */
2151 [ + + ]: 107 : if (mixed_allocated_unallocated)
2152 [ + + ]: 198232 : for (cnt = 1; cnt <= shdridx; ++cnt)
2153 [ + + ]: 198184 : if (shdr_info[cnt].idx > 0)
2154 : : {
2155 : 66501 : scn = elf_getscn (newelf, shdr_info[cnt].idx);
2156 [ + + ]: 66501 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
2157 : : {
2158 [ + - ]: 65949 : if (shdr_info[cnt].shdr.sh_offset == 0)
2159 : 65949 : shdr_info[cnt].shdr.sh_offset
2160 : 65949 : = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
2161 : 65949 : & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
2162 : :
2163 : : /* Set the section header in the new file. */
2164 [ - + ]: 65949 : if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
2165 : : /* There cannot be any overflows. */
2166 : 0 : INTERNAL_ERROR (fname);
2167 : :
2168 : : /* Remember the last section written so far. */
2169 : 131898 : GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
2170 [ + - ]: 65949 : ? shdr_info[cnt].shdr.sh_size : 0);
2171 [ + + ]: 65949 : if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
2172 : 198184 : lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
2173 : : }
2174 : : }
2175 : :
2176 : : /* Adjust symbol references if symbol tables changed. */
2177 [ + + ]: 107 : if (any_symtab_changes)
2178 : : /* Find all relocation sections which use this symbol table. */
2179 [ + + ]: 67664 : for (cnt = 1; cnt <= shdridx; ++cnt)
2180 : : {
2181 : 67601 : struct shdr_info *info = &shdr_info[cnt];
2182 [ + + + + ]: 67601 : if (info->idx == 0 && debug_fname == NULL)
2183 : : /* Ignore sections which are discarded. When we are saving a
2184 : : relocation section in a separate debug file, we must fix up
2185 : : the symbol table references. */
2186 : 211 : continue;
2187 : :
2188 : 67390 : const Elf32_Word symtabidx = info->old_sh_link;
2189 [ - + ]: 67390 : elf_assert (symtabidx < shnum + 2);
2190 : 67390 : const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
2191 : :
2192 : : /* If the symbol table hasn't changed, do not do anything. */
2193 [ + + ]: 67390 : if (newsymidx == NULL)
2194 : 67008 : continue;
2195 : :
2196 : : /* If the symbol table is not discarded, but additionally
2197 : : duplicated in the separate debug file and this section
2198 : : is discarded, don't adjust anything. */
2199 [ + + + - ]: 382 : if (info->idx == 0 && shdr_info[symtabidx].debug_data != NULL)
2200 : 174 : continue;
2201 : :
2202 [ + + + + : 208 : switch (info->shdr.sh_type)
- ]
2203 : : {
2204 : 187 : case SHT_REL:
2205 : : case SHT_RELA:
2206 : 374 : scn = (info->idx == 0
2207 : 0 : ? elf_getscn (debugelf, cnt)
2208 [ - + ]: 187 : : elf_getscn (newelf, info->idx));
2209 : 187 : Elf_Data *d = elf_getdata (scn, NULL);
2210 [ + - + - : 187 : elf_assert (d != NULL && d->d_buf != NULL
- + ]
2211 : : && info->shdr.sh_entsize != 0);
2212 : 187 : size_t nrels = (info->shdr.sh_size / info->shdr.sh_entsize);
2213 : :
2214 : 187 : size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2215 : 187 : const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
2216 : 187 : / symsize);
2217 [ + + ]: 187 : if (info->shdr.sh_type == SHT_REL)
2218 [ + + ]: 2439 : for (size_t relidx = 0; relidx < nrels; ++relidx)
2219 : : {
2220 : 2411 : GElf_Rel rel_mem;
2221 [ - + ]: 2411 : if (gelf_getrel (d, relidx, &rel_mem) == NULL)
2222 : 0 : INTERNAL_ERROR (fname);
2223 : :
2224 : 2411 : size_t symidx = GELF_R_SYM (rel_mem.r_info);
2225 [ - + ]: 2411 : elf_assert (symidx < symidxn);
2226 [ + + ]: 2411 : if (newsymidx[symidx] != symidx)
2227 : : {
2228 : 2206 : rel_mem.r_info
2229 : 2206 : = GELF_R_INFO (newsymidx[symidx],
2230 : : GELF_R_TYPE (rel_mem.r_info));
2231 : :
2232 [ - + ]: 2206 : if (gelf_update_rel (d, relidx, &rel_mem) == 0)
2233 : 2411 : INTERNAL_ERROR (fname);
2234 : : }
2235 : : }
2236 : : else
2237 [ + + ]: 13580 : for (size_t relidx = 0; relidx < nrels; ++relidx)
2238 : : {
2239 : 13421 : GElf_Rela rel_mem;
2240 [ - + ]: 13421 : if (gelf_getrela (d, relidx, &rel_mem) == NULL)
2241 : 0 : INTERNAL_ERROR (fname);
2242 : :
2243 : 13421 : size_t symidx = GELF_R_SYM (rel_mem.r_info);
2244 [ - + ]: 13421 : elf_assert (symidx < symidxn);
2245 [ + + ]: 13421 : if (newsymidx[symidx] != symidx)
2246 : : {
2247 : 3140 : rel_mem.r_info
2248 : 3140 : = GELF_R_INFO (newsymidx[symidx],
2249 : : GELF_R_TYPE (rel_mem.r_info));
2250 : :
2251 [ - + ]: 3140 : if (gelf_update_rela (d, relidx, &rel_mem) == 0)
2252 : 13421 : INTERNAL_ERROR (fname);
2253 : : }
2254 : : }
2255 : 208 : break;
2256 : :
2257 : 6 : case SHT_HASH:
2258 : : /* We have to recompute the hash table. */
2259 : :
2260 [ - + ]: 6 : elf_assert (info->idx > 0);
2261 : :
2262 : : /* The hash section in the new file. */
2263 : 6 : scn = elf_getscn (newelf, info->idx);
2264 : :
2265 : : /* The symbol table data. */
2266 : 6 : Elf_Data *symd = elf_getdata (elf_getscn (newelf,
2267 : 6 : shdr_info[symtabidx].idx),
2268 : : NULL);
2269 [ + - - + ]: 6 : elf_assert (symd != NULL && symd->d_buf != NULL);
2270 : :
2271 : : /* The hash table data. */
2272 : 6 : Elf_Data *hashd = elf_getdata (scn, NULL);
2273 [ + - - + ]: 6 : elf_assert (hashd != NULL && hashd->d_buf != NULL);
2274 : :
2275 [ + - ]: 6 : if (info->shdr.sh_entsize == sizeof (Elf32_Word))
2276 : : {
2277 : : /* Sane arches first. */
2278 [ - + ]: 6 : elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
2279 : 6 : Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
2280 : :
2281 : 6 : size_t strshndx = shdr_info[symtabidx].old_sh_link;
2282 : 6 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2283 : :
2284 : 6 : Elf32_Word nchain = bucket[1];
2285 : 6 : Elf32_Word nbucket = bucket[0];
2286 : 6 : uint64_t used_buf = ((2ULL + nchain + nbucket)
2287 : : * sizeof (Elf32_Word));
2288 [ - + ]: 6 : elf_assert (used_buf <= hashd->d_size);
2289 : :
2290 : : /* Adjust the nchain value. The symbol table size
2291 : : changed. We keep the same size for the bucket array. */
2292 : 6 : bucket[1] = symd->d_size / elsize;
2293 : 6 : bucket += 2;
2294 : 6 : Elf32_Word *chain = bucket + nbucket;
2295 : :
2296 : : /* New size of the section. */
2297 : 6 : size_t n_size = ((2 + symd->d_size / elsize + nbucket)
2298 : : * sizeof (Elf32_Word));
2299 [ - + ]: 6 : elf_assert (n_size <= hashd->d_size);
2300 : 6 : hashd->d_size = n_size;
2301 : 6 : update_section_size (scn, hashd, debugelf, cnt, fname);
2302 : :
2303 : : /* Clear the arrays. */
2304 : 6 : memset (bucket, '\0',
2305 : 6 : (symd->d_size / elsize + nbucket)
2306 : : * sizeof (Elf32_Word));
2307 : :
2308 : 6 : for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
2309 [ + + ]: 78 : inner < symd->d_size / elsize; ++inner)
2310 : : {
2311 : 72 : GElf_Sym sym_mem;
2312 : 72 : GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
2313 [ - + ]: 72 : elf_assert (sym != NULL);
2314 : :
2315 : 144 : const char *name = elf_strptr (elf, strshndx,
2316 : 72 : sym->st_name);
2317 [ - + ]: 72 : elf_assert (name != NULL && nbucket != 0);
2318 : 72 : size_t hidx = elf_hash (name) % nbucket;
2319 : :
2320 [ + + ]: 72 : if (bucket[hidx] == 0)
2321 : 60 : bucket[hidx] = inner;
2322 : : else
2323 : : {
2324 : 12 : hidx = bucket[hidx];
2325 : :
2326 [ - + - - ]: 12 : while (chain[hidx] != 0 && chain[hidx] < nchain)
2327 : 0 : hidx = chain[hidx];
2328 : :
2329 : 12 : chain[hidx] = inner;
2330 : : }
2331 : : }
2332 : : }
2333 : : else
2334 : : {
2335 : : /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
2336 [ # # ]: 0 : elf_assert (info->shdr.sh_entsize == sizeof (Elf64_Xword));
2337 : :
2338 : 0 : Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
2339 : :
2340 : 0 : size_t strshndx = shdr_info[symtabidx].old_sh_link;
2341 : 0 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2342 : :
2343 [ # # ]: 0 : elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
2344 : 0 : Elf64_Xword nbucket = bucket[0];
2345 : 0 : Elf64_Xword nchain = bucket[1];
2346 : 0 : uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
2347 [ # # # # : 0 : elf_assert (maxwords >= 2
# # ]
2348 : : && maxwords - 2 >= nbucket
2349 : : && maxwords - 2 - nbucket >= nchain);
2350 : :
2351 : : /* Adjust the nchain value. The symbol table size
2352 : : changed. We keep the same size for the bucket array. */
2353 : 0 : bucket[1] = symd->d_size / elsize;
2354 : 0 : bucket += 2;
2355 : 0 : Elf64_Xword *chain = bucket + nbucket;
2356 : :
2357 : : /* New size of the section. */
2358 : 0 : size_t n_size = ((2 + symd->d_size / elsize + nbucket)
2359 : : * sizeof (Elf64_Xword));
2360 [ # # ]: 0 : elf_assert (n_size <= hashd->d_size);
2361 : 0 : hashd->d_size = n_size;
2362 : 0 : update_section_size (scn, hashd, debugelf, cnt, fname);
2363 : :
2364 : : /* Clear the arrays. */
2365 : 0 : memset (bucket, '\0',
2366 : 0 : (symd->d_size / elsize + nbucket)
2367 : : * sizeof (Elf64_Xword));
2368 : :
2369 : 0 : for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
2370 [ # # ]: 0 : inner < symd->d_size / elsize; ++inner)
2371 : : {
2372 : 0 : GElf_Sym sym_mem;
2373 : 0 : GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
2374 [ # # ]: 0 : elf_assert (sym != NULL);
2375 : :
2376 : 0 : const char *name = elf_strptr (elf, strshndx,
2377 : 0 : sym->st_name);
2378 [ # # ]: 0 : elf_assert (name != NULL && nbucket != 0);
2379 : 0 : size_t hidx = elf_hash (name) % nbucket;
2380 : :
2381 [ # # ]: 0 : if (bucket[hidx] == 0)
2382 : 0 : bucket[hidx] = inner;
2383 : : else
2384 : : {
2385 : : hidx = bucket[hidx];
2386 : :
2387 [ # # # # ]: 0 : while (chain[hidx] != 0 && chain[hidx] < nchain)
2388 : : hidx = chain[hidx];
2389 : :
2390 : 0 : chain[hidx] = inner;
2391 : : }
2392 : : }
2393 : : }
2394 : : break;
2395 : :
2396 : 6 : case SHT_GNU_versym:
2397 : : /* If the symbol table changed we have to adjust the entries. */
2398 [ - + ]: 6 : elf_assert (info->idx > 0);
2399 : :
2400 : : /* The symbol version section in the new file. */
2401 : 6 : scn = elf_getscn (newelf, info->idx);
2402 : :
2403 : : /* The symbol table data. */
2404 : 6 : symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
2405 : : NULL);
2406 [ + - - + ]: 6 : elf_assert (symd != NULL && symd->d_buf != NULL);
2407 : 6 : size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2408 : 6 : const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
2409 : :
2410 : : /* The version symbol data. */
2411 : 6 : Elf_Data *verd = elf_getdata (scn, NULL);
2412 [ + - - + ]: 6 : elf_assert (verd != NULL && verd->d_buf != NULL);
2413 : :
2414 : : /* The symbol version array. */
2415 : 6 : GElf_Half *verstab = (GElf_Half *) verd->d_buf;
2416 : :
2417 : : /* Walk through the list and */
2418 : 6 : size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
2419 : 6 : Elf32_Word vers = verd->d_size / elsize;
2420 [ + + + - ]: 258 : for (size_t inner = 1; inner < vers && inner < syms; ++inner)
2421 [ + + + - ]: 252 : if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
2422 : : /* Overwriting the same array works since the
2423 : : reordering can only move entries to lower indices
2424 : : in the array. */
2425 : 204 : verstab[newsymidx[inner]] = verstab[inner];
2426 : :
2427 : : /* New size of the section. */
2428 : 6 : verd->d_size = gelf_fsize (newelf, verd->d_type,
2429 : 6 : symd->d_size
2430 : 6 : / gelf_fsize (elf, symd->d_type, 1,
2431 : : EV_CURRENT),
2432 : : EV_CURRENT);
2433 : 6 : update_section_size (scn, verd, debugelf, cnt, fname);
2434 : 6 : break;
2435 : :
2436 : 9 : case SHT_GROUP:
2437 : : /* Yes, the symbol table changed.
2438 : : Update the section header of the section group. */
2439 : 9 : scn = elf_getscn (newelf, info->idx);
2440 : 9 : GElf_Shdr shdr_mem;
2441 : 9 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2442 [ - + ]: 9 : elf_assert (shdr != NULL);
2443 : :
2444 : 9 : size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2445 : 9 : const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
2446 : 9 : / symsz);
2447 [ - + ]: 9 : elf_assert (shdr->sh_info < symn);
2448 : 9 : shdr->sh_info = newsymidx[shdr->sh_info];
2449 : :
2450 : 9 : (void) gelf_update_shdr (scn, shdr);
2451 : 9 : break;
2452 : : }
2453 : : }
2454 : :
2455 : : /* Remove any relocations between debug sections in ET_REL
2456 : : for the debug file when requested. These relocations are always
2457 : : zero based between the unallocated sections. */
2458 [ + + + + ]: 107 : if (debug_fname != NULL && removing_sections
2459 [ + + + + ]: 70 : && reloc_debug && ehdr->e_type == ET_REL)
2460 : 15 : remove_debug_relocations (ebl, debugelf, ehdr, fname, shstrndx);
2461 : :
2462 : : /* Now that we have done all adjustments to the data,
2463 : : we can actually write out the debug file. */
2464 [ + + + + ]: 107 : if (debug_fname != NULL && removing_sections)
2465 : : {
2466 : : /* Finally write the file. */
2467 [ - + ]: 70 : if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
2468 : : {
2469 : 0 : error (0, 0, _("while writing '%s': %s"),
2470 : : tmp_debug_fname, elf_errmsg (-1));
2471 : 0 : result = 1;
2472 : 0 : goto fail_close;
2473 : : }
2474 : :
2475 : : /* Create the real output file. First rename, then change the
2476 : : mode. */
2477 [ + - ]: 70 : if (rename (tmp_debug_fname, debug_fname) != 0
2478 [ - + ]: 70 : || fchmod (debug_fd, mode) != 0)
2479 : : {
2480 : 0 : error (0, errno, _("while creating '%s'"), debug_fname);
2481 : 0 : result = 1;
2482 : 0 : goto fail_close;
2483 : : }
2484 : :
2485 : : /* The temporary file does not exist anymore. */
2486 : 70 : free (tmp_debug_fname);
2487 : 70 : tmp_debug_fname = NULL;
2488 : :
2489 [ + - ]: 70 : if (!remove_shdrs)
2490 : : {
2491 : 70 : uint32_t debug_crc;
2492 : 70 : Elf_Data debug_crc_data =
2493 : : {
2494 : : .d_type = ELF_T_WORD,
2495 : : .d_buf = &debug_crc,
2496 : : .d_size = sizeof (debug_crc),
2497 : : .d_version = EV_CURRENT
2498 : : };
2499 : :
2500 : : /* Compute the checksum which we will add to the executable. */
2501 [ - + ]: 70 : if (crc32_file (debug_fd, &debug_crc) != 0)
2502 : : {
2503 : 0 : error (0, errno, _("\
2504 : : while computing checksum for debug information"));
2505 : 0 : unlink (debug_fname);
2506 : 0 : result = 1;
2507 : 0 : goto fail_close;
2508 : : }
2509 : :
2510 : : /* Store it in the debuglink section data. */
2511 [ - + ]: 70 : if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
2512 : : &debug_crc_data, ehdr->e_ident[EI_DATA])
2513 : : != &debuglink_crc_data))
2514 : 70 : INTERNAL_ERROR (fname);
2515 : : }
2516 : : }
2517 : :
2518 : 107 : lastsec_offset = shdr_info[shdridx].shdr.sh_offset;
2519 : 107 : lastsec_size = shdr_info[shdridx].shdr.sh_size;
2520 : :
2521 : 123 : done:
2522 : : /* Finally finish the ELF header. Fill in the fields not handled by
2523 : : libelf from the old file. */
2524 : 123 : newehdr = gelf_getehdr (newelf, &newehdr_mem);
2525 [ - + ]: 123 : if (newehdr == NULL)
2526 : 0 : INTERNAL_ERROR (fname);
2527 : :
2528 : 123 : memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
2529 : 123 : newehdr->e_type = ehdr->e_type;
2530 : 123 : newehdr->e_machine = ehdr->e_machine;
2531 : 123 : newehdr->e_version = ehdr->e_version;
2532 : 123 : newehdr->e_entry = ehdr->e_entry;
2533 : 123 : newehdr->e_flags = ehdr->e_flags;
2534 : 123 : newehdr->e_phoff = ehdr->e_phoff;
2535 : :
2536 : : /* We need to position the section header table. */
2537 : 123 : const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
2538 : 123 : newehdr->e_shoff = ((lastsec_offset + lastsec_size + offsize - 1)
2539 : 123 : & ~((GElf_Off) (offsize - 1)));
2540 : 123 : newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
2541 : :
2542 [ - + ]: 123 : if (gelf_update_ehdr (newelf, newehdr) == 0)
2543 : : {
2544 : 0 : error (0, 0, _("%s: error while creating ELF header: %s"),
2545 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2546 : 0 : cleanup_debug ();
2547 : 0 : return 1;
2548 : : }
2549 : :
2550 : : /* The new section header string table index. */
2551 [ - + ]: 123 : if (update_shdrstrndx (newelf, idx) != 0)
2552 : : {
2553 : 0 : error (0, 0, _("%s: error updating shdrstrndx: %s"),
2554 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2555 : 0 : cleanup_debug ();
2556 : 0 : return 1;
2557 : : }
2558 : :
2559 : : /* We have everything from the old file. */
2560 [ - + ]: 123 : if (elf_cntl (elf, ELF_C_FDDONE) != 0)
2561 : : {
2562 : 0 : error (0, 0, _("%s: error while reading the file: %s"),
2563 : : fname, elf_errmsg (-1));
2564 : 0 : cleanup_debug ();
2565 : 0 : return 1;
2566 : : }
2567 : :
2568 : : /* The ELF library better follows our layout when this is not a
2569 : : relocatable object file. */
2570 : 246 : elf_flagelf (newelf, ELF_C_SET,
2571 [ + + ]: 123 : (phnum > 0 ? ELF_F_LAYOUT : 0)
2572 [ + - ]: 246 : | (permissive ? ELF_F_PERMISSIVE : 0));
2573 : :
2574 : : /* Finally write the file. */
2575 [ - + ]: 123 : if (elf_update (newelf, ELF_C_WRITE) == -1)
2576 : : {
2577 : 0 : error (0, 0, _("while writing '%s': %s"),
2578 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2579 : 0 : result = 1;
2580 : : }
2581 : :
2582 [ + - ]: 123 : if (remove_shdrs)
2583 : : {
2584 : : /* libelf can't cope without the section headers being properly intact.
2585 : : So we just let it write them normally, and then we nuke them later. */
2586 : :
2587 [ # # ]: 0 : if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
2588 : : {
2589 : 0 : assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
2590 : : == offsetof (Elf32_Ehdr, e_shnum));
2591 : 0 : assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
2592 : : == offsetof (Elf32_Ehdr, e_shstrndx));
2593 : 0 : const Elf32_Off zero_off = 0;
2594 : 0 : const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
2595 [ # # ]: 0 : if (pwrite_retry (fd, &zero_off, sizeof zero_off,
2596 : : offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
2597 [ # # ]: 0 : || (pwrite_retry (fd, zero, sizeof zero,
2598 : : offsetof (Elf32_Ehdr, e_shentsize))
2599 : : != sizeof zero)
2600 [ # # ]: 0 : || ftruncate (fd, lastsec_offset) < 0)
2601 : : {
2602 : 0 : error (0, errno, _("while writing '%s'"),
2603 [ # # ]: 0 : output_fname ?: fname);
2604 : 0 : result = 1;
2605 : : }
2606 : : }
2607 : : else
2608 : : {
2609 : 0 : assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
2610 : : == offsetof (Elf64_Ehdr, e_shnum));
2611 : 0 : assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
2612 : : == offsetof (Elf64_Ehdr, e_shstrndx));
2613 : 0 : const Elf64_Off zero_off = 0;
2614 : 0 : const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
2615 [ # # ]: 0 : if (pwrite_retry (fd, &zero_off, sizeof zero_off,
2616 : : offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
2617 [ # # ]: 0 : || (pwrite_retry (fd, zero, sizeof zero,
2618 : : offsetof (Elf64_Ehdr, e_shentsize))
2619 : : != sizeof zero)
2620 [ # # ]: 0 : || ftruncate (fd, lastsec_offset) < 0)
2621 : : {
2622 : 0 : error (0, errno, _("while writing '%s'"),
2623 [ # # ]: 0 : output_fname ?: fname);
2624 : 0 : result = 1;
2625 : : }
2626 : : }
2627 : : }
2628 : :
2629 : 123 : fail_close:
2630 [ + + ]: 125 : if (shdr_info != NULL)
2631 : : {
2632 : : /* For some sections we might have created an table to map symbol
2633 : : table indices. Or we might kept (original) data around to put
2634 : : into the .debug file. */
2635 [ + + ]: 200287 : for (cnt = 1; cnt <= shdridx; ++cnt)
2636 : : {
2637 : 200178 : free (shdr_info[cnt].newsymidx);
2638 [ + + ]: 200178 : if (shdr_info[cnt].debug_data != NULL)
2639 : 88 : free (shdr_info[cnt].debug_data->d_buf);
2640 : : }
2641 : :
2642 : : /* Free data we allocated for the .gnu_debuglink section. */
2643 : 109 : free (debuglink_buf);
2644 : :
2645 : : /* Free the memory. */
2646 [ + + ]: 109 : if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
2647 : 3 : free (shdr_info);
2648 : : }
2649 : :
2650 : : /* Free other resources. */
2651 [ + + ]: 125 : if (shstrtab_data != NULL)
2652 : 107 : free (shstrtab_data->d_buf);
2653 [ + + ]: 125 : if (shst != NULL)
2654 : 109 : dwelf_strtab_free (shst);
2655 : :
2656 : : /* That was it. Close the descriptors. */
2657 [ - + ]: 125 : if (elf_end (newelf) != 0)
2658 : : {
2659 : 0 : error (0, 0, _("error while finishing '%s': %s"),
2660 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2661 : 0 : result = 1;
2662 : : }
2663 : :
2664 [ + + + - ]: 125 : if (debugelf != NULL && elf_end (debugelf) != 0)
2665 : : {
2666 : 0 : error (0, 0, _("error while finishing '%s': %s"), debug_fname,
2667 : : elf_errmsg (-1));
2668 : 0 : result = 1;
2669 : : }
2670 : :
2671 : 125 : fail:
2672 : : /* Close the EBL backend. */
2673 [ + + ]: 125 : if (ebl != NULL)
2674 : 68 : ebl_closebackend (ebl);
2675 : :
2676 : 125 : cleanup_debug ();
2677 : :
2678 : : /* If requested, preserve the timestamp. */
2679 [ + - ]: 125 : if (tvp != NULL)
2680 : : {
2681 [ # # ]: 0 : if (futimens (fd, tvp) != 0)
2682 : : {
2683 : 0 : error (0, errno, _("\
2684 : : cannot set access and modification date of '%s'"),
2685 [ # # ]: 0 : output_fname ?: fname);
2686 : 0 : result = 1;
2687 : : }
2688 : : }
2689 : :
2690 : : /* Close the file descriptor if we created a new file. */
2691 [ + + ]: 125 : if (output_fname != NULL)
2692 : : {
2693 : 82 : close (fd);
2694 [ + - ]: 82 : if (result != 0)
2695 : 0 : unlink (output_fname);
2696 : : }
2697 : :
2698 : : return result;
2699 : : }
2700 : :
2701 : : static void
2702 : 125 : cleanup_debug (void)
2703 : : {
2704 [ + + ]: 125 : if (debug_fd >= 0)
2705 : : {
2706 [ + + ]: 72 : if (tmp_debug_fname != NULL)
2707 : : {
2708 : 2 : unlink (tmp_debug_fname);
2709 : 2 : free (tmp_debug_fname);
2710 : 2 : tmp_debug_fname = NULL;
2711 : : }
2712 : 72 : close (debug_fd);
2713 : 72 : debug_fd = -1;
2714 : : }
2715 : 125 : }
2716 : :
2717 : : static int
2718 : : handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
2719 : : struct timespec tvp[2])
2720 : : {
2721 : : size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
2722 : : size_t fname_len = strlen (fname) + 1;
2723 : : char new_prefix[prefix_len + 1 + fname_len];
2724 : : char *cp = new_prefix;
2725 : :
2726 : : /* Create the full name of the file. */
2727 : : if (prefix != NULL)
2728 : : {
2729 : : cp = mempcpy (cp, prefix, prefix_len);
2730 : : *cp++ = ':';
2731 : : }
2732 : : memcpy (cp, fname, fname_len);
2733 : :
2734 : :
2735 : : /* Process all the files contained in the archive. */
2736 : : Elf *subelf;
2737 : : Elf_Cmd cmd = ELF_C_RDWR;
2738 : : int result = 0;
2739 : : while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
2740 : : {
2741 : : /* The the header for this element. */
2742 : : Elf_Arhdr *arhdr = elf_getarhdr (subelf);
2743 : :
2744 : : if (elf_kind (subelf) == ELF_K_ELF)
2745 : : result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
2746 : : else if (elf_kind (subelf) == ELF_K_AR)
2747 : : result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
2748 : :
2749 : : /* Get next archive element. */
2750 : : cmd = elf_next (subelf);
2751 : : if (unlikely (elf_end (subelf) != 0))
2752 : : INTERNAL_ERROR (fname);
2753 : : }
2754 : :
2755 : : if (tvp != NULL)
2756 : : {
2757 : : if (unlikely (futimens (fd, tvp) != 0))
2758 : : {
2759 : : error (0, errno, _("\
2760 : : cannot set access and modification date of '%s'"), fname);
2761 : : result = 1;
2762 : : }
2763 : : }
2764 : :
2765 : : if (unlikely (close (fd) != 0))
2766 : : error_exit (errno, _("while closing '%s'"), fname);
2767 : :
2768 : : return result;
2769 : : }
2770 : :
2771 : :
2772 : : #include "debugpred.h"
|