blob: 78f683a8c2842ba5764eb31a2b62a869a2aef7d3 [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Discard section not used at runtime from object files.
2 Copyright (C) 2000-2012 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
9
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include <argp.h>
32#include <assert.h>
33#include <byteswap.h>
34#include <endian.h>
35#include <error.h>
36#include <fcntl.h>
37#include <gelf.h>
38#include <libelf.h>
39#include <libintl.h>
40#include <locale.h>
41#include <mcheck.h>
42#include <stdbool.h>
43#include <stdio.h>
44#include <stdio_ext.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include <sys/param.h>
49#include <sys/stat.h>
50#include <sys/time.h>
51
52#include <elf-knowledge.h>
53#include <libebl.h>
54#include <system.h>
55
56typedef uint8_t GElf_Byte;
57
58/* Name and version of program. */
59static void print_version (FILE *stream, struct argp_state *state);
60ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
61
62/* Bug report address. */
63ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
64
65
66/* Values for the parameters which have no short form. */
67#define OPT_REMOVE_COMMENT 0x100
68#define OPT_PERMISSIVE 0x101
69#define OPT_STRIP_SECTIONS 0x102
70#define OPT_RELOC_DEBUG 0x103
71
72
73/* Definitions of arguments for argp functions. */
74static const struct argp_option options[] =
75{
76 { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
77 { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
78 { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
79 { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
80
81 { NULL, 0, NULL, 0, N_("Output options:"), 0 },
82 { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
83 { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
84 { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
85 { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
86 { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
87 N_("Remove section headers (not recommended)"), 0 },
88 { "preserve-dates", 'p', NULL, 0,
89 N_("Copy modified/access timestamps to the output"), 0 },
90 { "reloc-debug-sections", OPT_RELOC_DEBUG, NULL, 0,
91 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 reversable, needs -f)"), 0 },
92 { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
93 N_("Remove .comment section"), 0 },
94 { "remove-section", 'R', "SECTION", OPTION_HIDDEN, NULL, 0 },
95 { "permissive", OPT_PERMISSIVE, NULL, 0,
96 N_("Relax a few rules to handle slightly broken ELF files"), 0 },
97 { NULL, 0, NULL, 0, NULL, 0 }
98};
99
100/* Short description of program. */
101static const char doc[] = N_("Discard symbols from object files.");
102
103/* Strings for arguments in help texts. */
104static const char args_doc[] = N_("[FILE...]");
105
106/* Prototype for option handler. */
107static error_t parse_opt (int key, char *arg, struct argp_state *state);
108
109/* Data structure to communicate with argp functions. */
110static struct argp argp =
111{
112 options, parse_opt, args_doc, doc, NULL, NULL, NULL
113};
114
115
116/* Print symbols in file named FNAME. */
117static int process_file (const char *fname);
118
119/* Handle one ELF file. */
120static int handle_elf (int fd, Elf *elf, const char *prefix,
121 const char *fname, mode_t mode, struct timeval tvp[2]);
122
123/* Handle all files contained in the archive. */
124static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
125 struct timeval tvp[2]);
126
127#define INTERNAL_ERROR(fname) \
128 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
129 fname, __LINE__, PACKAGE_VERSION, __DATE__, elf_errmsg (-1))
130
131
132/* Name of the output file. */
133static const char *output_fname;
134
135/* Name of the debug output file. */
136static const char *debug_fname;
137
138/* Name to pretend the debug output file has. */
139static const char *debug_fname_embed;
140
141/* If true output files shall have same date as the input file. */
142static bool preserve_dates;
143
144/* If true .comment sections will be removed. */
145static bool remove_comment;
146
147/* If true remove all debug sections. */
148static bool remove_debug;
149
150/* If true remove all section headers. */
151static bool remove_shdrs;
152
153/* If true relax some ELF rules for input files. */
154static bool permissive;
155
156/* If true perform relocations between debug sections. */
157static bool reloc_debug;
158
159
160int
161main (int argc, char *argv[])
162{
163 int remaining;
164 int result = 0;
165
166 /* Make memory leak detection possible. */
167 mtrace ();
168
169 /* We use no threads here which can interfere with handling a stream. */
170 __fsetlocking (stdin, FSETLOCKING_BYCALLER);
171 __fsetlocking (stdout, FSETLOCKING_BYCALLER);
172 __fsetlocking (stderr, FSETLOCKING_BYCALLER);
173
174 /* Set locale. */
175 setlocale (LC_ALL, "");
176
177 /* Make sure the message catalog can be found. */
178 bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
179
180 /* Initialize the message catalog. */
181 textdomain (PACKAGE_TARNAME);
182
183 /* Parse and process arguments. */
184 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
185 return EXIT_FAILURE;
186
187 if (reloc_debug && debug_fname == NULL)
188 error (EXIT_FAILURE, 0,
189 gettext ("--reloc-debug-sections used without -f"));
190
191 /* Tell the library which version we are expecting. */
192 elf_version (EV_CURRENT);
193
194 if (remaining == argc)
195 /* The user didn't specify a name so we use a.out. */
196 result = process_file ("a.out");
197 else
198 {
199 /* If we have seen the '-o' or '-f' option there must be exactly one
200 input file. */
201 if ((output_fname != NULL || debug_fname != NULL)
202 && remaining + 1 < argc)
203 error (EXIT_FAILURE, 0, gettext ("\
204Only one input file allowed together with '-o' and '-f'"));
205
206 /* Process all the remaining files. */
207 do
208 result |= process_file (argv[remaining]);
209 while (++remaining < argc);
210 }
211
212 return result;
213}
214
215
216/* Print the version information. */
217static void
218print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
219{
220 fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
221 fprintf (stream, gettext ("\
222Copyright (C) %s Red Hat, Inc.\n\
223This is free software; see the source for copying conditions. There is NO\n\
224warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
225"), "2012");
226 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
227}
228
229
230/* Handle program arguments. */
231static error_t
232parse_opt (int key, char *arg, struct argp_state *state)
233{
234 switch (key)
235 {
236 case 'f':
237 if (debug_fname != NULL)
238 {
239 error (0, 0, gettext ("-f option specified twice"));
240 return EINVAL;
241 }
242 debug_fname = arg;
243 break;
244
245 case 'F':
246 if (debug_fname_embed != NULL)
247 {
248 error (0, 0, gettext ("-F option specified twice"));
249 return EINVAL;
250 }
251 debug_fname_embed = arg;
252 break;
253
254 case 'o':
255 if (output_fname != NULL)
256 {
257 error (0, 0, gettext ("-o option specified twice"));
258 return EINVAL;
259 }
260 output_fname = arg;
261 break;
262
263 case 'p':
264 preserve_dates = true;
265 break;
266
267 case OPT_RELOC_DEBUG:
268 reloc_debug = true;
269 break;
270
271 case OPT_REMOVE_COMMENT:
272 remove_comment = true;
273 break;
274
275 case 'R':
276 if (!strcmp (arg, ".comment"))
277 remove_comment = true;
278 else
279 {
280 argp_error (state,
281 gettext ("-R option supports only .comment section"));
282 return EINVAL;
283 }
284 break;
285
286 case 'g':
287 case 'd':
288 case 'S':
289 remove_debug = true;
290 break;
291
292 case OPT_STRIP_SECTIONS:
293 remove_shdrs = true;
294 break;
295
296 case OPT_PERMISSIVE:
297 permissive = true;
298 break;
299
300 case 's': /* Ignored for compatibility. */
301 break;
302
303 default:
304 return ARGP_ERR_UNKNOWN;
305 }
306 return 0;
307}
308
309
310static int
311process_file (const char *fname)
312{
313 /* If we have to preserve the modify and access timestamps get them
314 now. We cannot use fstat() after opening the file since the open
315 would change the access time. */
316 struct stat64 pre_st;
317 struct timeval tv[2];
318 again:
319 if (preserve_dates)
320 {
321 if (stat64 (fname, &pre_st) != 0)
322 {
323 error (0, errno, gettext ("cannot stat input file '%s'"), fname);
324 return 1;
325 }
326
327 /* If we have to preserve the timestamp, we need it in the
328 format utimes() understands. */
329 TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
330 TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
331 }
332
333 /* Open the file. */
334 int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
335 if (fd == -1)
336 {
337 error (0, errno, gettext ("while opening '%s'"), fname);
338 return 1;
339 }
340
341 /* We always use fstat() even if we called stat() before. This is
342 done to make sure the information returned by stat() is for the
343 same file. */
344 struct stat64 st;
345 if (fstat64 (fd, &st) != 0)
346 {
347 error (0, errno, gettext ("cannot stat input file '%s'"), fname);
348 return 1;
349 }
350 /* Paranoid mode on. */
351 if (preserve_dates
352 && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
353 {
354 /* We detected a race. Try again. */
355 close (fd);
356 goto again;
357 }
358
359 /* Now get the ELF descriptor. */
360 Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
361 NULL);
362 int result;
363 switch (elf_kind (elf))
364 {
365 case ELF_K_ELF:
366 result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
367 preserve_dates ? tv : NULL);
368 break;
369
370 case ELF_K_AR:
371 /* It is not possible to strip the content of an archive direct
372 the output to a specific file. */
373 if (unlikely (output_fname != NULL || debug_fname != NULL))
374 {
375 error (0, 0, gettext ("%s: cannot use -o or -f when stripping archive"),
376 fname);
377 result = 1;
378 }
379 else
380 result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
381 break;
382
383 default:
384 error (0, 0, gettext ("%s: File format not recognized"), fname);
385 result = 1;
386 break;
387 }
388
389 if (unlikely (elf_end (elf) != 0))
390 INTERNAL_ERROR (fname);
391
392 close (fd);
393
394 return result;
395}
396
397
398/* Maximum size of array allocated on stack. */
399#define MAX_STACK_ALLOC (400 * 1024)
400
401static int
402handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
403 mode_t mode, struct timeval tvp[2])
404{
405 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
406 size_t fname_len = strlen (fname) + 1;
407 char *fullname = alloca (prefix_len + 1 + fname_len);
408 char *cp = fullname;
409 Elf *debugelf = NULL;
410 char *tmp_debug_fname = NULL;
411 int result = 0;
412 size_t shdridx = 0;
413 size_t shstrndx;
414 struct shdr_info
415 {
416 Elf_Scn *scn;
417 GElf_Shdr shdr;
418 Elf_Data *data;
419 Elf_Data *debug_data;
420 const char *name;
421 Elf32_Word idx; /* Index in new file. */
422 Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
423 Elf32_Word symtab_idx;
424 Elf32_Word version_idx;
425 Elf32_Word group_idx;
426 Elf32_Word group_cnt;
427 Elf_Scn *newscn;
428 struct Ebl_Strent *se;
429 Elf32_Word *newsymidx;
430 } *shdr_info = NULL;
431 Elf_Scn *scn;
432 size_t cnt;
433 size_t idx;
434 bool changes;
435 GElf_Ehdr newehdr_mem;
436 GElf_Ehdr *newehdr;
437 GElf_Ehdr debugehdr_mem;
438 GElf_Ehdr *debugehdr;
439 struct Ebl_Strtab *shst = NULL;
440 Elf_Data debuglink_crc_data;
441 bool any_symtab_changes = false;
442 Elf_Data *shstrtab_data = NULL;
443
444 /* Create the full name of the file. */
445 if (prefix != NULL)
446 {
447 cp = mempcpy (cp, prefix, prefix_len);
448 *cp++ = ':';
449 }
450 memcpy (cp, fname, fname_len);
451
452 /* If we are not replacing the input file open a new file here. */
453 if (output_fname != NULL)
454 {
455 fd = open (output_fname, O_RDWR | O_CREAT, mode);
456 if (unlikely (fd == -1))
457 {
458 error (0, errno, gettext ("cannot open '%s'"), output_fname);
459 return 1;
460 }
461 }
462
463 int debug_fd = -1;
464
465 /* Get the EBL handling. Removing all debugging symbols with the -g
466 option or resolving all relocations between debug sections with
467 the --reloc-debug-sections option are currently the only reasons
468 we need EBL so don't open the backend unless necessary. */
469 Ebl *ebl = NULL;
470 if (remove_debug || reloc_debug)
471 {
472 ebl = ebl_openbackend (elf);
473 if (ebl == NULL)
474 {
475 error (0, errno, gettext ("cannot open EBL backend"));
476 result = 1;
477 goto fail;
478 }
479 }
480
481 /* Open the additional file the debug information will be stored in. */
482 if (debug_fname != NULL)
483 {
484 /* Create a temporary file name. We do not want to overwrite
485 the debug file if the file would not contain any
486 information. */
487 size_t debug_fname_len = strlen (debug_fname);
488 tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
489 strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
490 ".XXXXXX");
491
492 debug_fd = mkstemp (tmp_debug_fname);
493 if (unlikely (debug_fd == -1))
494 {
495 error (0, errno, gettext ("cannot open '%s'"), debug_fname);
496 result = 1;
497 goto fail;
498 }
499 }
500
501 /* Get the information from the old file. */
502 GElf_Ehdr ehdr_mem;
503 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
504 if (ehdr == NULL)
505 INTERNAL_ERROR (fname);
506
507 /* Get the section header string table index. */
508 if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
509 error (EXIT_FAILURE, 0,
510 gettext ("cannot get section header string table index"));
511
512 /* We now create a new ELF descriptor for the same file. We
513 construct it almost exactly in the same way with some information
514 dropped. */
515 Elf *newelf;
516 if (output_fname != NULL)
517 newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
518 else
519 newelf = elf_clone (elf, ELF_C_EMPTY);
520
521 if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
522 || (ehdr->e_type != ET_REL
523 && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
524 {
525 error (0, 0, gettext ("cannot create new file '%s': %s"),
526 output_fname, elf_errmsg (-1));
527 goto fail;
528 }
529
530 /* Copy over the old program header if needed. */
531 if (ehdr->e_type != ET_REL)
532 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
533 {
534 GElf_Phdr phdr_mem;
535 GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
536 if (phdr == NULL
537 || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
538 INTERNAL_ERROR (fname);
539 }
540
541 if (debug_fname != NULL)
542 {
543 /* Also create an ELF descriptor for the debug file */
544 debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
545 if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
546 || (ehdr->e_type != ET_REL
547 && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
548 {
549 error (0, 0, gettext ("cannot create new file '%s': %s"),
550 debug_fname, elf_errmsg (-1));
551 goto fail_close;
552 }
553
554 /* Copy over the old program header if needed. */
555 if (ehdr->e_type != ET_REL)
556 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
557 {
558 GElf_Phdr phdr_mem;
559 GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
560 if (phdr == NULL
561 || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
562 INTERNAL_ERROR (fname);
563 }
564 }
565
566 /* Number of sections. */
567 size_t shnum;
568 if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
569 {
570 error (0, 0, gettext ("cannot determine number of sections: %s"),
571 elf_errmsg (-1));
572 goto fail_close;
573 }
574
575 /* Storage for section information. We leave room for two more
576 entries since we unconditionally create a section header string
577 table. Maybe some weird tool created an ELF file without one.
578 The other one is used for the debug link section. */
579 if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
580 shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
581 sizeof (struct shdr_info));
582 else
583 {
584 shdr_info = (struct shdr_info *) alloca ((shnum + 2)
585 * sizeof (struct shdr_info));
586 memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
587 }
588
589 /* Prepare section information data structure. */
590 scn = NULL;
591 cnt = 1;
592 while ((scn = elf_nextscn (elf, scn)) != NULL)
593 {
594 /* This should always be true (i.e., there should not be any
595 holes in the numbering). */
596 assert (elf_ndxscn (scn) == cnt);
597
598 shdr_info[cnt].scn = scn;
599
600 /* Get the header. */
601 if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
602 INTERNAL_ERROR (fname);
603
604 /* Get the name of the section. */
605 shdr_info[cnt].name = elf_strptr (elf, shstrndx,
606 shdr_info[cnt].shdr.sh_name);
607 if (shdr_info[cnt].name == NULL)
608 {
609 error (0, 0, gettext ("illformed file '%s'"), fname);
610 goto fail_close;
611 }
612
613 /* Mark them as present but not yet investigated. */
614 shdr_info[cnt].idx = 1;
615
616 /* Remember the shdr.sh_link value. */
617 shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
618
619 /* Sections in files other than relocatable object files which
620 are not loaded can be freely moved by us. In relocatable
621 object files everything can be moved. */
622 if (ehdr->e_type == ET_REL
623 || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
624 shdr_info[cnt].shdr.sh_offset = 0;
625
626 /* If this is an extended section index table store an
627 appropriate reference. */
628 if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
629 {
630 assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
631 shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
632 }
633 else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
634 {
635 /* Cross-reference the sections contained in the section
636 group. */
637 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
638 if (shdr_info[cnt].data == NULL)
639 INTERNAL_ERROR (fname);
640
641 /* XXX Fix for unaligned access. */
642 Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
643 size_t inner;
644 for (inner = 1;
645 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
646 ++inner)
647 shdr_info[grpref[inner]].group_idx = cnt;
648
649 if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
650 /* If the section group contains only one element and this
651 is n COMDAT section we can drop it right away. */
652 shdr_info[cnt].idx = 0;
653 else
654 shdr_info[cnt].group_cnt = inner - 1;
655 }
656 else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
657 {
658 assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
659 shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
660 }
661
662 /* If this section is part of a group make sure it is not
663 discarded right away. */
664 if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
665 {
666 assert (shdr_info[cnt].group_idx != 0);
667
668 if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
669 {
670 /* The section group section will be removed. */
671 shdr_info[cnt].group_idx = 0;
672 shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
673 }
674 }
675
676 /* Increment the counter. */
677 ++cnt;
678 }
679
680 /* Now determine which sections can go away. The general rule is that
681 all sections which are not used at runtime are stripped out. But
682 there are a few exceptions:
683
684 - special sections named ".comment" and ".note" are kept
685 - OS or architecture specific sections are kept since we might not
686 know how to handle them
687 - if a section is referred to from a section which is not removed
688 in the sh_link or sh_info element it cannot be removed either
689 */
690 for (cnt = 1; cnt < shnum; ++cnt)
691 /* Check whether the section can be removed. */
692 if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
693 : ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
694 shdr_info[cnt].name, remove_comment,
695 remove_debug))
696 {
697 /* For now assume this section will be removed. */
698 shdr_info[cnt].idx = 0;
699
700 idx = shdr_info[cnt].group_idx;
701 while (idx != 0)
702 {
703 /* The section group data is already loaded. */
704 assert (shdr_info[idx].data != NULL);
705
706 /* If the references section group is a normal section
707 group and has one element remaining, or if it is an
708 empty COMDAT section group it is removed. */
709 bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
710 & GRP_COMDAT) != 0;
711
712 --shdr_info[idx].group_cnt;
713 if ((!is_comdat && shdr_info[idx].group_cnt == 1)
714 || (is_comdat && shdr_info[idx].group_cnt == 0))
715 {
716 shdr_info[idx].idx = 0;
717 /* Continue recursively. */
718 idx = shdr_info[idx].group_idx;
719 }
720 else
721 break;
722 }
723 }
724
725 /* Mark the SHT_NULL section as handled. */
726 shdr_info[0].idx = 2;
727
728
729 /* Handle exceptions: section groups and cross-references. We might
730 have to repeat this a few times since the resetting of the flag
731 might propagate. */
732 do
733 {
734 changes = false;
735
736 for (cnt = 1; cnt < shnum; ++cnt)
737 {
738 if (shdr_info[cnt].idx == 0)
739 {
740 /* If a relocation section is marked as being removed make
741 sure the section it is relocating is removed, too. */
742 if ((shdr_info[cnt].shdr.sh_type == SHT_REL
743 || shdr_info[cnt].shdr.sh_type == SHT_RELA)
744 && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
745 shdr_info[cnt].idx = 1;
746
747 /* If a group section is marked as being removed make
748 sure all the sections it contains are being removed, too. */
749 if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
750 {
751 Elf32_Word *grpref;
752 grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
753 for (size_t in = 1;
754 in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
755 ++in)
756 if (shdr_info[grpref[in]].idx != 0)
757 {
758 shdr_info[cnt].idx = 1;
759 break;
760 }
761 }
762 }
763
764 if (shdr_info[cnt].idx == 1)
765 {
766 /* The content of symbol tables we don't remove must not
767 reference any section which we do remove. Otherwise
768 we cannot remove the section. */
769 if (debug_fname != NULL
770 && shdr_info[cnt].debug_data == NULL
771 && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
772 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
773 {
774 /* Make sure the data is loaded. */
775 if (shdr_info[cnt].data == NULL)
776 {
777 shdr_info[cnt].data
778 = elf_getdata (shdr_info[cnt].scn, NULL);
779 if (shdr_info[cnt].data == NULL)
780 INTERNAL_ERROR (fname);
781 }
782 Elf_Data *symdata = shdr_info[cnt].data;
783
784 /* If there is an extended section index table load it
785 as well. */
786 if (shdr_info[cnt].symtab_idx != 0
787 && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
788 {
789 assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
790
791 shdr_info[shdr_info[cnt].symtab_idx].data
792 = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
793 NULL);
794 if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
795 INTERNAL_ERROR (fname);
796 }
797 Elf_Data *xndxdata
798 = shdr_info[shdr_info[cnt].symtab_idx].data;
799
800 /* Go through all symbols and make sure the section they
801 reference is not removed. */
802 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
803 ehdr->e_version);
804
805 for (size_t inner = 0;
806 inner < shdr_info[cnt].data->d_size / elsize;
807 ++inner)
808 {
809 GElf_Sym sym_mem;
810 Elf32_Word xndx;
811 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
812 inner, &sym_mem,
813 &xndx);
814 if (sym == NULL)
815 INTERNAL_ERROR (fname);
816
817 size_t scnidx = sym->st_shndx;
818 if (scnidx == SHN_UNDEF || scnidx >= shnum
819 || (scnidx >= SHN_LORESERVE
820 && scnidx <= SHN_HIRESERVE
821 && scnidx != SHN_XINDEX)
822 /* Don't count in the section symbols. */
823 || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
824 /* This is no section index, leave it alone. */
825 continue;
826 else if (scnidx == SHN_XINDEX)
827 scnidx = xndx;
828
829 if (shdr_info[scnidx].idx == 0)
830 /* This symbol table has a real symbol in
831 a discarded section. So preserve the
832 original table in the debug file. */
833 shdr_info[cnt].debug_data = symdata;
834 }
835 }
836
837 /* Cross referencing happens:
838 - for the cases the ELF specification says. That are
839 + SHT_DYNAMIC in sh_link to string table
840 + SHT_HASH in sh_link to symbol table
841 + SHT_REL and SHT_RELA in sh_link to symbol table
842 + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
843 + SHT_GROUP in sh_link to symbol table
844 + SHT_SYMTAB_SHNDX in sh_link to symbol table
845 Other (OS or architecture-specific) sections might as
846 well use this field so we process it unconditionally.
847 - references inside section groups
848 - specially marked references in sh_info if the SHF_INFO_LINK
849 flag is set
850 */
851
852 if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
853 {
854 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
855 changes |= shdr_info[cnt].shdr.sh_link < cnt;
856 }
857
858 /* Handle references through sh_info. */
859 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
860 && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
861 {
862 shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
863 changes |= shdr_info[cnt].shdr.sh_info < cnt;
864 }
865
866 /* Mark the section as investigated. */
867 shdr_info[cnt].idx = 2;
868 }
869
870 if (debug_fname != NULL
871 && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
872 {
873 /* This section is being preserved in the debug file.
874 Sections it refers to must be preserved there too.
875
876 In this pass we mark sections to be preserved in both
877 files by setting the .debug_data pointer to the original
878 file's .data pointer. Below, we'll copy the section
879 contents. */
880
881 inline void check_preserved (size_t i)
882 {
883 if (i != 0 && shdr_info[i].idx != 0
884 && shdr_info[i].debug_data == NULL)
885 {
886 if (shdr_info[i].data == NULL)
887 shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
888 if (shdr_info[i].data == NULL)
889 INTERNAL_ERROR (fname);
890
891 shdr_info[i].debug_data = shdr_info[i].data;
892 changes |= i < cnt;
893 }
894 }
895
896 check_preserved (shdr_info[cnt].shdr.sh_link);
897 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
898 check_preserved (shdr_info[cnt].shdr.sh_info);
899 }
900 }
901 }
902 while (changes);
903
904 /* Copy the removed sections to the debug output file.
905 The ones that are not removed in the stripped file are SHT_NOBITS. */
906 if (debug_fname != NULL)
907 {
908 for (cnt = 1; cnt < shnum; ++cnt)
909 {
910 scn = elf_newscn (debugelf);
911 if (scn == NULL)
912 error (EXIT_FAILURE, 0,
913 gettext ("while generating output file: %s"),
914 elf_errmsg (-1));
915
916 bool discard_section = (shdr_info[cnt].idx > 0
917 && shdr_info[cnt].debug_data == NULL
918 && shdr_info[cnt].shdr.sh_type != SHT_NOTE
919 && shdr_info[cnt].shdr.sh_type != SHT_GROUP
920 && cnt != ehdr->e_shstrndx);
921
922 /* Set the section header in the new file. */
923 GElf_Shdr debugshdr = shdr_info[cnt].shdr;
924 if (discard_section)
925 debugshdr.sh_type = SHT_NOBITS;
926
927 if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
928 /* There cannot be any overflows. */
929 INTERNAL_ERROR (fname);
930
931 /* Get the data from the old file if necessary. */
932 if (shdr_info[cnt].data == NULL)
933 {
934 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
935 if (shdr_info[cnt].data == NULL)
936 INTERNAL_ERROR (fname);
937 }
938
939 /* Set the data. This is done by copying from the old file. */
940 Elf_Data *debugdata = elf_newdata (scn);
941 if (debugdata == NULL)
942 INTERNAL_ERROR (fname);
943
944 /* Copy the structure. This data may be modified in place
945 before we write out the file. */
946 *debugdata = *shdr_info[cnt].data;
947 if (discard_section)
948 debugdata->d_buf = NULL;
949 else if (shdr_info[cnt].debug_data != NULL
950 || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
951 {
952 /* Copy the original data before it gets modified. */
953 shdr_info[cnt].debug_data = debugdata;
954 debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
955 debugdata->d_buf, debugdata->d_size);
956 }
957 }
958
959 /* Finish the ELF header. Fill in the fields not handled by
960 libelf from the old file. */
961 debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
962 if (debugehdr == NULL)
963 INTERNAL_ERROR (fname);
964
965 memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
966 debugehdr->e_type = ehdr->e_type;
967 debugehdr->e_machine = ehdr->e_machine;
968 debugehdr->e_version = ehdr->e_version;
969 debugehdr->e_entry = ehdr->e_entry;
970 debugehdr->e_flags = ehdr->e_flags;
971 debugehdr->e_shstrndx = ehdr->e_shstrndx;
972
973 if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
974 {
975 error (0, 0, gettext ("%s: error while creating ELF header: %s"),
976 debug_fname, elf_errmsg (-1));
977 result = 1;
978 goto fail_close;
979 }
980 }
981
982 /* Mark the section header string table as unused, we will create
983 a new one. */
984 shdr_info[shstrndx].idx = 0;
985
986 /* We need a string table for the section headers. */
987 shst = ebl_strtabinit (true);
988 if (shst == NULL)
989 error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
990 output_fname ?: fname);
991
992 /* Assign new section numbers. */
993 shdr_info[0].idx = 0;
994 for (cnt = idx = 1; cnt < shnum; ++cnt)
995 if (shdr_info[cnt].idx > 0)
996 {
997 shdr_info[cnt].idx = idx++;
998
999 /* Create a new section. */
1000 shdr_info[cnt].newscn = elf_newscn (newelf);
1001 if (shdr_info[cnt].newscn == NULL)
1002 error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
1003 elf_errmsg (-1));
1004
1005 assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1006
1007 /* Add this name to the section header string table. */
1008 shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
1009 }
1010
1011 /* Test whether we are doing anything at all. */
1012 if (cnt == idx)
1013 /* Nope, all removable sections are already gone. */
1014 goto fail_close;
1015
1016 /* Create the reference to the file with the debug info. */
1017 if (debug_fname != NULL && !remove_shdrs)
1018 {
1019 /* Add the section header string table section name. */
1020 shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
1021 shdr_info[cnt].idx = idx++;
1022
1023 /* Create the section header. */
1024 shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
1025 shdr_info[cnt].shdr.sh_flags = 0;
1026 shdr_info[cnt].shdr.sh_addr = 0;
1027 shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1028 shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1029 shdr_info[cnt].shdr.sh_entsize = 0;
1030 shdr_info[cnt].shdr.sh_addralign = 4;
1031 /* We set the offset to zero here. Before we write the ELF file the
1032 field must have the correct value. This is done in the final
1033 loop over all section. Then we have all the information needed. */
1034 shdr_info[cnt].shdr.sh_offset = 0;
1035
1036 /* Create the section. */
1037 shdr_info[cnt].newscn = elf_newscn (newelf);
1038 if (shdr_info[cnt].newscn == NULL)
1039 error (EXIT_FAILURE, 0,
1040 gettext ("while create section header section: %s"),
1041 elf_errmsg (-1));
1042 assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
1043
1044 shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
1045 if (shdr_info[cnt].data == NULL)
1046 error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
1047 elf_errmsg (-1));
1048
1049 char *debug_basename = basename (debug_fname_embed ?: debug_fname);
1050 off_t crc_offset = strlen (debug_basename) + 1;
1051 /* Align to 4 byte boundary */
1052 crc_offset = ((crc_offset - 1) & ~3) + 4;
1053
1054 shdr_info[cnt].data->d_align = 4;
1055 shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
1056 = crc_offset + 4;
1057 shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
1058
1059 strcpy (shdr_info[cnt].data->d_buf, debug_basename);
1060
1061 /* Cache this Elf_Data describing the CRC32 word in the section.
1062 We'll fill this in when we have written the debug file. */
1063 debuglink_crc_data = *shdr_info[cnt].data;
1064 debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
1065 + crc_offset);
1066 debuglink_crc_data.d_size = 4;
1067
1068 /* One more section done. */
1069 ++cnt;
1070 }
1071
1072 /* Index of the section header table in the shdr_info array. */
1073 shdridx = cnt;
1074
1075 /* Add the section header string table section name. */
1076 shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
1077 shdr_info[cnt].idx = idx;
1078
1079 /* Create the section header. */
1080 shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
1081 shdr_info[cnt].shdr.sh_flags = 0;
1082 shdr_info[cnt].shdr.sh_addr = 0;
1083 shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1084 shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1085 shdr_info[cnt].shdr.sh_entsize = 0;
1086 /* We set the offset to zero here. Before we write the ELF file the
1087 field must have the correct value. This is done in the final
1088 loop over all section. Then we have all the information needed. */
1089 shdr_info[cnt].shdr.sh_offset = 0;
1090 shdr_info[cnt].shdr.sh_addralign = 1;
1091
1092 /* Create the section. */
1093 shdr_info[cnt].newscn = elf_newscn (newelf);
1094 if (shdr_info[cnt].newscn == NULL)
1095 error (EXIT_FAILURE, 0,
1096 gettext ("while create section header section: %s"),
1097 elf_errmsg (-1));
1098 assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1099
1100 /* Finalize the string table and fill in the correct indices in the
1101 section headers. */
1102 shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1103 if (shstrtab_data == NULL)
1104 error (EXIT_FAILURE, 0,
1105 gettext ("while create section header string table: %s"),
1106 elf_errmsg (-1));
1107 ebl_strtabfinalize (shst, shstrtab_data);
1108
1109 /* We have to set the section size. */
1110 shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1111
1112 /* Update the section information. */
1113 GElf_Off lastoffset = 0;
1114 for (cnt = 1; cnt <= shdridx; ++cnt)
1115 if (shdr_info[cnt].idx > 0)
1116 {
1117 Elf_Data *newdata;
1118
1119 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1120 assert (scn != NULL);
1121
1122 /* Update the name. */
1123 shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1124
1125 /* Update the section header from the input file. Some fields
1126 might be section indeces which now have to be adjusted. */
1127 if (shdr_info[cnt].shdr.sh_link != 0)
1128 shdr_info[cnt].shdr.sh_link =
1129 shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1130
1131 if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1132 {
1133 assert (shdr_info[cnt].data != NULL);
1134
1135 Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1136 for (size_t inner = 0;
1137 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1138 ++inner)
1139 grpref[inner] = shdr_info[grpref[inner]].idx;
1140 }
1141
1142 /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
1143 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1144 shdr_info[cnt].shdr.sh_info =
1145 shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1146
1147 /* Get the data from the old file if necessary. We already
1148 created the data for the section header string table. */
1149 if (cnt < shnum)
1150 {
1151 if (shdr_info[cnt].data == NULL)
1152 {
1153 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1154 if (shdr_info[cnt].data == NULL)
1155 INTERNAL_ERROR (fname);
1156 }
1157
1158 /* Set the data. This is done by copying from the old file. */
1159 newdata = elf_newdata (scn);
1160 if (newdata == NULL)
1161 INTERNAL_ERROR (fname);
1162
1163 /* Copy the structure. */
1164 *newdata = *shdr_info[cnt].data;
1165
1166 /* We know the size. */
1167 shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1168
1169 /* We have to adjust symbol tables. The st_shndx member might
1170 have to be updated. */
1171 if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1172 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1173 {
1174 Elf_Data *versiondata = NULL;
1175 Elf_Data *shndxdata = NULL;
1176
1177 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1178 ehdr->e_version);
1179
1180 if (shdr_info[cnt].symtab_idx != 0)
1181 {
1182 assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1183 /* This section has extended section information.
1184 We have to modify that information, too. */
1185 shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1186 NULL);
1187
1188 assert ((versiondata->d_size / sizeof (Elf32_Word))
1189 >= shdr_info[cnt].data->d_size / elsize);
1190 }
1191
1192 if (shdr_info[cnt].version_idx != 0)
1193 {
1194 assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1195 /* This section has associated version
1196 information. We have to modify that
1197 information, too. */
1198 versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1199 NULL);
1200
1201 assert ((versiondata->d_size / sizeof (GElf_Versym))
1202 >= shdr_info[cnt].data->d_size / elsize);
1203 }
1204
1205 shdr_info[cnt].newsymidx
1206 = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1207 / elsize, sizeof (Elf32_Word));
1208
1209 bool last_was_local = true;
1210 size_t destidx;
1211 size_t inner;
1212 for (destidx = inner = 1;
1213 inner < shdr_info[cnt].data->d_size / elsize;
1214 ++inner)
1215 {
1216 Elf32_Word sec;
1217 GElf_Sym sym_mem;
1218 Elf32_Word xshndx;
1219 GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1220 shndxdata, inner,
1221 &sym_mem, &xshndx);
1222 if (sym == NULL)
1223 INTERNAL_ERROR (fname);
1224
1225 if (sym->st_shndx == SHN_UNDEF
1226 || (sym->st_shndx >= shnum
1227 && sym->st_shndx != SHN_XINDEX))
1228 {
1229 /* This is no section index, leave it alone
1230 unless it is moved. */
1231 if (destidx != inner
1232 && gelf_update_symshndx (shdr_info[cnt].data,
1233 shndxdata,
1234 destidx, sym,
1235 xshndx) == 0)
1236 INTERNAL_ERROR (fname);
1237
1238 shdr_info[cnt].newsymidx[inner] = destidx++;
1239
1240 if (last_was_local
1241 && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1242 {
1243 last_was_local = false;
1244 shdr_info[cnt].shdr.sh_info = destidx - 1;
1245 }
1246
1247 continue;
1248 }
1249
1250 /* Get the full section index, if necessary from the
1251 XINDEX table. */
1252 if (sym->st_shndx != SHN_XINDEX)
1253 sec = shdr_info[sym->st_shndx].idx;
1254 else
1255 {
1256 assert (shndxdata != NULL);
1257
1258 sec = shdr_info[xshndx].idx;
1259 }
1260
1261 if (sec != 0)
1262 {
1263 GElf_Section nshndx;
1264 Elf32_Word nxshndx;
1265
1266 if (sec < SHN_LORESERVE)
1267 {
1268 nshndx = sec;
1269 nxshndx = 0;
1270 }
1271 else
1272 {
1273 nshndx = SHN_XINDEX;
1274 nxshndx = sec;
1275 }
1276
1277 assert (sec < SHN_LORESERVE || shndxdata != NULL);
1278
1279 if ((inner != destidx || nshndx != sym->st_shndx
1280 || (shndxdata != NULL && nxshndx != xshndx))
1281 && (sym->st_shndx = nshndx,
1282 gelf_update_symshndx (shdr_info[cnt].data,
1283 shndxdata,
1284 destidx, sym,
1285 nxshndx) == 0))
1286 INTERNAL_ERROR (fname);
1287
1288 shdr_info[cnt].newsymidx[inner] = destidx++;
1289
1290 if (last_was_local
1291 && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1292 {
1293 last_was_local = false;
1294 shdr_info[cnt].shdr.sh_info = destidx - 1;
1295 }
1296 }
1297 else if (debug_fname == NULL
1298 || shdr_info[cnt].debug_data == NULL)
1299 /* This is a section or group signature symbol
1300 for a section which has been removed. */
1301 {
1302 size_t sidx = (sym->st_shndx != SHN_XINDEX
1303 ? sym->st_shndx : xshndx);
1304 assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
1305 || (shdr_info[sidx].shdr.sh_type == SHT_GROUP
1306 && shdr_info[sidx].shdr.sh_info == inner));
1307 }
1308 }
1309
1310 if (destidx != inner)
1311 {
1312 /* The size of the symbol table changed. */
1313 shdr_info[cnt].shdr.sh_size = newdata->d_size
1314 = destidx * elsize;
1315 any_symtab_changes = true;
1316 }
1317 else
1318 {
1319 /* The symbol table didn't really change. */
1320 free (shdr_info[cnt].newsymidx);
1321 shdr_info[cnt].newsymidx = NULL;
1322 }
1323 }
1324 }
1325
1326 /* If we have to, compute the offset of the section. */
1327 if (shdr_info[cnt].shdr.sh_offset == 0)
1328 shdr_info[cnt].shdr.sh_offset
1329 = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1330 & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1331
1332 /* Set the section header in the new file. */
1333 if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1334 /* There cannot be any overflows. */
1335 INTERNAL_ERROR (fname);
1336
1337 /* Remember the last section written so far. */
1338 GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1339 ? shdr_info[cnt].shdr.sh_size : 0);
1340 if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1341 lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1342 }
1343
1344 /* Adjust symbol references if symbol tables changed. */
1345 if (any_symtab_changes)
1346 /* Find all relocation sections which use this symbol table. */
1347 for (cnt = 1; cnt <= shdridx; ++cnt)
1348 {
1349 /* Update section headers when the data size has changed.
1350 We also update the SHT_NOBITS section in the debug
1351 file so that the section headers match in sh_size. */
1352 inline void update_section_size (const Elf_Data *newdata)
1353 {
1354 GElf_Shdr shdr_mem;
1355 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1356 shdr->sh_size = newdata->d_size;
1357 (void) gelf_update_shdr (scn, shdr);
1358 if (debugelf != NULL)
1359 {
1360 /* libelf will use d_size to set sh_size. */
1361 Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
1362 cnt), NULL);
1363 debugdata->d_size = newdata->d_size;
1364 }
1365 }
1366
1367 if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
1368 /* Ignore sections which are discarded. When we are saving a
1369 relocation section in a separate debug file, we must fix up
1370 the symbol table references. */
1371 continue;
1372
1373 const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1374 const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
1375 switch (shdr_info[cnt].shdr.sh_type)
1376 {
1377 inline bool no_symtab_updates (void)
1378 {
1379 /* If the symbol table hasn't changed, do not do anything. */
1380 if (shdr_info[symtabidx].newsymidx == NULL)
1381 return true;
1382
1383 /* If the symbol table is not discarded, but additionally
1384 duplicated in the separate debug file and this section
1385 is discarded, don't adjust anything. */
1386 return (shdr_info[cnt].idx == 0
1387 && shdr_info[symtabidx].debug_data != NULL);
1388 }
1389
1390 case SHT_REL:
1391 case SHT_RELA:
1392 if (no_symtab_updates ())
1393 break;
1394
1395 Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
1396 ? elf_getscn (debugelf, cnt)
1397 : elf_getscn (newelf,
1398 shdr_info[cnt].idx),
1399 NULL);
1400 assert (d != NULL);
1401 size_t nrels = (shdr_info[cnt].shdr.sh_size
1402 / shdr_info[cnt].shdr.sh_entsize);
1403
1404 if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1405 for (size_t relidx = 0; relidx < nrels; ++relidx)
1406 {
1407 GElf_Rel rel_mem;
1408 if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1409 INTERNAL_ERROR (fname);
1410
1411 size_t symidx = GELF_R_SYM (rel_mem.r_info);
1412 if (newsymidx[symidx] != symidx)
1413 {
1414 rel_mem.r_info
1415 = GELF_R_INFO (newsymidx[symidx],
1416 GELF_R_TYPE (rel_mem.r_info));
1417
1418 if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1419 INTERNAL_ERROR (fname);
1420 }
1421 }
1422 else
1423 for (size_t relidx = 0; relidx < nrels; ++relidx)
1424 {
1425 GElf_Rela rel_mem;
1426 if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1427 INTERNAL_ERROR (fname);
1428
1429 size_t symidx = GELF_R_SYM (rel_mem.r_info);
1430 if (newsymidx[symidx] != symidx)
1431 {
1432 rel_mem.r_info
1433 = GELF_R_INFO (newsymidx[symidx],
1434 GELF_R_TYPE (rel_mem.r_info));
1435
1436 if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1437 INTERNAL_ERROR (fname);
1438 }
1439 }
1440 break;
1441
1442 case SHT_HASH:
1443 if (no_symtab_updates ())
1444 break;
1445
1446 /* We have to recompute the hash table. */
1447
1448 assert (shdr_info[cnt].idx > 0);
1449
1450 /* The hash section in the new file. */
1451 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1452
1453 /* The symbol table data. */
1454 Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1455 shdr_info[symtabidx].idx),
1456 NULL);
1457 assert (symd != NULL);
1458
1459 /* The hash table data. */
1460 Elf_Data *hashd = elf_getdata (scn, NULL);
1461 assert (hashd != NULL);
1462
1463 if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1464 {
1465 /* Sane arches first. */
1466 Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1467
1468 size_t strshndx = shdr_info[symtabidx].old_sh_link;
1469 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1470 ehdr->e_version);
1471
1472 /* Adjust the nchain value. The symbol table size
1473 changed. We keep the same size for the bucket array. */
1474 bucket[1] = symd->d_size / elsize;
1475 Elf32_Word nbucket = bucket[0];
1476 bucket += 2;
1477 Elf32_Word *chain = bucket + nbucket;
1478
1479 /* New size of the section. */
1480 hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
1481 * sizeof (Elf32_Word));
1482 update_section_size (hashd);
1483
1484 /* Clear the arrays. */
1485 memset (bucket, '\0',
1486 (symd->d_size / elsize + nbucket)
1487 * sizeof (Elf32_Word));
1488
1489 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1490 inner < symd->d_size / elsize; ++inner)
1491 {
1492 GElf_Sym sym_mem;
1493 GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1494 assert (sym != NULL);
1495
1496 const char *name = elf_strptr (elf, strshndx,
1497 sym->st_name);
1498 assert (name != NULL);
1499 size_t hidx = elf_hash (name) % nbucket;
1500
1501 if (bucket[hidx] == 0)
1502 bucket[hidx] = inner;
1503 else
1504 {
1505 hidx = bucket[hidx];
1506
1507 while (chain[hidx] != 0)
1508 hidx = chain[hidx];
1509
1510 chain[hidx] = inner;
1511 }
1512 }
1513 }
1514 else
1515 {
1516 /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
1517 assert (shdr_info[cnt].shdr.sh_entsize
1518 == sizeof (Elf64_Xword));
1519
1520 Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1521
1522 size_t strshndx = shdr_info[symtabidx].old_sh_link;
1523 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1524 ehdr->e_version);
1525
1526 /* Adjust the nchain value. The symbol table size
1527 changed. We keep the same size for the bucket array. */
1528 bucket[1] = symd->d_size / elsize;
1529 Elf64_Xword nbucket = bucket[0];
1530 bucket += 2;
1531 Elf64_Xword *chain = bucket + nbucket;
1532
1533 /* New size of the section. */
1534 hashd->d_size = ((2 + symd->d_size / elsize + nbucket)
1535 * sizeof (Elf64_Xword));
1536 update_section_size (hashd);
1537
1538 /* Clear the arrays. */
1539 memset (bucket, '\0',
1540 (symd->d_size / elsize + nbucket)
1541 * sizeof (Elf64_Xword));
1542
1543 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1544 inner < symd->d_size / elsize; ++inner)
1545 {
1546 GElf_Sym sym_mem;
1547 GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1548 assert (sym != NULL);
1549
1550 const char *name = elf_strptr (elf, strshndx,
1551 sym->st_name);
1552 assert (name != NULL);
1553 size_t hidx = elf_hash (name) % nbucket;
1554
1555 if (bucket[hidx] == 0)
1556 bucket[hidx] = inner;
1557 else
1558 {
1559 hidx = bucket[hidx];
1560
1561 while (chain[hidx] != 0)
1562 hidx = chain[hidx];
1563
1564 chain[hidx] = inner;
1565 }
1566 }
1567 }
1568 break;
1569
1570 case SHT_GNU_versym:
1571 /* If the symbol table changed we have to adjust the entries. */
1572 if (no_symtab_updates ())
1573 break;
1574
1575 assert (shdr_info[cnt].idx > 0);
1576
1577 /* The symbol version section in the new file. */
1578 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1579
1580 /* The symbol table data. */
1581 symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
1582 NULL);
1583 assert (symd != NULL);
1584
1585 /* The version symbol data. */
1586 Elf_Data *verd = elf_getdata (scn, NULL);
1587 assert (verd != NULL);
1588
1589 /* The symbol version array. */
1590 GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1591
1592 /* Walk through the list and */
1593 size_t elsize = gelf_fsize (elf, verd->d_type, 1,
1594 ehdr->e_version);
1595 for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
1596 if (newsymidx[inner] != 0)
1597 /* Overwriting the same array works since the
1598 reordering can only move entries to lower indices
1599 in the array. */
1600 verstab[newsymidx[inner]] = verstab[inner];
1601
1602 /* New size of the section. */
1603 verd->d_size = gelf_fsize (newelf, verd->d_type,
1604 symd->d_size
1605 / gelf_fsize (elf, symd->d_type, 1,
1606 ehdr->e_version),
1607 ehdr->e_version);
1608 update_section_size (verd);
1609 break;
1610
1611 case SHT_GROUP:
1612 if (no_symtab_updates ())
1613 break;
1614
1615 /* Yes, the symbol table changed.
1616 Update the section header of the section group. */
1617 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1618 GElf_Shdr shdr_mem;
1619 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1620 assert (shdr != NULL);
1621
1622 shdr->sh_info = newsymidx[shdr->sh_info];
1623
1624 (void) gelf_update_shdr (scn, shdr);
1625 break;
1626 }
1627 }
1628
1629 /* Remove any relocations between debug sections in ET_REL
1630 for the debug file when requested. These relocations are always
1631 zero based between the unallocated sections. */
1632 if (debug_fname != NULL && reloc_debug && ehdr->e_type == ET_REL)
1633 {
1634 scn = NULL;
1635 cnt = 0;
1636 while ((scn = elf_nextscn (debugelf, scn)) != NULL)
1637 {
1638 cnt++;
1639 /* We need the actual section and header from the debugelf
1640 not just the cached original in shdr_info because we
1641 might want to change the size. */
1642 GElf_Shdr shdr_mem;
1643 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1644 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
1645 {
1646 /* Make sure that this relocation section points to a
1647 section to relocate with contents, that isn't
1648 allocated and that is a debug section. */
1649 Elf_Scn *tscn = elf_getscn (debugelf, shdr->sh_info);
1650 GElf_Shdr tshdr_mem;
1651 GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
1652 if (tshdr->sh_type == SHT_NOBITS
1653 || tshdr->sh_size == 0
1654 || (tshdr->sh_flags & SHF_ALLOC) != 0)
1655 continue;
1656
1657 const char *tname = elf_strptr (debugelf, shstrndx,
1658 tshdr->sh_name);
1659 if (! tname || ! ebl_debugscn_p (ebl, tname))
1660 continue;
1661
1662 /* OK, lets relocate all trivial cross debug section
1663 relocations. */
1664 Elf_Data *reldata = elf_getdata (scn, NULL);
1665 /* We actually wanted the rawdata, but since we already
1666 accessed it earlier as elf_getdata () that won't
1667 work. But debug sections are all ELF_T_BYTE, so it
1668 doesn't really matter. */
1669 Elf_Data *tdata = elf_getdata (tscn, NULL);
1670 if (tdata->d_type != ELF_T_BYTE)
1671 INTERNAL_ERROR (fname);
1672
1673 /* Pick up the symbol table and shndx table to
1674 resolve relocation symbol indexes. */
1675 Elf64_Word symt = shdr->sh_link;
1676 Elf_Data *symdata, *xndxdata;
1677 symdata = (shdr_info[symt].debug_data
1678 ?: shdr_info[symt].data);
1679 xndxdata = (shdr_info[shdr_info[symt].symtab_idx].debug_data
1680 ?: shdr_info[shdr_info[symt].symtab_idx].data);
1681
1682 /* Apply one relocation. Returns true when trivial
1683 relocation actually done. */
1684 bool relocate (GElf_Addr offset, const GElf_Sxword addend,
1685 bool is_rela, int rtype, int symndx)
1686 {
1687 /* R_*_NONE relocs can always just be removed. */
1688 if (rtype == 0)
1689 return true;
1690
1691 /* We only do simple absolute relocations. */
1692 Elf_Type type = ebl_reloc_simple_type (ebl, rtype);
1693 if (type == ELF_T_NUM)
1694 return false;
1695
1696 /* These are the types we can relocate. */
1697#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \
1698 DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
1699 DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
1700
1701 /* And only for relocations against other debug sections. */
1702 GElf_Sym sym_mem;
1703 Elf32_Word xndx;
1704 GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
1705 symndx, &sym_mem,
1706 &xndx);
1707 Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
1708 ? xndx : sym->st_shndx);
1709 if (ebl_debugscn_p (ebl, shdr_info[sec].name))
1710 {
1711 size_t size;
1712
1713#define DO_TYPE(NAME, Name) GElf_##Name Name;
1714 union { TYPES; } tmpbuf;
1715#undef DO_TYPE
1716
1717 switch (type)
1718 {
1719#define DO_TYPE(NAME, Name) \
1720 case ELF_T_##NAME: \
1721 size = sizeof (GElf_##Name); \
1722 tmpbuf.Name = 0; \
1723 break;
1724 TYPES;
1725#undef DO_TYPE
1726 default:
1727 return false;
1728 }
1729
1730 if (offset > tdata->d_size
1731 || tdata->d_size - offset < size)
1732 error (0, 0, gettext ("bad relocation"));
1733
1734 /* When the symbol value is zero then for SHT_REL
1735 sections this is all that needs to be checked.
1736 The addend is contained in the original data at
1737 the offset already. So if the (section) symbol
1738 address is zero and the given addend is zero
1739 just remove the relocation, it isn't needed
1740 anymore. */
1741 if (addend == 0 && sym->st_value == 0)
1742 return true;
1743
1744 Elf_Data tmpdata =
1745 {
1746 .d_type = type,
1747 .d_buf = &tmpbuf,
1748 .d_size = size,
1749 .d_version = EV_CURRENT,
1750 };
1751 Elf_Data rdata =
1752 {
1753 .d_type = type,
1754 .d_buf = tdata->d_buf + offset,
1755 .d_size = size,
1756 .d_version = EV_CURRENT,
1757 };
1758
1759 GElf_Addr value = sym->st_value;
1760 if (is_rela)
1761 {
1762 /* For SHT_RELA sections we just take the
1763 given addend and add it to the value. */
1764 value += addend;
1765 }
1766 else
1767 {
1768 /* For SHT_REL sections we have to peek at
1769 what is already in the section at the given
1770 offset to get the addend. */
1771 Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata,
1772 &rdata,
1773 ehdr->e_ident[EI_DATA]);
1774 if (d == NULL)
1775 INTERNAL_ERROR (fname);
1776 assert (d == &tmpdata);
1777 }
1778
1779 switch (type)
1780 {
1781#define DO_TYPE(NAME, Name) \
1782 case ELF_T_##NAME: \
1783 tmpbuf.Name += (GElf_##Name) value; \
1784 break;
1785 TYPES;
1786#undef DO_TYPE
1787 default:
1788 abort ();
1789 }
1790
1791 /* Now finally put in the new value. */
1792 Elf_Data *s = gelf_xlatetof (debugelf, &rdata,
1793 &tmpdata,
1794 ehdr->e_ident[EI_DATA]);
1795 if (s == NULL)
1796 INTERNAL_ERROR (fname);
1797 assert (s == &rdata);
1798
1799 return true;
1800 }
1801 return false;
1802 }
1803
1804 size_t nrels = shdr->sh_size / shdr->sh_entsize;
1805 size_t next = 0;
1806 if (shdr->sh_type == SHT_REL)
1807 for (size_t relidx = 0; relidx < nrels; ++relidx)
1808 {
1809 GElf_Rel rel_mem;
1810 GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
1811 if (! relocate (r->r_offset, 0, false,
1812 GELF_R_TYPE (r->r_info),
1813 GELF_R_SYM (r->r_info)))
1814 {
1815 if (relidx != next)
1816 gelf_update_rel (reldata, next, r);
1817 ++next;
1818 }
1819 }
1820 else
1821 for (size_t relidx = 0; relidx < nrels; ++relidx)
1822 {
1823 GElf_Rela rela_mem;
1824 GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
1825 if (! relocate (r->r_offset, r->r_addend, true,
1826 GELF_R_TYPE (r->r_info),
1827 GELF_R_SYM (r->r_info)))
1828 {
1829 if (relidx != next)
1830 gelf_update_rela (reldata, next, r);
1831 ++next;
1832 }
1833 }
1834
1835 nrels = next;
1836 shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
1837 gelf_update_shdr (scn, shdr);
1838 }
1839 }
1840 }
1841
1842 /* Now that we have done all adjustments to the data,
1843 we can actually write out the debug file. */
1844 if (debug_fname != NULL)
1845 {
1846 /* Finally write the file. */
1847 if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
1848 {
1849 error (0, 0, gettext ("while writing '%s': %s"),
1850 debug_fname, elf_errmsg (-1));
1851 result = 1;
1852 goto fail_close;
1853 }
1854
1855 /* Create the real output file. First rename, then change the
1856 mode. */
1857 if (rename (tmp_debug_fname, debug_fname) != 0
1858 || fchmod (debug_fd, mode) != 0)
1859 {
1860 error (0, errno, gettext ("while creating '%s'"), debug_fname);
1861 result = 1;
1862 goto fail_close;
1863 }
1864
1865 /* The temporary file does not exist anymore. */
1866 tmp_debug_fname = NULL;
1867
1868 if (!remove_shdrs)
1869 {
1870 uint32_t debug_crc;
1871 Elf_Data debug_crc_data =
1872 {
1873 .d_type = ELF_T_WORD,
1874 .d_buf = &debug_crc,
1875 .d_size = sizeof (debug_crc),
1876 .d_version = EV_CURRENT
1877 };
1878
1879 /* Compute the checksum which we will add to the executable. */
1880 if (crc32_file (debug_fd, &debug_crc) != 0)
1881 {
1882 error (0, errno, gettext ("\
1883while computing checksum for debug information"));
1884 unlink (debug_fname);
1885 result = 1;
1886 goto fail_close;
1887 }
1888
1889 /* Store it in the debuglink section data. */
1890 if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
1891 &debug_crc_data, ehdr->e_ident[EI_DATA])
1892 != &debuglink_crc_data))
1893 INTERNAL_ERROR (fname);
1894 }
1895 }
1896
1897 /* Finally finish the ELF header. Fill in the fields not handled by
1898 libelf from the old file. */
1899 newehdr = gelf_getehdr (newelf, &newehdr_mem);
1900 if (newehdr == NULL)
1901 INTERNAL_ERROR (fname);
1902
1903 memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1904 newehdr->e_type = ehdr->e_type;
1905 newehdr->e_machine = ehdr->e_machine;
1906 newehdr->e_version = ehdr->e_version;
1907 newehdr->e_entry = ehdr->e_entry;
1908 newehdr->e_flags = ehdr->e_flags;
1909 newehdr->e_phoff = ehdr->e_phoff;
1910
1911 /* We need to position the section header table. */
1912 const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1913 newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
1914 + shdr_info[shdridx].shdr.sh_size + offsize - 1)
1915 & ~((GElf_Off) (offsize - 1)));
1916 newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1917
1918 /* The new section header string table index. */
1919 if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
1920 newehdr->e_shstrndx = idx;
1921 else
1922 {
1923 /* The index does not fit in the ELF header field. */
1924 shdr_info[0].scn = elf_getscn (elf, 0);
1925
1926 if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
1927 INTERNAL_ERROR (fname);
1928
1929 shdr_info[0].shdr.sh_link = idx;
1930 (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
1931
1932 newehdr->e_shstrndx = SHN_XINDEX;
1933 }
1934
1935 if (gelf_update_ehdr (newelf, newehdr) == 0)
1936 {
1937 error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1938 fname, elf_errmsg (-1));
1939 return 1;
1940 }
1941
1942 /* We have everything from the old file. */
1943 if (elf_cntl (elf, ELF_C_FDDONE) != 0)
1944 {
1945 error (0, 0, gettext ("%s: error while reading the file: %s"),
1946 fname, elf_errmsg (-1));
1947 return 1;
1948 }
1949
1950 /* The ELF library better follows our layout when this is not a
1951 relocatable object file. */
1952 elf_flagelf (newelf, ELF_C_SET,
1953 (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
1954 | (permissive ? ELF_F_PERMISSIVE : 0));
1955
1956 /* Finally write the file. */
1957 if (elf_update (newelf, ELF_C_WRITE) == -1)
1958 {
1959 error (0, 0, gettext ("while writing '%s': %s"),
1960 fname, elf_errmsg (-1));
1961 result = 1;
1962 }
1963
1964 if (remove_shdrs)
1965 {
1966 /* libelf can't cope without the section headers being properly intact.
1967 So we just let it write them normally, and then we nuke them later. */
1968
1969 if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
1970 {
1971 assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
1972 == offsetof (Elf32_Ehdr, e_shnum));
1973 assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
1974 == offsetof (Elf32_Ehdr, e_shstrndx));
1975 const Elf32_Off zero_off = 0;
1976 const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
1977 if (pwrite_retry (fd, &zero_off, sizeof zero_off,
1978 offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
1979 || (pwrite_retry (fd, zero, sizeof zero,
1980 offsetof (Elf32_Ehdr, e_shentsize))
1981 != sizeof zero)
1982 || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
1983 {
1984 error (0, errno, gettext ("while writing '%s'"),
1985 fname);
1986 result = 1;
1987 }
1988 }
1989 else
1990 {
1991 assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
1992 == offsetof (Elf64_Ehdr, e_shnum));
1993 assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
1994 == offsetof (Elf64_Ehdr, e_shstrndx));
1995 const Elf64_Off zero_off = 0;
1996 const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
1997 if (pwrite_retry (fd, &zero_off, sizeof zero_off,
1998 offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
1999 || (pwrite_retry (fd, zero, sizeof zero,
2000 offsetof (Elf64_Ehdr, e_shentsize))
2001 != sizeof zero)
2002 || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
2003 {
2004 error (0, errno, gettext ("while writing '%s'"),
2005 fname);
2006 result = 1;
2007 }
2008 }
2009 }
2010
2011 fail_close:
2012 if (shdr_info != NULL)
2013 {
2014 /* For some sections we might have created an table to map symbol
2015 table indices. */
2016 if (any_symtab_changes)
2017 for (cnt = 1; cnt <= shdridx; ++cnt)
2018 {
2019 free (shdr_info[cnt].newsymidx);
2020 if (shdr_info[cnt].debug_data != NULL)
2021 free (shdr_info[cnt].debug_data->d_buf);
2022 }
2023
2024 /* Free the memory. */
2025 if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
2026 free (shdr_info);
2027 }
2028
2029 /* Free other resources. */
2030 if (shstrtab_data != NULL)
2031 free (shstrtab_data->d_buf);
2032 if (shst != NULL)
2033 ebl_strtabfree (shst);
2034
2035 /* That was it. Close the descriptors. */
2036 if (elf_end (newelf) != 0)
2037 {
2038 error (0, 0, gettext ("error while finishing '%s': %s"), fname,
2039 elf_errmsg (-1));
2040 result = 1;
2041 }
2042
2043 if (debugelf != NULL && elf_end (debugelf) != 0)
2044 {
2045 error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
2046 elf_errmsg (-1));
2047 result = 1;
2048 }
2049
2050 fail:
2051 /* Close the EBL backend. */
2052 if (ebl != NULL)
2053 ebl_closebackend (ebl);
2054
2055 /* Close debug file descriptor, if opened */
2056 if (debug_fd >= 0)
2057 {
2058 if (tmp_debug_fname != NULL)
2059 unlink (tmp_debug_fname);
2060 close (debug_fd);
2061 }
2062
2063 /* If requested, preserve the timestamp. */
2064 if (tvp != NULL)
2065 {
2066 if (futimes (fd, tvp) != 0)
2067 {
2068 error (0, errno, gettext ("\
2069cannot set access and modification date of '%s'"),
2070 output_fname ?: fname);
2071 result = 1;
2072 }
2073 }
2074
2075 /* Close the file descriptor if we created a new file. */
2076 if (output_fname != NULL)
2077 close (fd);
2078
2079 return result;
2080}
2081
2082
2083static int
2084handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
2085 struct timeval tvp[2])
2086{
2087 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
2088 size_t fname_len = strlen (fname) + 1;
2089 char new_prefix[prefix_len + 1 + fname_len];
2090 char *cp = new_prefix;
2091
2092 /* Create the full name of the file. */
2093 if (prefix != NULL)
2094 {
2095 cp = mempcpy (cp, prefix, prefix_len);
2096 *cp++ = ':';
2097 }
2098 memcpy (cp, fname, fname_len);
2099
2100
2101 /* Process all the files contained in the archive. */
2102 Elf *subelf;
2103 Elf_Cmd cmd = ELF_C_RDWR;
2104 int result = 0;
2105 while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
2106 {
2107 /* The the header for this element. */
2108 Elf_Arhdr *arhdr = elf_getarhdr (subelf);
2109
2110 if (elf_kind (subelf) == ELF_K_ELF)
2111 result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
2112 else if (elf_kind (subelf) == ELF_K_AR)
2113 result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
2114
2115 /* Get next archive element. */
2116 cmd = elf_next (subelf);
2117 if (unlikely (elf_end (subelf) != 0))
2118 INTERNAL_ERROR (fname);
2119 }
2120
2121 if (tvp != NULL)
2122 {
2123 if (unlikely (futimes (fd, tvp) != 0))
2124 {
2125 error (0, errno, gettext ("\
2126cannot set access and modification date of '%s'"), fname);
2127 result = 1;
2128 }
2129 }
2130
2131 if (unlikely (close (fd) != 0))
2132 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
2133
2134 return result;
2135}
2136
2137
2138#include "debugpred.h"