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 : 20 : add_pattern (struct section_pattern **patterns, const char *pattern)
179 : : {
180 : 20 : struct section_pattern *p = xmalloc (sizeof *p);
181 : 20 : p->pattern = xstrdup (pattern);
182 : 20 : p->next = *patterns;
183 : 20 : *patterns = p;
184 : 20 : }
185 : :
186 : : static void
187 : 512 : free_sec_patterns (struct section_pattern *patterns)
188 : : {
189 : 512 : struct section_pattern *pattern = patterns;
190 [ + + ]: 532 : while (pattern != NULL)
191 : : {
192 : 20 : struct section_pattern *p = pattern;
193 : 20 : pattern = p->next;
194 : 20 : free (p->pattern);
195 : 20 : free (p);
196 : : }
197 : 512 : }
198 : :
199 : : static void
200 : 256 : free_patterns (void)
201 : : {
202 : 256 : free_sec_patterns (keep_secs);
203 : 256 : free_sec_patterns (remove_secs);
204 : 256 : }
205 : :
206 : : static bool
207 : 800462 : section_name_matches (struct section_pattern *patterns, const char *name)
208 : : {
209 : 800462 : struct section_pattern *pattern = patterns;
210 [ + + ]: 800964 : while (pattern != NULL)
211 : : {
212 [ + + ]: 538 : if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
213 : : return true;
214 : 502 : pattern = pattern->next;
215 : : }
216 : : return false;
217 : : }
218 : :
219 : :
220 : : int
221 : 256 : main (int argc, char *argv[])
222 : : {
223 : 256 : int remaining;
224 : 256 : int result = 0;
225 : :
226 : : /* We use no threads here which can interfere with handling a stream. */
227 : 256 : __fsetlocking (stdin, FSETLOCKING_BYCALLER);
228 : 256 : __fsetlocking (stdout, FSETLOCKING_BYCALLER);
229 : 256 : __fsetlocking (stderr, FSETLOCKING_BYCALLER);
230 : :
231 : : /* Set locale. */
232 : 256 : setlocale (LC_ALL, "");
233 : :
234 : : /* Make sure the message catalog can be found. */
235 : 256 : bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
236 : :
237 : : /* Initialize the message catalog. */
238 : 256 : textdomain (PACKAGE_TARNAME);
239 : :
240 : : /* Parse and process arguments. */
241 [ + - ]: 256 : if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
242 : : return EXIT_FAILURE;
243 : :
244 [ + + - + ]: 256 : if (reloc_debug && debug_fname == NULL)
245 : 0 : error_exit (0, _("--reloc-debug-sections used without -f"));
246 : :
247 [ + + ]: 256 : if (reloc_debug_only &&
248 [ + - + - ]: 34 : (debug_fname != NULL || remove_secs != NULL
249 [ + - - + ]: 34 : || 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 : 256 : elf_version (EV_CURRENT);
255 : :
256 [ + + ]: 256 : if (remaining == argc)
257 : : /* The user didn't specify a name so we use a.out. */
258 : 10 : 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 [ + + + + ]: 246 : if ((output_fname != NULL || debug_fname != NULL)
264 [ - + ]: 184 : && 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 : 246 : do
269 : 246 : result |= process_file (argv[remaining]);
270 [ - + ]: 246 : while (++remaining < argc);
271 : : }
272 : :
273 : 256 : free_patterns ();
274 : 256 : return result;
275 : : }
276 : :
277 : :
278 : : /* Handle program arguments. */
279 : : static error_t
280 : 1770 : parse_opt (int key, char *arg, struct argp_state *state)
281 : : {
282 [ + + - + : 1770 : switch (key)
- + + + +
+ + - - +
+ ]
283 : : {
284 : 148 : case 'f':
285 [ - + ]: 148 : if (debug_fname != NULL)
286 : : {
287 : 0 : error (0, 0, _("-f option specified twice"));
288 : 0 : return EINVAL;
289 : : }
290 : 148 : debug_fname = arg;
291 : 148 : break;
292 : :
293 : 12 : case 'F':
294 [ - + ]: 12 : if (debug_fname_embed != NULL)
295 : : {
296 : 0 : error (0, 0, _("-F option specified twice"));
297 : 0 : return EINVAL;
298 : : }
299 : 12 : debug_fname_embed = arg;
300 : 12 : break;
301 : :
302 : 168 : case 'o':
303 [ - + ]: 168 : if (output_fname != NULL)
304 : : {
305 : 0 : error (0, 0, _("-o option specified twice"));
306 : 0 : return EINVAL;
307 : : }
308 : 168 : output_fname = arg;
309 : 168 : break;
310 : :
311 : 0 : case 'p':
312 : 0 : preserve_dates = true;
313 : 0 : break;
314 : :
315 : 34 : case OPT_RELOC_DEBUG:
316 : 34 : reloc_debug = true;
317 : 34 : break;
318 : :
319 : 34 : case OPT_RELOC_DEBUG_ONLY:
320 : 34 : reloc_debug_only = true;
321 : 34 : break;
322 : :
323 : 2 : case OPT_REMOVE_COMMENT:
324 : 2 : remove_comment = true;
325 : 2 : break;
326 : :
327 : 8 : case 'R':
328 [ - + ]: 8 : if (fnmatch (arg, ".comment", FNM_EXTMATCH) == 0)
329 : 0 : remove_comment = true;
330 : 8 : add_pattern (&remove_secs, arg);
331 : 8 : break;
332 : :
333 : 12 : case OPT_KEEP_SECTION:
334 : 12 : add_pattern (&keep_secs, arg);
335 : 12 : break;
336 : :
337 : 72 : case 'g':
338 : : case 'd':
339 : : case 'S':
340 : 72 : remove_debug = true;
341 : 72 : 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 : 256 : case ARGP_KEY_SUCCESS:
355 [ + + ]: 256 : if (remove_comment == true
356 [ + - ]: 2 : && 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 : 139636 : secndx_name (Elf *elf, size_t ndx)
372 : : {
373 : 139636 : size_t shstrndx;
374 : 139636 : GElf_Shdr mem;
375 : 139636 : Elf_Scn *sec = elf_getscn (elf, ndx);
376 : 139636 : GElf_Shdr *shdr = gelf_getshdr (sec, &mem);
377 [ + - - + ]: 139636 : if (shdr == NULL || elf_getshdrstrndx (elf, &shstrndx) < 0)
378 : 0 : return "???";
379 [ - + ]: 139636 : 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 : 300 : get_xndxdata (Elf *elf, Elf_Scn *symscn)
385 : : {
386 : 300 : Elf_Data *xndxdata = NULL;
387 : 300 : GElf_Shdr shdr_mem;
388 : 300 : GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
389 [ - + - + ]: 300 : if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
390 : : {
391 : 300 : size_t scnndx = elf_ndxscn (symscn);
392 : 300 : Elf_Scn *xndxscn = NULL;
393 [ + + ]: 9804 : while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
394 : : {
395 : 9504 : GElf_Shdr xndxshdr_mem;
396 : 9504 : GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
397 : :
398 [ + - ]: 9504 : if (xndxshdr != NULL
399 [ - + ]: 9504 : && 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 : 300 : 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 : 430 : update_shdrstrndx (Elf *elf, size_t shdrstrndx)
415 : : {
416 : 430 : GElf_Ehdr ehdr;
417 [ - + ]: 430 : if (gelf_getehdr (elf, &ehdr) == 0)
418 : : return 1;
419 : :
420 [ + + ]: 430 : if (shdrstrndx < SHN_LORESERVE)
421 : 424 : ehdr.e_shstrndx = shdrstrndx;
422 : : else
423 : : {
424 : 6 : ehdr.e_shstrndx = SHN_XINDEX;
425 : 6 : Elf_Scn *scn0 = elf_getscn (elf, 0);
426 : 6 : GElf_Shdr shdr0_mem;
427 : 6 : GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem);
428 [ + - ]: 6 : if (shdr0 == NULL)
429 : 0 : return 1;
430 : :
431 : 6 : shdr0->sh_link = shdrstrndx;
432 [ + - ]: 6 : if (gelf_update_shdr (scn0, shdr0) == 0)
433 : : return 1;
434 : : }
435 : :
436 [ - + ]: 430 : 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 : 118272 : 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 : 118272 : size_t size;
456 : :
457 : : #define DO_TYPE(NAME, Name) GElf_##Name Name;
458 : 118272 : union { TYPES; } tmpbuf;
459 : : #undef DO_TYPE
460 : :
461 [ - - + + : 118272 : 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 : 118272 : TYPES;
469 : : #undef DO_TYPE
470 : : default:
471 : : return false;
472 : : }
473 : :
474 [ + - ]: 118272 : if (offset > tdata->d_size
475 [ - + ]: 118272 : || 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 [ + + + + ]: 118272 : if (addend == 0 && sym->st_value == 0)
489 : : return true;
490 : :
491 : 105128 : Elf_Data tmpdata =
492 : : {
493 : : .d_type = type,
494 : : .d_buf = &tmpbuf,
495 : : .d_size = size,
496 : : .d_version = EV_CURRENT,
497 : : };
498 : 105128 : Elf_Data rdata =
499 : : {
500 : : .d_type = type,
501 : 105128 : .d_buf = tdata->d_buf + offset,
502 : : .d_size = size,
503 : : .d_version = EV_CURRENT,
504 : : };
505 : :
506 : 105128 : GElf_Addr value = sym->st_value;
507 [ + - ]: 105128 : if (is_rela)
508 : : {
509 : : /* For SHT_RELA sections we just take the
510 : : given addend and add it to the value. */
511 : 105128 : value += addend;
512 : : /* For ADD/SUB relocations we need to fetch the
513 : : current section contents. */
514 [ - + ]: 105128 : 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 [ - - + + : 105128 : 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 [ - - - - : 105128 : TYPES;
- + - + -
- - - ]
547 : : #undef DO_TYPE
548 : 0 : default:
549 : 0 : abort ();
550 : : }
551 : :
552 : : /* Now finally put in the new value. */
553 : 105128 : Elf_Data *s = gelf_xlatetof (elf, &rdata,
554 : : &tmpdata,
555 : : ei_data);
556 [ - + ]: 105128 : if (s == NULL)
557 : 0 : INTERNAL_ERROR (fname);
558 [ - + ]: 105128 : 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 : 64 : remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
568 : : const char *fname, size_t shstrndx)
569 : : {
570 : 64 : Elf_Scn *scn = NULL;
571 [ + + ]: 2040 : 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 : 1976 : GElf_Shdr shdr_mem;
577 : 1976 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
578 [ + - ]: 1976 : if (shdr != NULL
579 [ + + ]: 1976 : && (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 : 300 : Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
585 : 300 : GElf_Shdr tshdr_mem;
586 : 300 : GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
587 [ + - ]: 300 : if (tshdr == NULL
588 [ + - ]: 300 : || tshdr->sh_type == SHT_NOBITS
589 [ + - ]: 300 : || tshdr->sh_size == 0
590 [ - + ]: 300 : || (tshdr->sh_flags & SHF_ALLOC) != 0)
591 : 0 : continue;
592 : :
593 : 600 : const char *tname = elf_strptr (elf, shstrndx,
594 : 300 : tshdr->sh_name);
595 [ + - - + ]: 300 : if (! tname || ! ebl_debugscn_p (ebl, tname))
596 : 0 : continue;
597 : :
598 : : /* OK, lets relocate all trivial cross debug section
599 : : relocations. */
600 : 300 : Elf_Data *reldata = elf_getdata (scn, NULL);
601 [ + - - + ]: 300 : 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 : 300 : GElf_Chdr tchdr;
607 : 300 : int tcompress_type = 0;
608 : 300 : bool is_gnu_compressed = false;
609 [ + + ]: 300 : if (startswith (tname, ".zdebug"))
610 : : {
611 : 8 : is_gnu_compressed = true;
612 [ - + ]: 8 : if (elf_compress_gnu (tscn, 0, 0) != 1)
613 : 0 : INTERNAL_ERROR (fname);
614 : : }
615 : : else
616 : : {
617 [ + + ]: 292 : if (gelf_getchdr (tscn, &tchdr) != NULL)
618 : : {
619 : 28 : tcompress_type = tchdr.ch_type;
620 [ - + ]: 28 : if (elf_compress (tscn, 0, 0) != 1)
621 : 0 : INTERNAL_ERROR (fname);
622 : : }
623 : : }
624 : :
625 : 300 : Elf_Data *tdata = elf_getdata (tscn, NULL);
626 [ + - + - ]: 300 : if (tdata == NULL || tdata->d_buf == NULL
627 [ - + ]: 300 : || 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 : 300 : Elf64_Word symt = shdr->sh_link;
633 : 300 : Elf_Data *symdata, *xndxdata;
634 : 300 : Elf_Scn * symscn = elf_getscn (elf, symt);
635 : 300 : symdata = elf_getdata (symscn, NULL);
636 : 300 : xndxdata = get_xndxdata (elf, symscn);
637 [ - + ]: 300 : if (symdata == NULL)
638 : 0 : INTERNAL_ERROR (fname);
639 : :
640 [ - + ]: 300 : if (shdr->sh_entsize == 0)
641 : 0 : INTERNAL_ERROR (fname);
642 : :
643 : 300 : size_t nrels = shdr->sh_size / shdr->sh_entsize;
644 : 300 : size_t next = 0;
645 : 300 : const bool is_rela = (shdr->sh_type == SHT_RELA);
646 : 300 : const unsigned int ei_data = ehdr->e_ident[EI_DATA];
647 : :
648 [ + + ]: 139952 : for (size_t relidx = 0; relidx < nrels; ++relidx)
649 : 118272 : {
650 : 139652 : int rtype, symndx, offset, addend;
651 : 139652 : union { GElf_Rela rela; GElf_Rel rel; } mem;
652 : 139652 : void *rel_p; /* Pointer to either rela or rel above */
653 : :
654 [ + + ]: 139652 : if (is_rela)
655 : : {
656 : 126804 : GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
657 [ - + ]: 126804 : if (r == NULL)
658 : 0 : INTERNAL_ERROR (fname);
659 : 126804 : offset = r->r_offset;
660 : 126804 : addend = r->r_addend;
661 : 126804 : rtype = GELF_R_TYPE (r->r_info);
662 : 126804 : symndx = GELF_R_SYM (r->r_info);
663 : 126804 : rel_p = r;
664 : : }
665 : : else
666 : : {
667 : 12848 : GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
668 [ - + ]: 12848 : if (r == NULL)
669 : 0 : INTERNAL_ERROR (fname);
670 : 12848 : offset = r->r_offset;
671 : 12848 : addend = 0;
672 : 12848 : rtype = GELF_R_TYPE (r->r_info);
673 : 12848 : symndx = GELF_R_SYM (r->r_info);
674 : 12848 : rel_p = r;
675 : : }
676 : :
677 : : /* R_*_NONE relocs can always just be removed. */
678 [ - + ]: 139652 : if (rtype == 0)
679 : 118272 : continue;
680 : :
681 : : /* We only do simple absolute relocations. */
682 : 139652 : int addsub = 0;
683 : 139652 : Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
684 [ + + ]: 139652 : if (type == ELF_T_NUM)
685 : 16 : goto relocate_failed;
686 : :
687 : : /* And only for relocations against other debug sections. */
688 : 139636 : GElf_Sym sym_mem;
689 : 139636 : Elf32_Word xndx;
690 : 139636 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
691 : : symndx, &sym_mem,
692 : : &xndx);
693 [ - + ]: 139636 : if (sym == NULL)
694 : 0 : INTERNAL_ERROR (fname);
695 : 279272 : Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
696 [ + - ]: 139636 : ? xndx : sym->st_shndx);
697 : :
698 : 139636 : bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
699 : :
700 [ + + ]: 139636 : if (!dbg_scn)
701 : 21364 : goto relocate_failed;
702 : :
703 [ - + ]: 118272 : if (! relocate (elf, offset, addend,
704 : : tdata, ei_data, fname, is_rela,
705 : : sym, addsub, type))
706 : 0 : goto relocate_failed;
707 : :
708 : 118272 : continue; /* Next */
709 : :
710 : 21380 : relocate_failed:
711 [ + + ]: 21380 : if (relidx != next)
712 : : {
713 : 15496 : int updated;
714 [ + + ]: 15496 : if (is_rela)
715 : 15432 : updated = gelf_update_rela (reldata, next, rel_p);
716 : : else
717 : 64 : updated = gelf_update_rel (reldata, next, rel_p);
718 [ - + ]: 15496 : if (updated == 0)
719 : 0 : INTERNAL_ERROR (fname);
720 : : }
721 : 21380 : ++next;
722 : : }
723 : :
724 : 300 : nrels = next;
725 : 300 : shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
726 [ - + ]: 300 : if (gelf_update_shdr (scn, shdr) == 0)
727 : 0 : INTERNAL_ERROR (fname);
728 : :
729 [ + + ]: 300 : if (is_gnu_compressed)
730 : : {
731 [ - + ]: 8 : if (elf_compress_gnu (tscn, 1, ELF_CHF_FORCE) != 1)
732 : 0 : INTERNAL_ERROR (fname);
733 : : }
734 [ + + ]: 292 : else if (tcompress_type != 0)
735 : : {
736 [ - + ]: 28 : if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
737 : 300 : INTERNAL_ERROR (fname);
738 : : }
739 : : }
740 : : }
741 : 64 : }
742 : :
743 : : static int
744 : 256 : 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 : 256 : struct stat pre_st;
750 : 256 : struct timespec tv[2];
751 : 256 : again:
752 [ - + ]: 256 : 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 [ + + ]: 256 : int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
768 [ - + ]: 256 : 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 : 256 : struct stat st;
778 [ - + ]: 256 : 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 [ - + ]: 256 : 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 [ + + ]: 424 : Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
794 : : NULL);
795 : 256 : int result;
796 [ + - - ]: 256 : switch (elf_kind (elf))
797 : : {
798 : 256 : case ELF_K_ELF:
799 : 512 : result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
800 [ + - ]: 256 : preserve_dates ? tv : NULL);
801 : 256 : 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 [ - + ]: 256 : if (unlikely (elf_end (elf) != 0))
833 : 0 : INTERNAL_ERROR (fname);
834 : :
835 : 256 : close (fd);
836 : :
837 : 256 : return result;
838 : : }
839 : :
840 : : /* Processing for --reloc-debug-sections-only. */
841 : : static int
842 : 32 : 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 [ - + ]: 32 : 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 [ + + ]: 1020 : while ((scn = elf_nextscn (elf, scn)) != NULL)
858 : : {
859 : : /* Get the header. */
860 : 988 : GElf_Shdr shdr;
861 [ - + ]: 988 : 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 : 988 : Elf_Scn *new_scn = elf_newscn (new_elf);
869 [ - + ]: 988 : 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 [ - + ]: 988 : 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 [ + + ]: 1976 : while ((data = elf_getdata (scn, data)) != NULL)
884 : : {
885 : 988 : Elf_Data *new_data = elf_newdata (new_scn);
886 [ - + ]: 988 : 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 : 988 : *new_data = *data;
893 : : }
894 : :
895 : : /* Record last offset of allocated section. */
896 [ + + ]: 988 : if ((shdr.sh_flags & SHF_ALLOC) != 0)
897 : : {
898 : 624 : GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
899 [ + + ]: 312 : ? shdr.sh_size : 0);
900 : 312 : if (lastoffset < shdr.sh_offset + filesz)
901 : 988 : 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 [ - + ]: 32 : 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 : 32 : 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 : 32 : scn = NULL;
919 [ + + ]: 1020 : while ((scn = elf_nextscn (new_elf, scn)) != NULL)
920 : : {
921 : : /* Get the header. */
922 : 988 : GElf_Shdr shdr;
923 [ - + ]: 988 : 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 [ + + ]: 988 : if ((shdr.sh_flags & SHF_ALLOC) == 0)
931 : : {
932 : 676 : shdr.sh_offset = ((lastoffset + shdr.sh_addralign - 1)
933 : 676 : & ~((GElf_Off) (shdr.sh_addralign - 1)));
934 [ - + ]: 676 : 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 : 1352 : GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
941 [ + + ]: 676 : ? shdr.sh_size : 0);
942 : 676 : lastoffset = shdr.sh_offset + filesz;
943 : 676 : *last_offset = shdr.sh_offset;
944 : 676 : *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 : 24 : update_section_size (Elf_Scn *scn,
956 : : const Elf_Data *newdata,
957 : : Elf *debugelf,
958 : : size_t cnt,
959 : : const char *fname)
960 : : {
961 : 24 : GElf_Shdr shdr_mem;
962 : 24 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
963 : 24 : shdr->sh_size = newdata->d_size;
964 [ - + ]: 24 : if (gelf_update_shdr (scn, shdr) == 0)
965 : 0 : INTERNAL_ERROR (fname);
966 [ + + ]: 24 : if (debugelf != NULL)
967 : : {
968 : : /* libelf will use d_size to set sh_size. */
969 : 4 : Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
970 : : cnt), NULL);
971 [ - + ]: 4 : if (debugdata == NULL)
972 : 0 : INTERNAL_ERROR (fname);
973 : 4 : debugdata->d_size = newdata->d_size;
974 : : }
975 : 24 : }
976 : :
977 : : /* Maximum size of array allocated on stack. */
978 : : #define MAX_STACK_ALLOC (400 * 1024)
979 : :
980 : : static int
981 : 256 : handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
982 : : mode_t mode, struct timespec tvp[2])
983 : : {
984 [ - + ]: 256 : size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
985 : 256 : size_t fname_len = strlen (fname) + 1;
986 : 256 : char *fullname = alloca (prefix_len + 1 + fname_len);
987 : 256 : char *cp = fullname;
988 : 256 : Elf *debugelf = NULL;
989 : 256 : tmp_debug_fname = NULL;
990 : 256 : int result = 0;
991 : 256 : size_t shdridx = 0;
992 : 256 : GElf_Off lastsec_offset = 0;
993 : 256 : Elf64_Xword lastsec_size = 0;
994 : 256 : size_t shstrndx;
995 : 256 : 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 : 256 : } *shdr_info = NULL;
1012 : 256 : Elf_Scn *scn;
1013 : 256 : size_t cnt;
1014 : 256 : size_t idx;
1015 : 256 : bool changes;
1016 : 256 : GElf_Ehdr newehdr_mem;
1017 : 256 : GElf_Ehdr *newehdr;
1018 : 256 : GElf_Ehdr debugehdr_mem;
1019 : 256 : GElf_Ehdr *debugehdr;
1020 : 256 : Dwelf_Strtab *shst = NULL;
1021 : 256 : Elf_Data debuglink_crc_data;
1022 : 256 : bool any_symtab_changes = false;
1023 : 256 : Elf_Data *shstrtab_data = NULL;
1024 : 256 : void *debuglink_buf = NULL;
1025 : :
1026 : : /* Create the full name of the file. */
1027 [ - + ]: 256 : if (prefix != NULL)
1028 : : {
1029 : 0 : cp = mempcpy (cp, prefix, prefix_len);
1030 : 0 : *cp++ = ':';
1031 : : }
1032 [ + + ]: 256 : memcpy (cp, fname, fname_len);
1033 : :
1034 : : /* If we are not replacing the input file open a new file here. */
1035 [ + + ]: 256 : if (output_fname != NULL)
1036 : : {
1037 : 168 : fd = open (output_fname, O_RDWR | O_CREAT, mode);
1038 [ - + ]: 168 : if (unlikely (fd == -1))
1039 : : {
1040 : 0 : error (0, errno, _("cannot open '%s'"), output_fname);
1041 : 0 : return 1;
1042 : : }
1043 : : }
1044 : :
1045 : 256 : 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 : 256 : Ebl *ebl = NULL;
1052 [ + + + + : 256 : if (remove_debug || reloc_debug || reloc_debug_only)
+ + ]
1053 : : {
1054 : 140 : ebl = ebl_openbackend (elf);
1055 [ - + ]: 140 : 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 [ + + ]: 256 : 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 : 148 : size_t debug_fname_len = strlen (debug_fname);
1070 : 148 : tmp_debug_fname = xmalloc (debug_fname_len + sizeof (".XXXXXX"));
1071 : 148 : strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
1072 : : ".XXXXXX");
1073 : :
1074 : 148 : debug_fd = mkstemp (tmp_debug_fname);
1075 [ - + ]: 148 : 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 : 256 : GElf_Ehdr ehdr_mem;
1085 : 256 : GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
1086 [ - + ]: 256 : if (ehdr == NULL)
1087 : 0 : INTERNAL_ERROR (fname);
1088 : :
1089 : : /* Get the section header string table index. */
1090 [ - + ]: 256 : 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 : 256 : size_t phnum;
1098 [ - + ]: 256 : 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 : 256 : Elf *newelf;
1108 [ + + ]: 256 : if (output_fname != NULL)
1109 : 168 : newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
1110 : : else
1111 : 88 : newelf = elf_clone (elf, ELF_C_EMPTY);
1112 : :
1113 [ - + ]: 256 : 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 [ + + ]: 256 : if (phnum > 0)
1122 : : {
1123 [ - + ]: 130 : 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 [ + + ]: 1256 : for (cnt = 0; cnt < phnum; ++cnt)
1131 : : {
1132 : 1126 : GElf_Phdr phdr_mem;
1133 : 1126 : GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
1134 [ + - ]: 1126 : if (phdr == NULL
1135 [ - + ]: 1126 : || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
1136 : 1126 : INTERNAL_ERROR (fname);
1137 : : }
1138 : : }
1139 : :
1140 [ + + ]: 256 : if (reloc_debug_only)
1141 : : {
1142 [ + + ]: 34 : if (ehdr->e_type != ET_REL)
1143 : : {
1144 : : /* Only ET_REL files can have debug relocations to remove. */
1145 : 2 : error (0, 0, _("Ignoring --reloc-debug-sections-only for " \
1146 : : "non-ET_REL file '%s'"), fname);
1147 : 2 : goto fail_close;
1148 : : }
1149 [ - + ]: 32 : if (handle_debug_relocs (elf, ebl, newelf, ehdr, fname, shstrndx,
1150 : : &lastsec_offset, &lastsec_size) != 0)
1151 : : {
1152 : 0 : result = 1;
1153 : 0 : goto fail_close;
1154 : : }
1155 : 32 : idx = shstrndx;
1156 : 32 : goto done; /* Skip all actual stripping operations. */
1157 : : }
1158 : :
1159 [ + + ]: 222 : if (debug_fname != NULL)
1160 : : {
1161 : : /* Also create an ELF descriptor for the debug file */
1162 : 148 : debugelf = elf_begin (debug_fd, ELF_C_WRITE, NULL);
1163 [ - + ]: 148 : if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0))
1164 : : {
1165 : 0 : error (0, 0, _("cannot create new ehdr for file '%s': %s"),
1166 : : debug_fname, elf_errmsg (-1));
1167 : 0 : goto fail_close;
1168 : : }
1169 : :
1170 : : /* Copy over the old program header if needed. */
1171 [ + + ]: 148 : if (phnum > 0)
1172 : : {
1173 [ - + ]: 70 : if (unlikely (gelf_newphdr (debugelf, phnum) == 0))
1174 : : {
1175 : 0 : error (0, 0, _("cannot create new phdr for file '%s': %s"),
1176 : : debug_fname, elf_errmsg (-1));
1177 : 0 : goto fail_close;
1178 : : }
1179 : :
1180 [ + + ]: 732 : for (cnt = 0; cnt < phnum; ++cnt)
1181 : : {
1182 : 662 : GElf_Phdr phdr_mem;
1183 : 662 : GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
1184 [ + - ]: 662 : if (phdr == NULL
1185 [ - + ]: 662 : || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
1186 : 662 : INTERNAL_ERROR (fname);
1187 : : }
1188 : : }
1189 : : }
1190 : :
1191 : : /* Number of sections. */
1192 : 222 : size_t shnum;
1193 [ - + ]: 222 : if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
1194 : : {
1195 : 0 : error (0, 0, _("cannot determine number of sections: %s"),
1196 : : elf_errmsg (-1));
1197 : 0 : goto fail_close;
1198 : : }
1199 : :
1200 [ - + ]: 222 : if (shstrndx >= shnum)
1201 : 0 : goto illformed;
1202 : :
1203 : : #define elf_assert(test) do { if (!(test)) goto illformed; } while (0)
1204 : :
1205 : : /* Storage for section information. We leave room for two more
1206 : : entries since we unconditionally create a section header string
1207 : : table. Maybe some weird tool created an ELF file without one.
1208 : : The other one is used for the debug link section. */
1209 [ + + ]: 222 : if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1210 : 6 : shdr_info = xcalloc (shnum + 2, sizeof (struct shdr_info));
1211 : : else
1212 : : {
1213 : 216 : shdr_info = (struct shdr_info *) alloca ((shnum + 2)
1214 : : * sizeof (struct shdr_info));
1215 : 216 : memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
1216 : : }
1217 : :
1218 : : /* Track whether allocated sections all come before non-allocated ones. */
1219 : 222 : bool seen_allocated = false;
1220 : 222 : bool seen_unallocated = false;
1221 : 222 : bool mixed_allocated_unallocated = false;
1222 : :
1223 : : /* Prepare section information data structure. */
1224 : 222 : scn = NULL;
1225 : 222 : cnt = 1;
1226 [ + + ]: 400440 : while ((scn = elf_nextscn (elf, scn)) != NULL)
1227 : : {
1228 : : /* This should always be true (i.e., there should not be any
1229 : : holes in the numbering). */
1230 [ - + ]: 400218 : elf_assert (elf_ndxscn (scn) == cnt);
1231 : :
1232 : 400218 : shdr_info[cnt].scn = scn;
1233 : :
1234 : : /* Get the header. */
1235 [ - + ]: 400218 : if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
1236 : 0 : INTERNAL_ERROR (fname);
1237 : :
1238 : : /* Normally (in non-ET_REL files) we see all allocated sections first,
1239 : : then all non-allocated. */
1240 [ + + ]: 400218 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
1241 : : seen_unallocated = true;
1242 : : else
1243 : : {
1244 [ + + ]: 3764 : if (seen_unallocated && seen_allocated)
1245 : 646 : mixed_allocated_unallocated = true;
1246 : : seen_allocated = true;
1247 : : }
1248 : :
1249 : : /* Get the name of the section. */
1250 : 800436 : shdr_info[cnt].name = elf_strptr (elf, shstrndx,
1251 : 400218 : shdr_info[cnt].shdr.sh_name);
1252 [ - + ]: 400218 : if (shdr_info[cnt].name == NULL)
1253 : : {
1254 : 0 : illformed:
1255 : 0 : error (0, 0, _("illformed file '%s'"), fname);
1256 : 0 : goto fail_close;
1257 : : }
1258 : :
1259 : : /* Sanity check the user. */
1260 [ + + ]: 400218 : if (section_name_matches (remove_secs, shdr_info[cnt].name))
1261 : : {
1262 [ - + ]: 12 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
1263 : : {
1264 : 0 : error (0, 0,
1265 : 0 : _("Cannot remove allocated section '%s'"),
1266 : : shdr_info[cnt].name);
1267 : 0 : result = 1;
1268 : 0 : goto fail_close;
1269 : : }
1270 : :
1271 [ - + ]: 12 : if (section_name_matches (keep_secs, shdr_info[cnt].name))
1272 : : {
1273 : 0 : error (0, 0,
1274 : 0 : _("Cannot both keep and remove section '%s'"),
1275 : : shdr_info[cnt].name);
1276 : 0 : result = 1;
1277 : 0 : goto fail_close;
1278 : : }
1279 : : }
1280 : :
1281 : : /* Mark them as present but not yet investigated. */
1282 : 400218 : shdr_info[cnt].idx = 1;
1283 : :
1284 : : /* Remember the shdr.sh_link value. */
1285 : 400218 : shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
1286 [ - + ]: 400218 : if (shdr_info[cnt].old_sh_link >= shnum)
1287 : 0 : goto illformed;
1288 : :
1289 : : /* Sections in files other than relocatable object files which
1290 : : not loaded can be freely moved by us. In theory we can also
1291 : : freely move around allocated nobits sections. But we don't
1292 : : to keep the layout of all allocated sections as similar as
1293 : : possible to the original file. In relocatable object files
1294 : : everything can be moved. */
1295 [ + + ]: 400218 : if (phnum == 0
1296 [ + + ]: 397466 : || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
1297 : 397260 : shdr_info[cnt].shdr.sh_offset = 0;
1298 : :
1299 : : /* If this is an extended section index table store an
1300 : : appropriate reference. */
1301 [ - + ]: 400218 : if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
1302 : : {
1303 [ # # ]: 0 : elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
1304 : 0 : shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
1305 : : }
1306 [ + + ]: 400218 : else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
1307 : : {
1308 : : /* Cross-reference the sections contained in the section
1309 : : group. */
1310 : 20 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1311 [ + - ]: 20 : if (shdr_info[cnt].data == NULL
1312 [ - + ]: 20 : || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
1313 : 0 : INTERNAL_ERROR (fname);
1314 : :
1315 : : /* XXX Fix for unaligned access. */
1316 : 20 : Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1317 : 20 : size_t inner;
1318 : 20 : for (inner = 1;
1319 [ + + ]: 56 : inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1320 : 36 : ++inner)
1321 : : {
1322 [ + - ]: 36 : if (grpref[inner] < shnum)
1323 : 36 : shdr_info[grpref[inner]].group_idx = cnt;
1324 : : else
1325 : 0 : goto illformed;
1326 : : }
1327 : :
1328 [ + - + + : 20 : if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
+ + ]
1329 : : /* If the section group contains only one element and this
1330 : : is n COMDAT section we can drop it right away. */
1331 : 4 : shdr_info[cnt].idx = 0;
1332 : : else
1333 : 16 : shdr_info[cnt].group_cnt = inner - 1;
1334 : : }
1335 [ + + ]: 400198 : else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
1336 : : {
1337 [ - + ]: 126 : elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
1338 : 126 : shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
1339 : : }
1340 : :
1341 : : /* If this section is part of a group make sure it is not
1342 : : discarded right away. */
1343 [ + + ]: 400218 : if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
1344 : : {
1345 [ - + ]: 36 : elf_assert (shdr_info[cnt].group_idx != 0);
1346 : :
1347 [ + + ]: 36 : if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
1348 : : {
1349 : : /* The section group section might be removed.
1350 : : Don't remove the SHF_GROUP flag. The section is
1351 : : either also removed, in which case the flag doesn't matter.
1352 : : Or it moves with the group into the debug file, then
1353 : : it will be reconnected with the new group and should
1354 : : still have the flag set. */
1355 : 4 : shdr_info[cnt].group_idx = 0;
1356 : : }
1357 : : }
1358 : :
1359 : : /* Increment the counter. */
1360 : 400218 : ++cnt;
1361 : : }
1362 : :
1363 : : /* Now determine which sections can go away. The general rule is that
1364 : : all sections which are not used at runtime are stripped out. But
1365 : : there are a few exceptions:
1366 : :
1367 : : - special sections named ".comment" and ".note" are kept
1368 : : - OS or architecture specific sections are kept since we might not
1369 : : know how to handle them
1370 : : - if a section is referred to from a section which is not removed
1371 : : in the sh_link or sh_info element it cannot be removed either
1372 : : - the user might have explicitly said to remove or keep a section
1373 : : */
1374 [ + + ]: 400440 : for (cnt = 1; cnt < shnum; ++cnt)
1375 : : /* Check whether the section can be removed. Since we will create
1376 : : a new .shstrtab assume it will be removed too. */
1377 [ - + - - ]: 400218 : if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
1378 : 400218 : : (ebl_section_strip_p (ebl, &shdr_info[cnt].shdr,
1379 : 400218 : shdr_info[cnt].name, remove_comment,
1380 : : remove_debug)
1381 [ + + ]: 135312 : || cnt == shstrndx
1382 [ + + + + ]: 535458 : || section_name_matches (remove_secs, shdr_info[cnt].name)))
1383 : : {
1384 : : /* The user might want to explicitly keep this one. */
1385 [ + + ]: 264990 : if (section_name_matches (keep_secs, shdr_info[cnt].name))
1386 : 12 : continue;
1387 : :
1388 : : /* For now assume this section will be removed. */
1389 : 264978 : shdr_info[cnt].idx = 0;
1390 : :
1391 : 264978 : idx = shdr_info[cnt].group_idx;
1392 [ + + ]: 264980 : while (idx != 0)
1393 : : {
1394 : : /* The section group data is already loaded. */
1395 [ + - + - : 10 : elf_assert (shdr_info[idx].data != NULL
- + ]
1396 : : && shdr_info[idx].data->d_buf != NULL
1397 : : && shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
1398 : :
1399 : : /* If the references section group is a normal section
1400 : : group and has one element remaining, or if it is an
1401 : : empty COMDAT section group it is removed. */
1402 : 10 : bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
1403 : 10 : & GRP_COMDAT) != 0;
1404 : :
1405 : 10 : --shdr_info[idx].group_cnt;
1406 [ + + - + ]: 10 : if ((!is_comdat && shdr_info[idx].group_cnt == 1)
1407 [ + - ]: 2 : || (is_comdat && shdr_info[idx].group_cnt == 0))
1408 : : {
1409 : 2 : shdr_info[idx].idx = 0;
1410 : : /* Continue recursively. */
1411 : 2 : idx = shdr_info[idx].group_idx;
1412 : : }
1413 : : else
1414 : : break;
1415 : : }
1416 : : }
1417 : :
1418 : : /* Mark the SHT_NULL section as handled. */
1419 : 222 : shdr_info[0].idx = 2;
1420 : :
1421 : :
1422 : : /* Handle exceptions: section groups and cross-references. We might
1423 : : have to repeat this a few times since the resetting of the flag
1424 : : might propagate. */
1425 : 222 : do
1426 : : {
1427 : 222 : changes = false;
1428 : :
1429 [ + + ]: 400440 : for (cnt = 1; cnt < shnum; ++cnt)
1430 : : {
1431 [ + + ]: 400218 : if (shdr_info[cnt].idx == 0)
1432 : : {
1433 : : /* If a relocation section is marked as being removed make
1434 : : sure the section it is relocating is removed, too. */
1435 : 264802 : if (shdr_info[cnt].shdr.sh_type == SHT_REL
1436 [ + + ]: 264802 : || shdr_info[cnt].shdr.sh_type == SHT_RELA)
1437 : : {
1438 [ - + ]: 780 : if (shdr_info[cnt].shdr.sh_info >= shnum)
1439 : 0 : goto illformed;
1440 [ + + ]: 780 : else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
1441 : 344 : shdr_info[cnt].idx = 1;
1442 : : }
1443 : :
1444 : : /* If a group section is marked as being removed make
1445 : : sure all the sections it contains are being removed, too. */
1446 [ + + ]: 264802 : if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1447 : : {
1448 : 20 : Elf32_Word *grpref;
1449 : 20 : grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1450 : 20 : for (size_t in = 1;
1451 [ + + ]: 22 : in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1452 : 2 : ++in)
1453 [ + - ]: 20 : if (grpref[in] < shnum)
1454 : : {
1455 [ + + ]: 20 : if (shdr_info[grpref[in]].idx != 0)
1456 : : {
1457 : 18 : shdr_info[cnt].idx = 1;
1458 : 18 : break;
1459 : : }
1460 : : }
1461 : : else
1462 : 0 : goto illformed;
1463 : : }
1464 : : }
1465 : :
1466 [ + + ]: 400218 : if (shdr_info[cnt].idx == 1)
1467 : : {
1468 : : /* The content of symbol tables we don't remove must not
1469 : : reference any section which we do remove. Otherwise
1470 : : we cannot remove the section. */
1471 [ + + ]: 135778 : if (debug_fname != NULL
1472 [ + + ]: 134174 : && shdr_info[cnt].debug_data == NULL
1473 : 134010 : && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1474 [ + + ]: 134010 : || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
1475 : : {
1476 : : /* Make sure the data is loaded. */
1477 [ + - ]: 102 : if (shdr_info[cnt].data == NULL)
1478 : : {
1479 : 102 : shdr_info[cnt].data
1480 : 102 : = elf_getdata (shdr_info[cnt].scn, NULL);
1481 [ - + ]: 102 : if (shdr_info[cnt].data == NULL)
1482 : 0 : INTERNAL_ERROR (fname);
1483 : : }
1484 : 102 : Elf_Data *symdata = shdr_info[cnt].data;
1485 : :
1486 : : /* If there is an extended section index table load it
1487 : : as well. */
1488 [ - + ]: 102 : if (shdr_info[cnt].symtab_idx != 0
1489 [ # # ]: 0 : && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
1490 : : {
1491 [ # # ]: 0 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
1492 : :
1493 : 0 : shdr_info[shdr_info[cnt].symtab_idx].data
1494 : 0 : = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1495 : : NULL);
1496 [ # # ]: 0 : if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
1497 : 0 : INTERNAL_ERROR (fname);
1498 : : }
1499 : 102 : Elf_Data *xndxdata
1500 : 102 : = shdr_info[shdr_info[cnt].symtab_idx].data;
1501 : :
1502 : : /* Go through all symbols and make sure the section they
1503 : : reference is not removed. */
1504 : 102 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1505 : :
1506 : 102 : for (size_t inner = 0;
1507 [ + + ]: 3112 : inner < shdr_info[cnt].data->d_size / elsize;
1508 : 3010 : ++inner)
1509 : : {
1510 : 3010 : GElf_Sym sym_mem;
1511 : 3010 : Elf32_Word xndx;
1512 : 3010 : GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1513 : : inner, &sym_mem,
1514 : : &xndx);
1515 [ - + ]: 3010 : if (sym == NULL)
1516 : 0 : INTERNAL_ERROR (fname);
1517 : :
1518 : 3010 : size_t scnidx = sym->st_shndx;
1519 [ + + + + ]: 3010 : if (scnidx == SHN_UNDEF || scnidx >= shnum
1520 : 1564 : || (scnidx >= SHN_LORESERVE
1521 : : && scnidx <= SHN_HIRESERVE
1522 [ + + ]: 1564 : && scnidx != SHN_XINDEX)
1523 : : /* Don't count in the section symbols. */
1524 [ + + ]: 1542 : || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
1525 : : /* This is no section index, leave it alone. */
1526 : 1860 : continue;
1527 [ - + ]: 1150 : else if (scnidx == SHN_XINDEX)
1528 : 0 : scnidx = xndx;
1529 : :
1530 [ - + ]: 1150 : if (scnidx >= shnum)
1531 : 0 : goto illformed;
1532 : :
1533 [ + + ]: 1150 : if (shdr_info[scnidx].idx == 0)
1534 : : /* This symbol table has a real symbol in
1535 : : a discarded section. So preserve the
1536 : : original table in the debug file. Unless
1537 : : it is a redundant data marker to a debug
1538 : : (data only) section. */
1539 [ + - - + ]: 16 : if (! (ebl_section_strip_p (ebl,
1540 : 8 : &shdr_info[scnidx].shdr,
1541 : : shdr_info[scnidx].name,
1542 : : remove_comment,
1543 : : remove_debug)
1544 : 8 : && ebl_data_marker_symbol (ebl, sym,
1545 : 8 : elf_strptr (elf,
1546 : 8 : shdr_info[cnt].shdr.sh_link,
1547 : 8 : sym->st_name))))
1548 : 0 : shdr_info[cnt].debug_data = symdata;
1549 : : }
1550 : : }
1551 : :
1552 : : /* Cross referencing happens:
1553 : : - for the cases the ELF specification says. That are
1554 : : + SHT_DYNAMIC in sh_link to string table
1555 : : + SHT_HASH in sh_link to symbol table
1556 : : + SHT_REL and SHT_RELA in sh_link to symbol table
1557 : : + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
1558 : : + SHT_GROUP in sh_link to symbol table
1559 : : + SHT_SYMTAB_SHNDX in sh_link to symbol table
1560 : : Other (OS or architecture-specific) sections might as
1561 : : well use this field so we process it unconditionally.
1562 : : - references inside section groups
1563 : : - specially marked references in sh_info if the SHF_INFO_LINK
1564 : : flag is set
1565 : : */
1566 : :
1567 [ + + ]: 135778 : if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
1568 : : {
1569 : 176 : shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
1570 : 176 : changes |= shdr_info[cnt].shdr.sh_link < cnt;
1571 : : }
1572 : :
1573 : : /* Handle references through sh_info. */
1574 [ + + - + ]: 135778 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1575 : : {
1576 [ - + ]: 572 : if (shdr_info[cnt].shdr.sh_info >= shnum)
1577 : 0 : goto illformed;
1578 [ - + ]: 572 : else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
1579 : : {
1580 : 0 : shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
1581 : 0 : changes |= shdr_info[cnt].shdr.sh_info < cnt;
1582 : : }
1583 : : }
1584 : :
1585 : : /* Mark the section as investigated. */
1586 : 135778 : shdr_info[cnt].idx = 2;
1587 : : }
1588 : :
1589 [ + + ]: 400218 : if (debug_fname != NULL
1590 [ + + + + ]: 266830 : && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
1591 : : {
1592 : : /* This section is being preserved in the debug file.
1593 : : Sections it refers to must be preserved there too.
1594 : :
1595 : : In this pass we mark sections to be preserved in both
1596 : : files by setting the .debug_data pointer to the original
1597 : : file's .data pointer. Below, we'll copy the section
1598 : : contents. */
1599 : 132820 : size_t shdr_indices[2] = { shdr_info[cnt].shdr.sh_link, 0 };
1600 : 132820 : int n = 1;
1601 : :
1602 [ + + - + ]: 132820 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1603 : : {
1604 : 366 : shdr_indices[1] = shdr_info[cnt].shdr.sh_info;
1605 : 366 : n++;
1606 : : }
1607 : :
1608 [ + + ]: 266006 : for (int j = 0; j < n; j++)
1609 : : {
1610 : 133186 : size_t i = shdr_indices[j];
1611 [ + + + - : 133186 : if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
+ + ]
1612 [ + + ]: 454 : && shdr_info[i].debug_data == NULL)
1613 : : {
1614 [ + - ]: 164 : if (shdr_info[i].data == NULL)
1615 : 164 : shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
1616 [ - + ]: 164 : if (shdr_info[i].data == NULL)
1617 : 0 : INTERNAL_ERROR (fname);
1618 : :
1619 : 164 : shdr_info[i].debug_data = shdr_info[i].data;
1620 : 164 : changes |= i < cnt;
1621 : : }
1622 : : }
1623 : : }
1624 : : }
1625 : : }
1626 [ - + ]: 222 : while (changes);
1627 : :
1628 : : /* Copy the removed sections to the debug output file.
1629 : : The ones that are not removed in the stripped file are SHT_NOBITS. */
1630 [ + + ]: 222 : if (debug_fname != NULL)
1631 : : {
1632 [ + + ]: 266978 : for (cnt = 1; cnt < shnum; ++cnt)
1633 : : {
1634 : 266830 : scn = elf_newscn (debugelf);
1635 [ - + ]: 266830 : if (scn == NULL)
1636 : : {
1637 : 0 : cleanup_debug ();
1638 : 0 : error_exit (0, _("while generating output file: %s"),
1639 : : elf_errmsg (-1));
1640 : : }
1641 : :
1642 : 533660 : bool discard_section = (shdr_info[cnt].idx > 0
1643 [ + + ]: 134174 : && shdr_info[cnt].debug_data == NULL
1644 [ + + ]: 134010 : && shdr_info[cnt].shdr.sh_type != SHT_NOTE
1645 [ + + ]: 133784 : && shdr_info[cnt].shdr.sh_type != SHT_GROUP
1646 [ + + - + ]: 400596 : && cnt != shstrndx);
1647 : :
1648 : : /* Set the section header in the new file. */
1649 : 266830 : GElf_Shdr debugshdr = shdr_info[cnt].shdr;
1650 [ + + ]: 266830 : if (discard_section)
1651 : 133766 : debugshdr.sh_type = SHT_NOBITS;
1652 : :
1653 [ - + ]: 266830 : if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
1654 : : /* There cannot be any overflows. */
1655 : 0 : INTERNAL_ERROR (fname);
1656 : :
1657 : : /* Get the data from the old file if necessary. */
1658 [ + + ]: 266830 : if (shdr_info[cnt].data == NULL)
1659 : : {
1660 : 266544 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1661 [ - + ]: 266544 : if (shdr_info[cnt].data == NULL)
1662 : 0 : INTERNAL_ERROR (fname);
1663 : : }
1664 : :
1665 : : /* Set the data. This is done by copying from the old file. */
1666 : 266830 : Elf_Data *debugdata = elf_newdata (scn);
1667 [ - + ]: 266830 : if (debugdata == NULL)
1668 : 0 : INTERNAL_ERROR (fname);
1669 : :
1670 : : /* Copy the structure. This data may be modified in place
1671 : : before we write out the file. */
1672 : 266830 : *debugdata = *shdr_info[cnt].data;
1673 [ + + ]: 266830 : if (discard_section)
1674 : 133766 : debugdata->d_buf = NULL;
1675 [ + + ]: 133064 : else if (shdr_info[cnt].debug_data != NULL
1676 [ + + ]: 132900 : || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1677 : : {
1678 : : /* Copy the original data before it gets modified. */
1679 : 184 : shdr_info[cnt].debug_data = debugdata;
1680 [ - + ]: 184 : if (debugdata->d_buf == NULL)
1681 : 0 : INTERNAL_ERROR (fname);
1682 : 184 : debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
1683 : : debugdata->d_buf, debugdata->d_size);
1684 : : }
1685 : : }
1686 : :
1687 : : /* Finish the ELF header. Fill in the fields not handled by
1688 : : libelf from the old file. */
1689 : 148 : debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
1690 [ - + ]: 148 : if (debugehdr == NULL)
1691 : 0 : INTERNAL_ERROR (fname);
1692 : :
1693 : 148 : memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1694 : 148 : debugehdr->e_type = ehdr->e_type;
1695 : 148 : debugehdr->e_machine = ehdr->e_machine;
1696 : 148 : debugehdr->e_version = ehdr->e_version;
1697 : 148 : debugehdr->e_entry = ehdr->e_entry;
1698 : 148 : debugehdr->e_flags = ehdr->e_flags;
1699 : :
1700 [ - + ]: 148 : if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
1701 : : {
1702 : 0 : error (0, 0, _("%s: error while updating ELF header: %s"),
1703 : : debug_fname, elf_errmsg (-1));
1704 : 0 : result = 1;
1705 : 0 : goto fail_close;
1706 : : }
1707 : :
1708 : 148 : size_t shdrstrndx;
1709 [ - + ]: 148 : if (elf_getshdrstrndx (elf, &shdrstrndx) < 0)
1710 : : {
1711 : 0 : error (0, 0, _("%s: error while getting shdrstrndx: %s"),
1712 : : fname, elf_errmsg (-1));
1713 : 0 : result = 1;
1714 : 0 : goto fail_close;
1715 : : }
1716 : :
1717 [ - + ]: 148 : if (update_shdrstrndx (debugelf, shdrstrndx) != 0)
1718 : : {
1719 : 0 : error (0, 0, _("%s: error updating shdrstrndx: %s"),
1720 : : debug_fname, elf_errmsg (-1));
1721 : 0 : result = 1;
1722 : 0 : goto fail_close;
1723 : : }
1724 : : }
1725 : :
1726 : : /* Although we always create a new section header string table we
1727 : : don't explicitly mark the existing one as unused. It can still
1728 : : be used through a symbol table section we are keeping. If not it
1729 : : will already be marked as unused. */
1730 : :
1731 : : /* We need a string table for the section headers. */
1732 : 222 : shst = dwelf_strtab_init (true);
1733 [ - + ]: 222 : if (shst == NULL)
1734 : : {
1735 : 0 : cleanup_debug ();
1736 [ # # ]: 0 : error_exit (errno, _("while preparing output for '%s'"),
1737 : : output_fname ?: fname);
1738 : : }
1739 : :
1740 : : /* Assign new section numbers. */
1741 : 222 : shdr_info[0].idx = 0;
1742 [ + + ]: 400440 : for (cnt = idx = 1; cnt < shnum; ++cnt)
1743 [ + + ]: 400218 : if (shdr_info[cnt].idx > 0)
1744 : : {
1745 : 135778 : shdr_info[cnt].idx = idx++;
1746 : :
1747 : : /* Create a new section. */
1748 : 135778 : shdr_info[cnt].newscn = elf_newscn (newelf);
1749 [ - + ]: 135778 : if (shdr_info[cnt].newscn == NULL)
1750 : : {
1751 : 0 : cleanup_debug ();
1752 : 0 : error_exit (0,
1753 : : _("while generating output file: %s"),
1754 : : elf_errmsg (-1));
1755 : : }
1756 : :
1757 [ - + ]: 135778 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1758 : :
1759 : : /* Add this name to the section header string table. */
1760 : 135778 : shdr_info[cnt].se = dwelf_strtab_add (shst, shdr_info[cnt].name);
1761 : : }
1762 : :
1763 : : /* Test whether we are doing anything at all. Either all removable
1764 : : sections are already gone. Or the only section we would remove is
1765 : : the .shstrtab section which we would add again. */
1766 [ + - ]: 222 : bool removing_sections = !(cnt == idx
1767 [ + + ]: 222 : || (cnt == idx + 1
1768 [ - + ]: 8 : && shdr_info[shstrndx].idx == 0));
1769 [ + + + + ]: 222 : if (output_fname == NULL && !removing_sections)
1770 : 4 : goto fail_close;
1771 : :
1772 : : /* Create the reference to the file with the debug info (if any). */
1773 [ + + + - : 218 : if (debug_fname != NULL && !remove_shdrs && removing_sections)
+ + ]
1774 : : {
1775 : : /* Add the section header string table section name. */
1776 : 144 : shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".gnu_debuglink", 15);
1777 : 144 : shdr_info[cnt].idx = idx++;
1778 : :
1779 : : /* Create the section header. */
1780 : 144 : shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
1781 : 144 : shdr_info[cnt].shdr.sh_flags = 0;
1782 : 144 : shdr_info[cnt].shdr.sh_addr = 0;
1783 : 144 : shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1784 : 144 : shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1785 : 144 : shdr_info[cnt].shdr.sh_entsize = 0;
1786 : 144 : shdr_info[cnt].shdr.sh_addralign = 4;
1787 : : /* We set the offset to zero here. Before we write the ELF file the
1788 : : field must have the correct value. This is done in the final
1789 : : loop over all section. Then we have all the information needed. */
1790 : 144 : shdr_info[cnt].shdr.sh_offset = 0;
1791 : :
1792 : : /* Create the section. */
1793 : 144 : shdr_info[cnt].newscn = elf_newscn (newelf);
1794 [ - + ]: 144 : if (shdr_info[cnt].newscn == NULL)
1795 : : {
1796 : 0 : cleanup_debug ();
1797 : 0 : error_exit (0, _("while create section header section: %s"),
1798 : : elf_errmsg (-1));
1799 : : }
1800 [ - + ]: 144 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1801 : :
1802 : 144 : shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
1803 [ - + ]: 144 : if (shdr_info[cnt].data == NULL)
1804 : : {
1805 : 0 : cleanup_debug ();
1806 : 0 : error_exit (0, _("cannot allocate section data: %s"),
1807 : : elf_errmsg (-1));
1808 : : }
1809 : :
1810 [ + + ]: 144 : const char *debug_basename = xbasename (debug_fname_embed ?: debug_fname);
1811 : 144 : off_t crc_offset = strlen (debug_basename) + 1;
1812 : : /* Align to 4 byte boundary */
1813 : 144 : crc_offset = ((crc_offset - 1) & ~3) + 4;
1814 : :
1815 : 144 : shdr_info[cnt].data->d_align = 4;
1816 : 144 : shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1817 : 144 : = crc_offset + 4;
1818 : 144 : debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1819 : 144 : shdr_info[cnt].data->d_buf = debuglink_buf;
1820 : :
1821 : 144 : strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1822 : :
1823 : : /* Cache this Elf_Data describing the CRC32 word in the section.
1824 : : We'll fill this in when we have written the debug file. */
1825 : 144 : debuglink_crc_data = *shdr_info[cnt].data;
1826 : 144 : debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1827 : 144 : + crc_offset);
1828 : 144 : debuglink_crc_data.d_size = 4;
1829 : :
1830 : : /* One more section done. */
1831 : 144 : ++cnt;
1832 : : }
1833 : :
1834 : : /* Index of the section header table in the shdr_info array. */
1835 : 218 : shdridx = cnt;
1836 : :
1837 : : /* Add the section header string table section name. */
1838 : 218 : shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".shstrtab", 10);
1839 : 218 : shdr_info[cnt].idx = idx;
1840 : :
1841 : : /* Create the section header. */
1842 : 218 : shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1843 : 218 : shdr_info[cnt].shdr.sh_flags = 0;
1844 : 218 : shdr_info[cnt].shdr.sh_addr = 0;
1845 : 218 : shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1846 : 218 : shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1847 : 218 : shdr_info[cnt].shdr.sh_entsize = 0;
1848 : : /* We set the offset to zero here. Before we write the ELF file the
1849 : : field must have the correct value. This is done in the final
1850 : : loop over all section. Then we have all the information needed. */
1851 : 218 : shdr_info[cnt].shdr.sh_offset = 0;
1852 : 218 : shdr_info[cnt].shdr.sh_addralign = 1;
1853 : :
1854 : : /* Create the section. */
1855 : 218 : shdr_info[cnt].newscn = elf_newscn (newelf);
1856 [ - + ]: 218 : if (shdr_info[cnt].newscn == NULL)
1857 : : {
1858 : 0 : cleanup_debug ();
1859 : 0 : error_exit (0, _("while create section header section: %s"),
1860 : : elf_errmsg (-1));
1861 : : }
1862 [ - + ]: 218 : elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1863 : :
1864 : : /* Finalize the string table and fill in the correct indices in the
1865 : : section headers. */
1866 : 218 : shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1867 [ - + ]: 218 : if (shstrtab_data == NULL)
1868 : : {
1869 : 0 : cleanup_debug ();
1870 : 0 : error_exit (0, _("while create section header string table: %s"),
1871 : : elf_errmsg (-1));
1872 : : }
1873 [ - + ]: 218 : if (dwelf_strtab_finalize (shst, shstrtab_data) == NULL)
1874 : : {
1875 : 0 : cleanup_debug ();
1876 : 0 : error_exit (0, _("no memory to create section header string table"));
1877 : : }
1878 : :
1879 : : /* We have to set the section size. */
1880 : 218 : shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1881 : :
1882 : : /* Update the section information. */
1883 : 218 : GElf_Off lastoffset = 0;
1884 [ + + ]: 400690 : for (cnt = 1; cnt <= shdridx; ++cnt)
1885 [ + + ]: 400472 : if (shdr_info[cnt].idx > 0)
1886 : : {
1887 : 136036 : Elf_Data *newdata;
1888 : :
1889 : 136036 : scn = elf_getscn (newelf, shdr_info[cnt].idx);
1890 [ - + ]: 136036 : elf_assert (scn != NULL);
1891 : :
1892 : : /* Update the name. */
1893 : 136036 : shdr_info[cnt].shdr.sh_name = dwelf_strent_off (shdr_info[cnt].se);
1894 : :
1895 : : /* Update the section header from the input file. Some fields
1896 : : might be section indices which now have to be adjusted. Keep
1897 : : the index to the "current" sh_link in case we need it to lookup
1898 : : symbol table names. */
1899 : 136036 : size_t sh_link = shdr_info[cnt].shdr.sh_link;
1900 [ + + ]: 136036 : if (shdr_info[cnt].shdr.sh_link != 0)
1901 : 1358 : shdr_info[cnt].shdr.sh_link =
1902 : 1358 : shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1903 : :
1904 [ + + ]: 136036 : if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1905 : : {
1906 [ + - - + ]: 18 : elf_assert (shdr_info[cnt].data != NULL
1907 : : && shdr_info[cnt].data->d_buf != NULL);
1908 : :
1909 : : Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1910 : : /* First word is the section group flag.
1911 : : Followed by section indexes, that need to be renumbered. */
1912 : : for (size_t inner = 1;
1913 [ + + ]: 52 : inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1914 : 34 : ++inner)
1915 [ + - ]: 34 : if (grpref[inner] < shnum)
1916 : 34 : grpref[inner] = shdr_info[grpref[inner]].idx;
1917 : : else
1918 : 0 : goto illformed;
1919 : : }
1920 : :
1921 : : /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
1922 [ + + - + ]: 136036 : if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1923 : 568 : shdr_info[cnt].shdr.sh_info =
1924 : 568 : shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1925 : :
1926 : : /* Get the data from the old file if necessary. We already
1927 : : created the data for the section header string table. */
1928 [ + + ]: 136036 : if (cnt < shnum)
1929 : : {
1930 [ + + ]: 135674 : if (shdr_info[cnt].data == NULL)
1931 : : {
1932 : 1552 : shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1933 [ - + ]: 1552 : if (shdr_info[cnt].data == NULL)
1934 : 0 : INTERNAL_ERROR (fname);
1935 : : }
1936 : :
1937 : : /* Set the data. This is done by copying from the old file. */
1938 : 135674 : newdata = elf_newdata (scn);
1939 [ - + ]: 135674 : if (newdata == NULL)
1940 : 0 : INTERNAL_ERROR (fname);
1941 : :
1942 : : /* Copy the structure. */
1943 : 135674 : *newdata = *shdr_info[cnt].data;
1944 : :
1945 : : /* We know the size. */
1946 : 135674 : shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1947 : :
1948 : : /* We have to adjust symbol tables. The st_shndx member might
1949 : : have to be updated. */
1950 : 135674 : if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1951 [ + + ]: 135674 : || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1952 : : {
1953 : 268 : Elf_Data *versiondata = NULL;
1954 : 268 : Elf_Data *shndxdata = NULL;
1955 : :
1956 : 268 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
1957 : :
1958 [ - + ]: 268 : if (shdr_info[cnt].symtab_idx != 0)
1959 : : {
1960 [ # # ]: 0 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1961 : : /* This section has extended section information.
1962 : : We have to modify that information, too. */
1963 : 0 : shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1964 : : NULL);
1965 : :
1966 [ # # # # : 0 : elf_assert (shndxdata != NULL
# # ]
1967 : : && shndxdata->d_buf != NULL
1968 : : && ((shndxdata->d_size / sizeof (Elf32_Word))
1969 : : >= shdr_info[cnt].data->d_size / elsize));
1970 : : }
1971 : :
1972 [ + + ]: 268 : if (shdr_info[cnt].version_idx != 0)
1973 : : {
1974 [ - + ]: 122 : elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1975 : : /* This section has associated version
1976 : : information. We have to modify that
1977 : : information, too. */
1978 : 122 : versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1979 : : NULL);
1980 : :
1981 [ + - + - : 122 : elf_assert (versiondata != NULL
- + ]
1982 : : && versiondata->d_buf != NULL
1983 : : && ((versiondata->d_size / sizeof (GElf_Versym))
1984 : : >= shdr_info[cnt].data->d_size / elsize));
1985 : : }
1986 : :
1987 : 268 : shdr_info[cnt].newsymidx
1988 : 268 : = xcalloc (shdr_info[cnt].data->d_size / elsize,
1989 : : sizeof (Elf32_Word));
1990 : :
1991 : 268 : bool last_was_local = true;
1992 : 268 : size_t destidx;
1993 : 268 : size_t inner;
1994 : 268 : for (destidx = inner = 1;
1995 [ + + ]: 39686 : inner < shdr_info[cnt].data->d_size / elsize;
1996 : 39418 : ++inner)
1997 : : {
1998 : 39418 : Elf32_Word sec;
1999 : 39418 : GElf_Sym sym_mem;
2000 : 39418 : Elf32_Word xshndx;
2001 : 39418 : GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
2002 : : shndxdata, inner,
2003 : : &sym_mem, &xshndx);
2004 [ - + ]: 39418 : if (sym == NULL)
2005 : 0 : INTERNAL_ERROR (fname);
2006 : :
2007 : 43726 : if (sym->st_shndx == SHN_UNDEF
2008 [ + + ]: 39418 : || (sym->st_shndx >= SHN_LORESERVE
2009 : : && sym->st_shndx != SHN_XINDEX))
2010 : : {
2011 : : /* This is no section index, leave it alone
2012 : : unless it is moved. */
2013 [ + + ]: 4308 : if (destidx != inner
2014 [ - + ]: 2816 : && gelf_update_symshndx (shdr_info[cnt].data,
2015 : : shndxdata,
2016 : : destidx, sym,
2017 : : xshndx) == 0)
2018 : 0 : INTERNAL_ERROR (fname);
2019 : :
2020 : 4308 : shdr_info[cnt].newsymidx[inner] = destidx++;
2021 : :
2022 [ + + ]: 4308 : if (last_was_local
2023 [ + + ]: 706 : && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
2024 : : {
2025 : 164 : last_was_local = false;
2026 : 164 : shdr_info[cnt].shdr.sh_info = destidx - 1;
2027 : : }
2028 : :
2029 : 4308 : continue;
2030 : : }
2031 : :
2032 : : /* Get the full section index, if necessary from the
2033 : : XINDEX table. */
2034 [ - + ]: 35110 : if (sym->st_shndx == SHN_XINDEX)
2035 [ # # # # ]: 0 : elf_assert (shndxdata != NULL
2036 : : && shndxdata->d_buf != NULL);
2037 : 70220 : size_t sidx = (sym->st_shndx != SHN_XINDEX
2038 [ + - ]: 35110 : ? sym->st_shndx : xshndx);
2039 [ - + ]: 35110 : elf_assert (sidx < shnum);
2040 : 35110 : sec = shdr_info[sidx].idx;
2041 : :
2042 [ + + ]: 35110 : if (sec != 0)
2043 : : {
2044 : 6378 : GElf_Section nshndx;
2045 : 6378 : Elf32_Word nxshndx;
2046 : :
2047 [ + - ]: 6378 : if (sec < SHN_LORESERVE)
2048 : : {
2049 : 6378 : nshndx = sec;
2050 : 6378 : nxshndx = 0;
2051 : : }
2052 : : else
2053 : : {
2054 : : nshndx = SHN_XINDEX;
2055 : : nxshndx = sec;
2056 : : }
2057 : :
2058 [ - + ]: 6378 : elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
2059 : :
2060 [ + + + + ]: 6378 : if ((inner != destidx || nshndx != sym->st_shndx
2061 [ - + - - ]: 4356 : || (shndxdata != NULL && nxshndx != xshndx))
2062 [ - + ]: 2022 : && (sym->st_shndx = nshndx,
2063 : 2022 : gelf_update_symshndx (shdr_info[cnt].data,
2064 : : shndxdata,
2065 : : destidx, sym,
2066 : : nxshndx) == 0))
2067 : 0 : INTERNAL_ERROR (fname);
2068 : :
2069 : 6378 : shdr_info[cnt].newsymidx[inner] = destidx++;
2070 : :
2071 [ + + ]: 6378 : if (last_was_local
2072 [ + + ]: 5244 : && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
2073 : : {
2074 : 104 : last_was_local = false;
2075 : 104 : shdr_info[cnt].shdr.sh_info = destidx - 1;
2076 : : }
2077 : : }
2078 [ + + ]: 28732 : else if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0
2079 [ - + ]: 96 : && GELF_ST_TYPE (sym->st_info) != STT_SECTION
2080 [ # # ]: 0 : && shdr_info[sidx].shdr.sh_type != SHT_GROUP)
2081 : : {
2082 : : /* Removing a real symbol from an allocated
2083 : : symbol table is hard and probably a
2084 : : mistake. Really removing it means
2085 : : rewriting the dynamic segment and hash
2086 : : sections. Just warn and set the symbol
2087 : : section to UNDEF. */
2088 : 0 : error (0, 0,
2089 : 0 : _("Cannot remove symbol [%zd] from allocated symbol table [%zd]"), inner, cnt);
2090 : 0 : sym->st_shndx = SHN_UNDEF;
2091 [ # # ]: 0 : if (gelf_update_sym (shdr_info[cnt].data, destidx,
2092 : : sym) == 0)
2093 : 0 : INTERNAL_ERROR (fname);
2094 : 0 : shdr_info[cnt].newsymidx[inner] = destidx++;
2095 : : }
2096 [ + + ]: 28732 : else if (debug_fname != NULL
2097 [ + + ]: 28376 : && shdr_info[cnt].debug_data == NULL)
2098 : : /* The symbol points to a section that is discarded
2099 : : but isn't preserved in the debug file. Check that
2100 : : this is a section or group signature symbol
2101 : : for a section which has been removed. Or a special
2102 : : data marker symbol to a debug section. */
2103 : : {
2104 [ + + - + : 35200 : elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
- - + - ]
2105 : : || ((shdr_info[sidx].shdr.sh_type
2106 : : == SHT_GROUP)
2107 : : && (shdr_info[sidx].shdr.sh_info
2108 : : == inner))
2109 : : || ebl_data_marker_symbol (ebl, sym,
2110 : : elf_strptr (elf, sh_link,
2111 : : sym->st_name)));
2112 : : }
2113 : : }
2114 : :
2115 [ + + ]: 268 : if (destidx != inner)
2116 : : {
2117 : : /* The size of the symbol table changed. */
2118 : 134 : shdr_info[cnt].shdr.sh_size = newdata->d_size
2119 : 134 : = destidx * elsize;
2120 : 134 : any_symtab_changes = true;
2121 : : }
2122 : : else
2123 : : {
2124 : : /* The symbol table didn't really change. */
2125 : 134 : free (shdr_info[cnt].newsymidx);
2126 : 134 : shdr_info[cnt].newsymidx = NULL;
2127 : : }
2128 : : }
2129 : : }
2130 : :
2131 : : /* If we have to, compute the offset of the section.
2132 : : If allocate and unallocated sections are mixed, we only update
2133 : : the allocated ones now. The unallocated ones come second. */
2134 [ + + ]: 136036 : if (! mixed_allocated_unallocated
2135 [ + + ]: 133054 : || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
2136 : : {
2137 [ + + ]: 4110 : if (shdr_info[cnt].shdr.sh_offset == 0)
2138 : 1252 : shdr_info[cnt].shdr.sh_offset
2139 : 1252 : = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
2140 : 1252 : & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
2141 : :
2142 : : /* Set the section header in the new file. */
2143 [ - + ]: 4110 : if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
2144 : : /* There cannot be any overflows. */
2145 : 0 : INTERNAL_ERROR (fname);
2146 : :
2147 : : /* Remember the last section written so far. */
2148 : 8220 : GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
2149 [ + + ]: 4110 : ? shdr_info[cnt].shdr.sh_size : 0);
2150 [ + + ]: 4110 : if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
2151 : 400472 : lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
2152 : : }
2153 : : }
2154 : :
2155 : : /* We might have to update the unallocated sections after we done the
2156 : : allocated ones. lastoffset is set to right after the last allocated
2157 : : section. */
2158 [ + + ]: 218 : if (mixed_allocated_unallocated)
2159 [ + + ]: 396584 : for (cnt = 1; cnt <= shdridx; ++cnt)
2160 [ + + ]: 396484 : if (shdr_info[cnt].idx > 0)
2161 : : {
2162 : 133054 : scn = elf_getscn (newelf, shdr_info[cnt].idx);
2163 [ + + ]: 133054 : if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
2164 : : {
2165 [ + - ]: 131926 : if (shdr_info[cnt].shdr.sh_offset == 0)
2166 : 131926 : shdr_info[cnt].shdr.sh_offset
2167 : 131926 : = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
2168 : 131926 : & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
2169 : :
2170 : : /* Set the section header in the new file. */
2171 [ - + ]: 131926 : if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
2172 : : /* There cannot be any overflows. */
2173 : 0 : INTERNAL_ERROR (fname);
2174 : :
2175 : : /* Remember the last section written so far. */
2176 : 263852 : GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
2177 [ + - ]: 131926 : ? shdr_info[cnt].shdr.sh_size : 0);
2178 [ + + ]: 131926 : if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
2179 : 396484 : lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
2180 : : }
2181 : : }
2182 : :
2183 : : /* Adjust symbol references if symbol tables changed. */
2184 [ + + ]: 218 : if (any_symtab_changes)
2185 : : /* Find all relocation sections which use this symbol table. */
2186 [ + + ]: 135448 : for (cnt = 1; cnt <= shdridx; ++cnt)
2187 : : {
2188 : 135318 : struct shdr_info *info = &shdr_info[cnt];
2189 [ + + + + ]: 135318 : if (info->idx == 0 && debug_fname == NULL)
2190 : : /* Ignore sections which are discarded. When we are saving a
2191 : : relocation section in a separate debug file, we must fix up
2192 : : the symbol table references. */
2193 : 422 : continue;
2194 : :
2195 : 134896 : const Elf32_Word symtabidx = info->old_sh_link;
2196 [ - + ]: 134896 : elf_assert (symtabidx < shnum + 2);
2197 : 134896 : const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
2198 : :
2199 : : /* If the symbol table hasn't changed, do not do anything. */
2200 [ + + ]: 134896 : if (newsymidx == NULL)
2201 : 134104 : continue;
2202 : :
2203 : : /* If the symbol table is not discarded, but additionally
2204 : : duplicated in the separate debug file and this section
2205 : : is discarded, don't adjust anything. */
2206 [ + + + - ]: 792 : if (info->idx == 0 && shdr_info[symtabidx].debug_data != NULL)
2207 : 368 : continue;
2208 : :
2209 [ + + + + : 424 : switch (info->shdr.sh_type)
- ]
2210 : : {
2211 : 382 : case SHT_REL:
2212 : : case SHT_RELA:
2213 : 764 : scn = (info->idx == 0
2214 : 0 : ? elf_getscn (debugelf, cnt)
2215 [ - + ]: 382 : : elf_getscn (newelf, info->idx));
2216 : 382 : Elf_Data *d = elf_getdata (scn, NULL);
2217 [ + - + - : 382 : elf_assert (d != NULL && d->d_buf != NULL
- + ]
2218 : : && info->shdr.sh_entsize != 0);
2219 : 382 : size_t nrels = (info->shdr.sh_size / info->shdr.sh_entsize);
2220 : :
2221 : 382 : size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2222 : 382 : const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
2223 : 382 : / symsize);
2224 [ + + ]: 382 : if (info->shdr.sh_type == SHT_REL)
2225 [ + + ]: 4878 : for (size_t relidx = 0; relidx < nrels; ++relidx)
2226 : : {
2227 : 4822 : GElf_Rel rel_mem;
2228 [ - + ]: 4822 : if (gelf_getrel (d, relidx, &rel_mem) == NULL)
2229 : 0 : INTERNAL_ERROR (fname);
2230 : :
2231 : 4822 : size_t symidx = GELF_R_SYM (rel_mem.r_info);
2232 [ - + ]: 4822 : elf_assert (symidx < symidxn);
2233 [ + + ]: 4822 : if (newsymidx[symidx] != symidx)
2234 : : {
2235 : 4412 : rel_mem.r_info
2236 : 4412 : = GELF_R_INFO (newsymidx[symidx],
2237 : : GELF_R_TYPE (rel_mem.r_info));
2238 : :
2239 [ - + ]: 4412 : if (gelf_update_rel (d, relidx, &rel_mem) == 0)
2240 : 4822 : INTERNAL_ERROR (fname);
2241 : : }
2242 : : }
2243 : : else
2244 [ + + ]: 27372 : for (size_t relidx = 0; relidx < nrels; ++relidx)
2245 : : {
2246 : 27046 : GElf_Rela rel_mem;
2247 [ - + ]: 27046 : if (gelf_getrela (d, relidx, &rel_mem) == NULL)
2248 : 0 : INTERNAL_ERROR (fname);
2249 : :
2250 : 27046 : size_t symidx = GELF_R_SYM (rel_mem.r_info);
2251 [ - + ]: 27046 : elf_assert (symidx < symidxn);
2252 [ + + ]: 27046 : if (newsymidx[symidx] != symidx)
2253 : : {
2254 : 6352 : rel_mem.r_info
2255 : 6352 : = GELF_R_INFO (newsymidx[symidx],
2256 : : GELF_R_TYPE (rel_mem.r_info));
2257 : :
2258 [ - + ]: 6352 : if (gelf_update_rela (d, relidx, &rel_mem) == 0)
2259 : 27046 : INTERNAL_ERROR (fname);
2260 : : }
2261 : : }
2262 : 424 : break;
2263 : :
2264 : 12 : case SHT_HASH:
2265 : : /* We have to recompute the hash table. */
2266 : :
2267 [ - + ]: 12 : elf_assert (info->idx > 0);
2268 : :
2269 : : /* The hash section in the new file. */
2270 : 12 : scn = elf_getscn (newelf, info->idx);
2271 : :
2272 : : /* The symbol table data. */
2273 : 12 : Elf_Data *symd = elf_getdata (elf_getscn (newelf,
2274 : 12 : shdr_info[symtabidx].idx),
2275 : : NULL);
2276 [ + - - + ]: 12 : elf_assert (symd != NULL && symd->d_buf != NULL);
2277 : :
2278 : : /* The hash table data. */
2279 : 12 : Elf_Data *hashd = elf_getdata (scn, NULL);
2280 [ + - - + ]: 12 : elf_assert (hashd != NULL && hashd->d_buf != NULL);
2281 : :
2282 [ + - ]: 12 : if (info->shdr.sh_entsize == sizeof (Elf32_Word))
2283 : : {
2284 : : /* Sane arches first. */
2285 [ - + ]: 12 : elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
2286 : 12 : Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
2287 : :
2288 : 12 : size_t strshndx = shdr_info[symtabidx].old_sh_link;
2289 : 12 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2290 : :
2291 : 12 : Elf32_Word nchain = bucket[1];
2292 : 12 : Elf32_Word nbucket = bucket[0];
2293 : 12 : uint64_t used_buf = ((2ULL + nchain + nbucket)
2294 : : * sizeof (Elf32_Word));
2295 [ - + ]: 12 : elf_assert (used_buf <= hashd->d_size);
2296 : :
2297 : : /* Adjust the nchain value. The symbol table size
2298 : : changed. We keep the same size for the bucket array. */
2299 : 12 : bucket[1] = symd->d_size / elsize;
2300 : 12 : bucket += 2;
2301 : 12 : Elf32_Word *chain = bucket + nbucket;
2302 : :
2303 : : /* New size of the section. */
2304 : 12 : size_t n_size = ((2 + symd->d_size / elsize + nbucket)
2305 : : * sizeof (Elf32_Word));
2306 [ - + ]: 12 : elf_assert (n_size <= hashd->d_size);
2307 : 12 : hashd->d_size = n_size;
2308 : 12 : update_section_size (scn, hashd, debugelf, cnt, fname);
2309 : :
2310 : : /* Clear the arrays. */
2311 : 12 : memset (bucket, '\0',
2312 : 12 : (symd->d_size / elsize + nbucket)
2313 : : * sizeof (Elf32_Word));
2314 : :
2315 : 12 : for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
2316 [ + + ]: 156 : inner < symd->d_size / elsize; ++inner)
2317 : : {
2318 : 144 : GElf_Sym sym_mem;
2319 : 144 : GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
2320 [ - + ]: 144 : elf_assert (sym != NULL);
2321 : :
2322 : 288 : const char *name = elf_strptr (elf, strshndx,
2323 : 144 : sym->st_name);
2324 [ - + ]: 144 : elf_assert (name != NULL && nbucket != 0);
2325 : 144 : size_t hidx = elf_hash (name) % nbucket;
2326 : :
2327 [ + + ]: 144 : if (bucket[hidx] == 0)
2328 : 120 : bucket[hidx] = inner;
2329 : : else
2330 : : {
2331 : 24 : hidx = bucket[hidx];
2332 : :
2333 [ - + - - ]: 24 : while (chain[hidx] != 0 && chain[hidx] < nchain)
2334 : 0 : hidx = chain[hidx];
2335 : :
2336 : 24 : chain[hidx] = inner;
2337 : : }
2338 : : }
2339 : : }
2340 : : else
2341 : : {
2342 : : /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
2343 [ # # ]: 0 : elf_assert (info->shdr.sh_entsize == sizeof (Elf64_Xword));
2344 : :
2345 : 0 : Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
2346 : :
2347 : 0 : size_t strshndx = shdr_info[symtabidx].old_sh_link;
2348 : 0 : size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2349 : :
2350 [ # # ]: 0 : elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
2351 : 0 : Elf64_Xword nbucket = bucket[0];
2352 : 0 : Elf64_Xword nchain = bucket[1];
2353 : 0 : uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
2354 [ # # # # : 0 : elf_assert (maxwords >= 2
# # ]
2355 : : && maxwords - 2 >= nbucket
2356 : : && maxwords - 2 - nbucket >= nchain);
2357 : :
2358 : : /* Adjust the nchain value. The symbol table size
2359 : : changed. We keep the same size for the bucket array. */
2360 : 0 : bucket[1] = symd->d_size / elsize;
2361 : 0 : bucket += 2;
2362 : 0 : Elf64_Xword *chain = bucket + nbucket;
2363 : :
2364 : : /* New size of the section. */
2365 : 0 : size_t n_size = ((2 + symd->d_size / elsize + nbucket)
2366 : : * sizeof (Elf64_Xword));
2367 [ # # ]: 0 : elf_assert (n_size <= hashd->d_size);
2368 : 0 : hashd->d_size = n_size;
2369 : 0 : update_section_size (scn, hashd, debugelf, cnt, fname);
2370 : :
2371 : : /* Clear the arrays. */
2372 : 0 : memset (bucket, '\0',
2373 : 0 : (symd->d_size / elsize + nbucket)
2374 : : * sizeof (Elf64_Xword));
2375 : :
2376 : 0 : for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
2377 [ # # ]: 0 : inner < symd->d_size / elsize; ++inner)
2378 : : {
2379 : 0 : GElf_Sym sym_mem;
2380 : 0 : GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
2381 [ # # ]: 0 : elf_assert (sym != NULL);
2382 : :
2383 : 0 : const char *name = elf_strptr (elf, strshndx,
2384 : 0 : sym->st_name);
2385 [ # # ]: 0 : elf_assert (name != NULL && nbucket != 0);
2386 : 0 : size_t hidx = elf_hash (name) % nbucket;
2387 : :
2388 [ # # ]: 0 : if (bucket[hidx] == 0)
2389 : 0 : bucket[hidx] = inner;
2390 : : else
2391 : : {
2392 : : hidx = bucket[hidx];
2393 : :
2394 [ # # # # ]: 0 : while (chain[hidx] != 0 && chain[hidx] < nchain)
2395 : : hidx = chain[hidx];
2396 : :
2397 : 0 : chain[hidx] = inner;
2398 : : }
2399 : : }
2400 : : }
2401 : : break;
2402 : :
2403 : 12 : case SHT_GNU_versym:
2404 : : /* If the symbol table changed we have to adjust the entries. */
2405 [ - + ]: 12 : elf_assert (info->idx > 0);
2406 : :
2407 : : /* The symbol version section in the new file. */
2408 : 12 : scn = elf_getscn (newelf, info->idx);
2409 : :
2410 : : /* The symbol table data. */
2411 : 12 : symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
2412 : : NULL);
2413 [ + - - + ]: 12 : elf_assert (symd != NULL && symd->d_buf != NULL);
2414 : 12 : size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2415 : 12 : const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
2416 : :
2417 : : /* The version symbol data. */
2418 : 12 : Elf_Data *verd = elf_getdata (scn, NULL);
2419 [ + - - + ]: 12 : elf_assert (verd != NULL && verd->d_buf != NULL);
2420 : :
2421 : : /* The symbol version array. */
2422 : 12 : GElf_Half *verstab = (GElf_Half *) verd->d_buf;
2423 : :
2424 : : /* Walk through the list and */
2425 : 12 : size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
2426 : 12 : Elf32_Word vers = verd->d_size / elsize;
2427 [ + + + - ]: 516 : for (size_t inner = 1; inner < vers && inner < syms; ++inner)
2428 [ + + + - ]: 504 : if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
2429 : : /* Overwriting the same array works since the
2430 : : reordering can only move entries to lower indices
2431 : : in the array. */
2432 : 408 : verstab[newsymidx[inner]] = verstab[inner];
2433 : :
2434 : : /* New size of the section. */
2435 : 12 : verd->d_size = gelf_fsize (newelf, verd->d_type,
2436 : 12 : symd->d_size
2437 : 12 : / gelf_fsize (elf, symd->d_type, 1,
2438 : : EV_CURRENT),
2439 : : EV_CURRENT);
2440 : 12 : update_section_size (scn, verd, debugelf, cnt, fname);
2441 : 12 : break;
2442 : :
2443 : 18 : case SHT_GROUP:
2444 : : /* Yes, the symbol table changed.
2445 : : Update the section header of the section group. */
2446 : 18 : scn = elf_getscn (newelf, info->idx);
2447 : 18 : GElf_Shdr shdr_mem;
2448 : 18 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
2449 [ - + ]: 18 : elf_assert (shdr != NULL);
2450 : :
2451 : 18 : size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
2452 : 18 : const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
2453 : 18 : / symsz);
2454 [ - + ]: 18 : elf_assert (shdr->sh_info < symn);
2455 : 18 : shdr->sh_info = newsymidx[shdr->sh_info];
2456 : :
2457 : 18 : (void) gelf_update_shdr (scn, shdr);
2458 : 18 : break;
2459 : : }
2460 : : }
2461 : :
2462 : : /* Remove any relocations between debug sections in ET_REL
2463 : : for the debug file when requested. These relocations are always
2464 : : zero based between the unallocated sections. */
2465 [ + + + + ]: 218 : if (debug_fname != NULL && removing_sections
2466 [ + + + + ]: 144 : && reloc_debug && ehdr->e_type == ET_REL)
2467 : 32 : remove_debug_relocations (ebl, debugelf, ehdr, fname, shstrndx);
2468 : :
2469 : : /* Now that we have done all adjustments to the data,
2470 : : we can actually write out the debug file. */
2471 [ + + + + ]: 218 : if (debug_fname != NULL && removing_sections)
2472 : : {
2473 : : /* Finally write the file. */
2474 [ - + ]: 144 : if (permissive)
2475 : 0 : elf_flagelf (debugelf, ELF_C_SET, ELF_F_PERMISSIVE);
2476 [ - + ]: 144 : if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
2477 : : {
2478 : 0 : error (0, 0, _("while writing '%s': %s"),
2479 : : tmp_debug_fname, elf_errmsg (-1));
2480 : 0 : result = 1;
2481 : 0 : goto fail_close;
2482 : : }
2483 : :
2484 : : /* Create the real output file. First rename, then change the
2485 : : mode. */
2486 [ + - ]: 144 : if (rename (tmp_debug_fname, debug_fname) != 0
2487 [ - + ]: 144 : || fchmod (debug_fd, mode) != 0)
2488 : : {
2489 : 0 : error (0, errno, _("while creating '%s'"), debug_fname);
2490 : 0 : result = 1;
2491 : 0 : goto fail_close;
2492 : : }
2493 : :
2494 : : /* The temporary file does not exist anymore. */
2495 : 144 : free (tmp_debug_fname);
2496 : 144 : tmp_debug_fname = NULL;
2497 : :
2498 [ + - ]: 144 : if (!remove_shdrs)
2499 : : {
2500 : 144 : uint32_t debug_crc;
2501 : 144 : Elf_Data debug_crc_data =
2502 : : {
2503 : : .d_type = ELF_T_WORD,
2504 : : .d_buf = &debug_crc,
2505 : : .d_size = sizeof (debug_crc),
2506 : : .d_version = EV_CURRENT
2507 : : };
2508 : :
2509 : : /* Compute the checksum which we will add to the executable. */
2510 [ - + ]: 144 : if (crc32_file (debug_fd, &debug_crc) != 0)
2511 : : {
2512 : 0 : error (0, errno, _("\
2513 : : while computing checksum for debug information"));
2514 : 0 : unlink (debug_fname);
2515 : 0 : result = 1;
2516 : 0 : goto fail_close;
2517 : : }
2518 : :
2519 : : /* Store it in the debuglink section data. */
2520 [ - + ]: 144 : if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
2521 : : &debug_crc_data, ehdr->e_ident[EI_DATA])
2522 : : != &debuglink_crc_data))
2523 : 144 : INTERNAL_ERROR (fname);
2524 : : }
2525 : : }
2526 : :
2527 : 218 : lastsec_offset = shdr_info[shdridx].shdr.sh_offset;
2528 : 218 : lastsec_size = shdr_info[shdridx].shdr.sh_size;
2529 : :
2530 : 250 : done:
2531 : : /* Finally finish the ELF header. Fill in the fields not handled by
2532 : : libelf from the old file. */
2533 : 250 : newehdr = gelf_getehdr (newelf, &newehdr_mem);
2534 [ - + ]: 250 : if (newehdr == NULL)
2535 : 0 : INTERNAL_ERROR (fname);
2536 : :
2537 : 250 : memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
2538 : 250 : newehdr->e_type = ehdr->e_type;
2539 : 250 : newehdr->e_machine = ehdr->e_machine;
2540 : 250 : newehdr->e_version = ehdr->e_version;
2541 : 250 : newehdr->e_entry = ehdr->e_entry;
2542 : 250 : newehdr->e_flags = ehdr->e_flags;
2543 : 250 : newehdr->e_phoff = ehdr->e_phoff;
2544 : :
2545 : : /* We need to position the section header table. */
2546 : 250 : const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
2547 : 250 : newehdr->e_shoff = ((lastsec_offset + lastsec_size + offsize - 1)
2548 : 250 : & ~((GElf_Off) (offsize - 1)));
2549 : 250 : newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
2550 : :
2551 [ - + ]: 250 : if (gelf_update_ehdr (newelf, newehdr) == 0)
2552 : : {
2553 : 0 : error (0, 0, _("%s: error while creating ELF header: %s"),
2554 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2555 : 0 : result = 1;
2556 : : }
2557 : :
2558 : : /* The new section header string table index. */
2559 [ - + ]: 250 : if (update_shdrstrndx (newelf, idx) != 0)
2560 : : {
2561 : 0 : error (0, 0, _("%s: error updating shdrstrndx: %s"),
2562 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2563 : 0 : result = 1;
2564 : : }
2565 : :
2566 : : /* We have everything from the old file. */
2567 [ - + ]: 250 : if (elf_cntl (elf, ELF_C_FDDONE) != 0)
2568 : : {
2569 : 0 : error (0, 0, _("%s: error while reading the file: %s"),
2570 : : fname, elf_errmsg (-1));
2571 : 0 : result = 1;
2572 : : }
2573 : :
2574 : : /* The ELF library better follows our layout when this is not a
2575 : : relocatable object file. */
2576 : 500 : elf_flagelf (newelf, ELF_C_SET,
2577 [ + + ]: 250 : (phnum > 0 ? ELF_F_LAYOUT : 0)
2578 [ + - ]: 500 : | (permissive ? ELF_F_PERMISSIVE : 0));
2579 : :
2580 : : /* Finally write the file. */
2581 [ - + ]: 250 : if (elf_update (newelf, ELF_C_WRITE) == -1)
2582 : : {
2583 : 0 : error (0, 0, _("while writing '%s': %s"),
2584 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2585 : 0 : result = 1;
2586 : : }
2587 : :
2588 [ + - ]: 250 : if (remove_shdrs)
2589 : : {
2590 : : /* libelf can't cope without the section headers being properly intact.
2591 : : So we just let it write them normally, and then we nuke them later. */
2592 : :
2593 [ # # ]: 0 : if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
2594 : : {
2595 : 0 : assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
2596 : : == offsetof (Elf32_Ehdr, e_shnum));
2597 : 0 : assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
2598 : : == offsetof (Elf32_Ehdr, e_shstrndx));
2599 : 0 : const Elf32_Off zero_off = 0;
2600 : 0 : const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
2601 [ # # ]: 0 : if (pwrite_retry (fd, &zero_off, sizeof zero_off,
2602 : : offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
2603 [ # # ]: 0 : || (pwrite_retry (fd, zero, sizeof zero,
2604 : : offsetof (Elf32_Ehdr, e_shentsize))
2605 : : != sizeof zero)
2606 [ # # ]: 0 : || ftruncate (fd, lastsec_offset) < 0)
2607 : : {
2608 : 0 : error (0, errno, _("while writing '%s'"),
2609 [ # # ]: 0 : output_fname ?: fname);
2610 : 0 : result = 1;
2611 : : }
2612 : : }
2613 : : else
2614 : : {
2615 : 0 : assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
2616 : : == offsetof (Elf64_Ehdr, e_shnum));
2617 : 0 : assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
2618 : : == offsetof (Elf64_Ehdr, e_shstrndx));
2619 : 0 : const Elf64_Off zero_off = 0;
2620 : 0 : const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
2621 [ # # ]: 0 : if (pwrite_retry (fd, &zero_off, sizeof zero_off,
2622 : : offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
2623 [ # # ]: 0 : || (pwrite_retry (fd, zero, sizeof zero,
2624 : : offsetof (Elf64_Ehdr, e_shentsize))
2625 : : != sizeof zero)
2626 [ # # ]: 0 : || ftruncate (fd, lastsec_offset) < 0)
2627 : : {
2628 : 0 : error (0, errno, _("while writing '%s'"),
2629 [ # # ]: 0 : output_fname ?: fname);
2630 : 0 : result = 1;
2631 : : }
2632 : : }
2633 : : }
2634 : :
2635 : 250 : fail_close:
2636 [ + + ]: 256 : if (shdr_info != NULL)
2637 : : {
2638 : : /* For some sections we might have created an table to map symbol
2639 : : table indices. Or we might kept (original) data around to put
2640 : : into the .debug file. */
2641 [ + + ]: 400694 : for (cnt = 1; cnt <= shdridx; ++cnt)
2642 : : {
2643 : 400472 : free (shdr_info[cnt].newsymidx);
2644 [ + + ]: 400472 : if (shdr_info[cnt].debug_data != NULL)
2645 : 184 : free (shdr_info[cnt].debug_data->d_buf);
2646 : : }
2647 : :
2648 : : /* Free data we allocated for the .gnu_debuglink section. */
2649 : 222 : free (debuglink_buf);
2650 : :
2651 : : /* Free the memory. */
2652 [ + + ]: 222 : if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
2653 : 6 : free (shdr_info);
2654 : : }
2655 : :
2656 : : /* Free other resources. */
2657 [ + + ]: 256 : if (shstrtab_data != NULL)
2658 : 218 : free (shstrtab_data->d_buf);
2659 [ + + ]: 256 : if (shst != NULL)
2660 : 222 : dwelf_strtab_free (shst);
2661 : :
2662 : : /* That was it. Close the descriptors. */
2663 [ - + ]: 256 : if (elf_end (newelf) != 0)
2664 : : {
2665 : 0 : error (0, 0, _("error while finishing '%s': %s"),
2666 [ # # ]: 0 : output_fname ?: fname, elf_errmsg (-1));
2667 : 0 : result = 1;
2668 : : }
2669 : :
2670 [ + + + - ]: 256 : if (debugelf != NULL && elf_end (debugelf) != 0)
2671 : : {
2672 : 0 : error (0, 0, _("error while finishing '%s': %s"), debug_fname,
2673 : : elf_errmsg (-1));
2674 : 0 : result = 1;
2675 : : }
2676 : :
2677 : 256 : fail:
2678 : : /* Close the EBL backend. */
2679 [ + + ]: 256 : if (ebl != NULL)
2680 : 140 : ebl_closebackend (ebl);
2681 : :
2682 : 256 : cleanup_debug ();
2683 : :
2684 : : /* If requested, preserve the timestamp. */
2685 [ + - ]: 256 : if (tvp != NULL)
2686 : : {
2687 [ # # ]: 0 : if (futimens (fd, tvp) != 0)
2688 : : {
2689 : 0 : error (0, errno, _("\
2690 : : cannot set access and modification date of '%s'"),
2691 [ # # ]: 0 : output_fname ?: fname);
2692 : 0 : result = 1;
2693 : : }
2694 : : }
2695 : :
2696 : : /* Close the file descriptor if we created a new file. */
2697 [ + + ]: 256 : if (output_fname != NULL)
2698 : : {
2699 : 168 : close (fd);
2700 [ + - ]: 168 : if (result != 0)
2701 : 0 : unlink (output_fname);
2702 : : }
2703 : :
2704 : : return result;
2705 : : }
2706 : :
2707 : : static void
2708 : 256 : cleanup_debug (void)
2709 : : {
2710 [ + + ]: 256 : if (debug_fd >= 0)
2711 : : {
2712 [ + + ]: 148 : if (tmp_debug_fname != NULL)
2713 : : {
2714 : 4 : unlink (tmp_debug_fname);
2715 : 4 : free (tmp_debug_fname);
2716 : 4 : tmp_debug_fname = NULL;
2717 : : }
2718 : 148 : close (debug_fd);
2719 : 148 : debug_fd = -1;
2720 : : }
2721 : 256 : }
2722 : :
2723 : : static int
2724 : : handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
2725 : : struct timespec tvp[2])
2726 : : {
2727 : : size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
2728 : : size_t fname_len = strlen (fname) + 1;
2729 : : char new_prefix[prefix_len + 1 + fname_len];
2730 : : char *cp = new_prefix;
2731 : :
2732 : : /* Create the full name of the file. */
2733 : : if (prefix != NULL)
2734 : : {
2735 : : cp = mempcpy (cp, prefix, prefix_len);
2736 : : *cp++ = ':';
2737 : : }
2738 : : memcpy (cp, fname, fname_len);
2739 : :
2740 : :
2741 : : /* Process all the files contained in the archive. */
2742 : : Elf *subelf;
2743 : : Elf_Cmd cmd = ELF_C_RDWR;
2744 : : int result = 0;
2745 : : while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
2746 : : {
2747 : : /* The the header for this element. */
2748 : : Elf_Arhdr *arhdr = elf_getarhdr (subelf);
2749 : :
2750 : : if (elf_kind (subelf) == ELF_K_ELF)
2751 : : result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
2752 : : else if (elf_kind (subelf) == ELF_K_AR)
2753 : : result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
2754 : :
2755 : : /* Get next archive element. */
2756 : : cmd = elf_next (subelf);
2757 : : if (unlikely (elf_end (subelf) != 0))
2758 : : INTERNAL_ERROR (fname);
2759 : : }
2760 : :
2761 : : if (tvp != NULL)
2762 : : {
2763 : : if (unlikely (futimens (fd, tvp) != 0))
2764 : : {
2765 : : error (0, errno, _("\
2766 : : cannot set access and modification date of '%s'"), fname);
2767 : : result = 1;
2768 : : }
2769 : : }
2770 : :
2771 : : if (unlikely (close (fd) != 0))
2772 : : error_exit (errno, _("while closing '%s'"), fname);
2773 : :
2774 : : return result;
2775 : : }
2776 : :
2777 : :
2778 : : #include "debugpred.h"
|