blob: 37f9eb0e089410eafaa4cfbac7ec042cf5345493 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Discard section not used at runtime from object files.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
4
5 This program is Open Source software; you can redistribute it and/or
6 modify it under the terms of the Open Software License version 1.0 as
7 published by the Open Source Initiative.
8
9 You should have received a copy of the Open Software License along
10 with this program; if not, you may obtain a copy of the Open Software
11 License version 1.0 from http://www.opensource.org/licenses/osl.php or
12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13 3001 King Ranch Road, Ukiah, CA 95482. */
14
15#ifdef HAVE_CONFIG_H
16# include <config.h>
17#endif
18
19#include <argp.h>
20#include <assert.h>
21#include <byteswap.h>
22#include <endian.h>
23#include <error.h>
24#include <fcntl.h>
25#include <gelf.h>
26#include <libelf.h>
27#include <libintl.h>
28#include <locale.h>
29#include <mcheck.h>
30#include <stdbool.h>
31#include <stdio.h>
32#include <stdio_ext.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <sys/param.h>
37#include <sys/time.h>
38
39#include <elf-knowledge.h>
40#include <libebl.h>
41#include <system.h>
42
43
44/* Name and version of program. */
45static void print_version (FILE *stream, struct argp_state *state);
46void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
47
48/* Bug report address. */
49const char *argp_program_bug_address = PACKAGE_BUGREPORT;
50
51
52/* Values for the parameters which have no short form. */
53#define OPT_REMOVE_COMMENT 0x100
54#define OPT_PERMISSIVE 0x101
55
56
57/* Definitions of arguments for argp functions. */
58static const struct argp_option options[] =
59{
60 { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
61 { NULL, 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
62 { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
63 { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
64
65 { NULL, 0, NULL, 0, N_("Output options:"), 0 },
Roland McGrath8f31c2c2005-08-09 04:58:05 +000066 { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000067 { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
Roland McGrath8f31c2c2005-08-09 04:58:05 +000068 { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
69 { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000070 { "preserve-dates", 'p', NULL, 0,
71 N_("Copy modified/access timestamps to the output"), 0 },
72 { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
73 N_("Remove .comment section"), 0 },
Roland McGrath8f31c2c2005-08-09 04:58:05 +000074 { "remove-section", 'R', "SECTION", OPTION_HIDDEN, NULL, 0 },
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000075 { "permissive", OPT_PERMISSIVE, NULL, 0,
76 N_("Relax a few rules to handle slightly broken ELF files"), 0 },
77 { NULL, 0, NULL, 0, NULL, 0 }
78};
79
80/* Short description of program. */
81static const char doc[] = N_("Discard symbols from object files.");
82
83/* Strings for arguments in help texts. */
84static const char args_doc[] = N_("[FILE...]");
85
86/* Prototype for option handler. */
87static error_t parse_opt (int key, char *arg, struct argp_state *state);
88
89/* Data structure to communicate with argp functions. */
90static struct argp argp =
91{
92 options, parse_opt, args_doc, doc, NULL, NULL, NULL
93};
94
95
96/* Print symbols in file named FNAME. */
97static int process_file (const char *fname);
98
99/* Handle one ELF file. */
100static int handle_elf (int fd, Elf *elf, const char *prefix,
101 const char *fname, mode_t mode, struct timeval tvp[2]);
102
103/* Handle all files contained in the archive. */
104static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
105 struct timeval tvp[2]);
106
107#define INTERNAL_ERROR(fname) \
108 error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
109 fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
110
111
112/* Name of the output file. */
113static const char *output_fname;
114
115/* Name of the debug output file. */
116static const char *debug_fname;
117
118/* Name to pretend the debug output file has. */
119static const char *debug_fname_embed;
120
121/* If true output files shall have same date as the input file. */
122static bool preserve_dates;
123
124/* If true .comment sections will be removed. */
125static bool remove_comment;
126
127/* If true remove all debug sections. */
128static bool remove_debug;
129
130/* If true relax some ELF rules for input files. */
131static bool permissive;
132
133
134int
135main (int argc, char *argv[])
136{
137 int remaining;
138 int result = 0;
139
140 /* Make memory leak detection possible. */
141 mtrace ();
142
143 /* We use no threads here which can interfere with handling a stream. */
144 __fsetlocking (stdin, FSETLOCKING_BYCALLER);
145 __fsetlocking (stdout, FSETLOCKING_BYCALLER);
146 __fsetlocking (stderr, FSETLOCKING_BYCALLER);
147
148 /* Set locale. */
149 setlocale (LC_ALL, "");
150
151 /* Make sure the message catalog can be found. */
152 bindtextdomain (PACKAGE, LOCALEDIR);
153
154 /* Initialize the message catalog. */
155 textdomain (PACKAGE);
156
157 /* Parse and process arguments. */
158 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
159 return EXIT_FAILURE;
160
161 /* Tell the library which version we are expecting. */
162 elf_version (EV_CURRENT);
163
164 if (remaining == argc)
165 /* The user didn't specify a name so we use a.out. */
166 result = process_file ("a.out");
167 else
168 {
169 /* If we have seen the '-o' or '-f' option there must be exactly one
170 input file. */
171 if ((output_fname != NULL || debug_fname != NULL)
172 && remaining + 1 < argc)
173 error (EXIT_FAILURE, 0, gettext ("\
174Only one input file allowed together with '-o' and '-f'"));
175
176 /* Process all the remaining files. */
177 do
178 result |= process_file (argv[remaining]);
179 while (++remaining < argc);
180 }
181
182 return result;
183}
184
185
186/* Print the version information. */
187static void
188print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
189{
190 fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, VERSION);
191 fprintf (stream, gettext ("\
192Copyright (C) %s Red Hat, Inc.\n\
193This is free software; see the source for copying conditions. There is NO\n\
194warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
195"), "2005");
196 fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
197}
198
199
200/* Handle program arguments. */
201static error_t
Roland McGrathce4550a2005-08-10 08:10:07 +0000202parse_opt (int key, char *arg,
203 struct argp_state *state __attribute__ ((unused)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000204{
205 switch (key)
206 {
207 case 'f':
208 if (debug_fname != NULL)
209 {
210 error (0, 0, gettext ("-f option specified twice"));
211 return EINVAL;
212 }
213 debug_fname = arg;
214 break;
215
216 case 'F':
217 if (debug_fname_embed != NULL)
218 {
219 error (0, 0, gettext ("-F option specified twice"));
220 return EINVAL;
221 }
222 debug_fname_embed = arg;
223 break;
224
225 case 'o':
226 if (output_fname != NULL)
227 {
228 error (0, 0, gettext ("-o option specified twice"));
229 return EINVAL;
230 }
231 output_fname = arg;
232 break;
233
234 case 'p':
235 preserve_dates = true;
236 break;
237
238 case OPT_REMOVE_COMMENT:
239 remove_comment = true;
240 break;
241
Roland McGrath8f31c2c2005-08-09 04:58:05 +0000242 case 'R':
243 if (!strcmp (arg, ".comment"))
244 remove_comment = true;
245 else
246 {
247 argp_error (state,
248 gettext ("-R option supports only .comment section"));
249 return EINVAL;
250 }
251 break;
252
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000253 case 'g':
Roland McGrath8f31c2c2005-08-09 04:58:05 +0000254 case 'd':
255 case 'S':
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000256 remove_debug = true;
257 break;
258
259 case OPT_PERMISSIVE:
260 permissive = true;
261 break;
262
Roland McGrath8f31c2c2005-08-09 04:58:05 +0000263 case 's': /* Ignored for compatibility. */
264 break;
265
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000266 default:
267 return ARGP_ERR_UNKNOWN;
268 }
269 return 0;
270}
271
272
273static int
274process_file (const char *fname)
275{
276 /* If we have to preserve the modify and access timestamps get them
277 now. We cannot use fstat() after opening the file since the open
278 would change the access time. */
279 struct stat64 pre_st;
280 struct timeval tv[2];
281 again:
282 if (preserve_dates)
283 {
284 if (stat64 (fname, &pre_st) != 0)
285 {
286 error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
287 return 1;
288 }
289
290 /* If we have to preserve the timestamp, we need it in the
291 format utimes() understands. */
292 TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
293 TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
294 }
295
296 /* Open the file. */
Roland McGrath095a01b2005-08-08 03:49:35 +0000297 int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000298 if (fd == -1)
299 {
300 error (0, errno, gettext ("while opening \"%s\""), fname);
301 return 1;
302 }
303
304 /* We always use fstat() even if we called stat() before. This is
305 done to make sure the information returned by stat() is for the
306 same file. */
307 struct stat64 st;
308 if (fstat64 (fd, &st) != 0)
309 {
310 error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
311 return 1;
312 }
313 /* Paranoid mode on. */
314 if (preserve_dates
315 && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
316 {
317 /* We detected a race. Try again. */
318 close (fd);
319 goto again;
320 }
321
322 /* Now get the ELF descriptor. */
Roland McGrath095a01b2005-08-08 03:49:35 +0000323 Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
324 NULL);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000325 int result;
326 switch (elf_kind (elf))
327 {
328 case ELF_K_ELF:
329 result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
330 preserve_dates ? tv : NULL);
331 break;
332
333 case ELF_K_AR:
334 /* It is not possible to strip the content of an archive direct
335 the output to a specific file. */
336 if (unlikely (output_fname != NULL))
337 {
338 error (0, 0, gettext ("%s: cannot use -o when stripping archive"),
339 fname);
340 result = 1;
341 }
342 else
343 result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
344 break;
345
346 default:
347 error (0, 0, gettext ("%s: File format not recognized"), fname);
348 result = 1;
349 break;
350 }
351
352 if (unlikely (elf_end (elf) != 0))
353 INTERNAL_ERROR (fname);
354
355 close (fd);
356
357 return result;
358}
359
360
361/* Maximum size of array allocated on stack. */
362#define MAX_STACK_ALLOC (400 * 1024)
363
364static int
365handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
366 mode_t mode, struct timeval tvp[2])
367{
368 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
369 size_t fname_len = strlen (fname) + 1;
370 char *fullname = alloca (prefix_len + 1 + fname_len);
371 char *cp = fullname;
Roland McGrathce4550a2005-08-10 08:10:07 +0000372 Elf *newelf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000373 Elf *debugelf = NULL;
374 char *tmp_debug_fname = NULL;
375 int result = 0;
Roland McGrathce4550a2005-08-10 08:10:07 +0000376 GElf_Ehdr ehdr_mem;
377 GElf_Ehdr *ehdr;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000378 size_t shstrndx;
Roland McGrathce4550a2005-08-10 08:10:07 +0000379 size_t shnum;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000380 struct shdr_info
381 {
382 Elf_Scn *scn;
383 GElf_Shdr shdr;
384 Elf_Data *data;
385 const char *name;
386 Elf32_Word idx; /* Index in new file. */
387 Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
388 Elf32_Word symtab_idx;
389 Elf32_Word version_idx;
390 Elf32_Word group_idx;
391 Elf32_Word group_cnt;
392 Elf_Scn *newscn;
393 struct Ebl_Strent *se;
394 Elf32_Word *newsymidx;
395 } *shdr_info = NULL;
396 Elf_Scn *scn;
397 size_t cnt;
398 size_t idx;
399 bool changes;
400 GElf_Ehdr newehdr_mem;
401 GElf_Ehdr *newehdr;
402 GElf_Ehdr debugehdr_mem;
403 GElf_Ehdr *debugehdr;
404 struct Ebl_Strtab *shst = NULL;
405 Elf_Data debuglink_crc_data;
406 bool any_symtab_changes = false;
407 Elf_Data *shstrtab_data = NULL;
408
409 /* Create the full name of the file. */
410 if (prefix != NULL)
411 {
412 cp = mempcpy (cp, prefix, prefix_len);
413 *cp++ = ':';
414 }
415 memcpy (cp, fname, fname_len);
416
417 /* If we are not replacing the input file open a new file here. */
418 if (output_fname != NULL)
419 {
420 fd = open (output_fname, O_RDWR | O_CREAT, mode);
421 if (unlikely (fd == -1))
422 {
423 error (0, errno, gettext ("cannot open '%s'"), output_fname);
424 return 1;
425 }
426 }
427
428 int debug_fd = -1;
429
430 /* Get the EBL handling. The -g option is currently the only reason
431 we need EBL so dont open the backend unless necessary. */
432 Ebl *ebl = NULL;
433 if (remove_debug)
434 {
435 ebl = ebl_openbackend (elf);
436 if (ebl == NULL)
437 {
438 error (0, errno, gettext ("cannot open EBL backend"));
439 result = 1;
440 goto fail;
441 }
442 }
443
444 /* Open the additional file the debug information will be stored in. */
445 if (debug_fname != NULL)
446 {
447 /* Create a temporary file name. We do not want to overwrite
448 the debug file if the file would not contain any
449 information. */
450 size_t debug_fname_len = strlen (debug_fname);
451 tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
452 strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
453 ".XXXXXX");
454
455 debug_fd = mkstemp (tmp_debug_fname);
456 if (unlikely (debug_fd == -1))
457 {
458 error (0, errno, gettext ("cannot open '%s'"), debug_fname);
459 result = 1;
460 goto fail;
461 }
462 }
463
464 /* Get the information from the old file. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000465 ehdr = gelf_getehdr (elf, &ehdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000466 if (ehdr == NULL)
467 INTERNAL_ERROR (fname);
468
469 /* Get the section header string table index. */
470 if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
471 error (EXIT_FAILURE, 0,
472 gettext ("cannot get section header string table index"));
473
474 /* We now create a new ELF descriptor for the same file. We
475 construct it almost exactly in the same way with some information
476 dropped. */
477 if (output_fname != NULL)
478 newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
479 else
480 newelf = elf_clone (elf, ELF_C_EMPTY);
481
482 if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
483 || (ehdr->e_type != ET_REL
484 && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
485 {
486 error (0, 0, gettext ("cannot create new file '%s': %s"),
487 output_fname, elf_errmsg (-1));
488 goto fail;
489 }
490
491 /* Copy over the old program header if needed. */
492 if (ehdr->e_type != ET_REL)
493 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
494 {
495 GElf_Phdr phdr_mem;
Roland McGrathce4550a2005-08-10 08:10:07 +0000496 GElf_Phdr *phdr;
497
498 phdr = gelf_getphdr (elf, cnt, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000499 if (phdr == NULL
500 || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
501 INTERNAL_ERROR (fname);
502 }
503
504 if (debug_fname != NULL)
505 {
506 /* Also create an ELF descriptor for the debug file */
507 debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
508 if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
509 || (ehdr->e_type != ET_REL
510 && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
511 {
512 error (0, 0, gettext ("cannot create new file '%s': %s"),
513 debug_fname, elf_errmsg (-1));
514 goto fail_close;
515 }
516
517 /* Copy over the old program header if needed. */
518 if (ehdr->e_type != ET_REL)
519 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
520 {
521 GElf_Phdr phdr_mem;
Roland McGrathce4550a2005-08-10 08:10:07 +0000522 GElf_Phdr *phdr;
523
524 phdr = gelf_getphdr (elf, cnt, &phdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000525 if (phdr == NULL
526 || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
527 INTERNAL_ERROR (fname);
528 }
529 }
530
531 /* Number of sections. */
532 if (unlikely (elf_getshnum (elf, &shnum) < 0))
533 {
534 error (0, 0, gettext ("cannot determine number of sections: %s"),
535 elf_errmsg (-1));
536 goto fail_close;
537 }
538
539 /* Storage for section information. We leave room for two more
540 entries since we unconditionally create a section header string
541 table. Maybe some weird tool created an ELF file without one.
542 The other one is used for the debug link section. */
543 if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
544 shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
545 sizeof (struct shdr_info));
546 else
547 {
548 shdr_info = (struct shdr_info *) alloca ((shnum + 2)
549 * sizeof (struct shdr_info));
550 memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
551 }
552
553 /* Prepare section information data structure. */
554 scn = NULL;
555 cnt = 1;
556 while ((scn = elf_nextscn (elf, scn)) != NULL)
557 {
558 /* This should always be true (i.e., there should not be any
559 holes in the numbering). */
560 assert (elf_ndxscn (scn) == cnt);
561
562 shdr_info[cnt].scn = scn;
563
564 /* Get the header. */
565 if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
566 INTERNAL_ERROR (fname);
567
568 /* Get the name of the section. */
569 shdr_info[cnt].name = elf_strptr (elf, shstrndx,
570 shdr_info[cnt].shdr.sh_name);
571 if (shdr_info[cnt].name == NULL)
572 {
573 error (0, 0, gettext ("illformed file '%s'"), fname);
574 goto fail_close;
575 }
576
577 /* Mark them as present but not yet investigated. */
578 shdr_info[cnt].idx = 1;
579
580 /* Remember the shdr.sh_link value. */
581 shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
582
583 /* Sections in files other than relocatable object files which
584 are not loaded can be freely moved by us. In relocatable
585 object files everything can be moved. */
586 if (ehdr->e_type == ET_REL
587 || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
588 shdr_info[cnt].shdr.sh_offset = 0;
589
590 /* If this is an extended section index table store an
591 appropriate reference. */
592 if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
593 {
594 assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
595 shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
596 }
597 else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
598 {
Roland McGrathce4550a2005-08-10 08:10:07 +0000599 Elf32_Word *grpref;
600 size_t inner;
601
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000602 /* Cross-reference the sections contained in the section
603 group. */
604 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
605 if (shdr_info[cnt].data == NULL)
606 INTERNAL_ERROR (fname);
607
608 /* XXX Fix for unaligned access. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000609 grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000610 for (inner = 1;
611 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
612 ++inner)
613 shdr_info[grpref[inner]].group_idx = cnt;
614
615 if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
616 /* If the section group contains only one element and this
617 is n COMDAT section we can drop it right away. */
618 shdr_info[cnt].idx = 0;
619 else
620 shdr_info[cnt].group_cnt = inner - 1;
621 }
622 else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
623 {
624 assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
625 shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
626 }
627
628 /* If this section is part of a group make sure it is not
629 discarded right away. */
630 if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
631 {
632 assert (shdr_info[cnt].group_idx != 0);
633
634 if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
635 {
636 /* The section group section will be removed. */
637 shdr_info[cnt].group_idx = 0;
638 shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
639 }
640 }
641
642 /* Increment the counter. */
643 ++cnt;
644 }
645
646 /* Now determine which sections can go away. The general rule is that
647 all sections which are not used at runtime are stripped out. But
648 there are a few exceptions:
649
650 - special sections named ".comment" and ".note" are kept
651 - OS or architecture specific sections are kept since we might not
652 know how to handle them
653 - if a section is referred to from a section which is not removed
654 in the sh_link or sh_info element it cannot be removed either
655 */
656 for (cnt = 1; cnt < shnum; ++cnt)
657 /* Check whether the section can be removed. */
658 if (ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr,
659 shdr_info[cnt].name, remove_comment,
660 remove_debug))
661 {
662 /* For now assume this section will be removed. */
663 shdr_info[cnt].idx = 0;
664
665 idx = shdr_info[cnt].group_idx;
666 while (idx != 0)
667 {
Ulrich Drepperfaf4d192005-08-11 05:12:05 +0000668 /* If the references section group is a normal section
669 group and has one element remaining, or if it is an
670 empty COMDAT section group it is removed. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000671 bool is_comdat;
672
673 /* The section group data is already loaded. */
674 assert (shdr_info[idx].data != NULL);
675
676 is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
677 & GRP_COMDAT) != 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000678
679 --shdr_info[idx].group_cnt;
680 if ((!is_comdat && shdr_info[idx].group_cnt == 1)
681 || (is_comdat && shdr_info[idx].group_cnt == 0))
682 {
683 shdr_info[idx].idx = 0;
684 /* Continue recursively. */
685 idx = shdr_info[idx].group_idx;
686 }
687 else
688 break;
689 }
690 }
691
692 /* Mark the SHT_NULL section as handled. */
693 shdr_info[0].idx = 2;
694
695
696 /* Handle exceptions: section groups and cross-references. We might
697 have to repeat this a few times since the resetting of the flag
698 might propagate. */
699 do
700 {
701 changes = false;
702
703 for (cnt = 1; cnt < shnum; ++cnt)
704 {
705 if (shdr_info[cnt].idx == 0)
706 {
707 /* If a relocation section is marked as being removed make
708 sure the section it is relocating is removed, too. */
709 if ((shdr_info[cnt].shdr.sh_type == SHT_REL
710 || shdr_info[cnt].shdr.sh_type == SHT_RELA)
711 && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
712 shdr_info[cnt].idx = 1;
713 }
714
715 if (shdr_info[cnt].idx == 1)
716 {
717 /* The content of symbol tables we don't remove must not
718 reference any section which we do remove. Otherwise
719 we cannot remove the section. */
720 if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
721 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
722 {
Roland McGrathce4550a2005-08-10 08:10:07 +0000723 Elf_Data *symdata;
724 Elf_Data *xndxdata;
725 size_t elsize;
726
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000727 /* Make sure the data is loaded. */
728 if (shdr_info[cnt].data == NULL)
729 {
730 shdr_info[cnt].data
731 = elf_getdata (shdr_info[cnt].scn, NULL);
732 if (shdr_info[cnt].data == NULL)
733 INTERNAL_ERROR (fname);
734 }
Roland McGrathce4550a2005-08-10 08:10:07 +0000735 symdata = shdr_info[cnt].data;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000736
737 /* If there is an extended section index table load it
738 as well. */
739 if (shdr_info[cnt].symtab_idx != 0
740 && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
741 {
742 assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
743
744 shdr_info[shdr_info[cnt].symtab_idx].data
745 = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
746 NULL);
747 if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
748 INTERNAL_ERROR (fname);
749 }
Roland McGrathce4550a2005-08-10 08:10:07 +0000750 xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000751
752 /* Go through all symbols and make sure the section they
753 reference is not removed. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000754 elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000755
756 for (size_t inner = 0;
757 inner < shdr_info[cnt].data->d_size / elsize;
758 ++inner)
759 {
760 GElf_Sym sym_mem;
761 Elf32_Word xndx;
Roland McGrathce4550a2005-08-10 08:10:07 +0000762 GElf_Sym *sym;
763 size_t scnidx;
764
765 sym = gelf_getsymshndx (symdata, xndxdata, inner,
766 &sym_mem, &xndx);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000767 if (sym == NULL)
768 INTERNAL_ERROR (fname);
769
Roland McGrathce4550a2005-08-10 08:10:07 +0000770 scnidx = sym->st_shndx;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000771 if (scnidx == SHN_UNDEF || scnidx >= shnum
772 || (scnidx >= SHN_LORESERVE
773 && scnidx <= SHN_HIRESERVE
774 && scnidx != SHN_XINDEX)
775 /* Don't count in the section symbols. */
776 || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
777 /* This is no section index, leave it alone. */
778 continue;
779 else if (scnidx == SHN_XINDEX)
780 scnidx = xndx;
781
782 if (shdr_info[scnidx].idx == 0)
783 {
784 /* Mark this section as used. */
785 shdr_info[scnidx].idx = 1;
786 changes |= scnidx < cnt;
787 }
788 }
789 }
790
791 /* Cross referencing happens:
792 - for the cases the ELF specification says. That are
793 + SHT_DYNAMIC in sh_link to string table
794 + SHT_HASH in sh_link to symbol table
795 + SHT_REL and SHT_RELA in sh_link to symbol table
796 + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
797 + SHT_GROUP in sh_link to symbol table
798 + SHT_SYMTAB_SHNDX in sh_link to symbol table
799 Other (OS or architecture-specific) sections might as
800 well use this field so we process it unconditionally.
801 - references inside section groups
802 - specially marked references in sh_info if the SHF_INFO_LINK
803 flag is set
804 */
805
806 if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
807 {
808 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
809 changes |= shdr_info[cnt].shdr.sh_link < cnt;
810 }
811
812 /* Handle references through sh_info. */
813 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
814 && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
815 {
816 shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
817 changes |= shdr_info[cnt].shdr.sh_info < cnt;
818 }
819
820 /* Mark the section as investigated. */
821 shdr_info[cnt].idx = 2;
822 }
823 }
824 }
825 while (changes);
826
827 /* Copy the removed sections to the debug output file.
828 The ones that are not removed in the stripped file are SHT_NOBITS. */
829 if (debug_fname != NULL)
830 {
831 for (cnt = 1; cnt < shnum; ++cnt)
832 {
Roland McGrathce4550a2005-08-10 08:10:07 +0000833 Elf_Data *debugdata;
834 GElf_Shdr debugshdr;
835 bool discard_section;
836
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000837 scn = elf_newscn (debugelf);
838 if (scn == NULL)
839 error (EXIT_FAILURE, 0,
840 gettext ("while generating output file: %s"),
841 elf_errmsg (-1));
842
Roland McGrathce4550a2005-08-10 08:10:07 +0000843 discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000844
845 /* Set the section header in the new file. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000846 debugshdr = shdr_info[cnt].shdr;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000847 if (discard_section)
848 debugshdr.sh_type = SHT_NOBITS;
849
850 if (unlikely (gelf_update_shdr (scn, &debugshdr)) == 0)
851 /* There cannot be any overflows. */
852 INTERNAL_ERROR (fname);
853
854 /* Get the data from the old file if necessary. */
855 if (shdr_info[cnt].data == NULL)
856 {
857 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
858 if (shdr_info[cnt].data == NULL)
859 INTERNAL_ERROR (fname);
860 }
861
862 /* Set the data. This is done by copying from the old file. */
Roland McGrathce4550a2005-08-10 08:10:07 +0000863 debugdata = elf_newdata (scn);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000864 if (debugdata == NULL)
865 INTERNAL_ERROR (fname);
866
867 /* Copy the structure. This data may be modified in place
868 before we write out the file. */
869 *debugdata = *shdr_info[cnt].data;
870 if (discard_section)
871 debugdata->d_buf = NULL;
872 }
873
874 /* Finish the ELF header. Fill in the fields not handled by
875 libelf from the old file. */
876 debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
877 if (debugehdr == NULL)
878 INTERNAL_ERROR (fname);
879
880 memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
881 debugehdr->e_type = ehdr->e_type;
882 debugehdr->e_machine = ehdr->e_machine;
883 debugehdr->e_version = ehdr->e_version;
884 debugehdr->e_entry = ehdr->e_entry;
885 debugehdr->e_flags = ehdr->e_flags;
886 debugehdr->e_shstrndx = ehdr->e_shstrndx;
887
888 if (unlikely (gelf_update_ehdr (debugelf, debugehdr)) == 0)
889 {
890 error (0, 0, gettext ("%s: error while creating ELF header: %s"),
891 debug_fname, elf_errmsg (-1));
892 result = 1;
893 goto fail_close;
894 }
895 }
896
897 /* Mark the section header string table as unused, we will create
898 a new one. */
899 shdr_info[shstrndx].idx = 0;
900
901 /* We need a string table for the section headers. */
902 shst = ebl_strtabinit (true);
903 if (shst == NULL)
904 error (EXIT_FAILURE, errno, gettext ("while preparing output for '%s'"),
905 output_fname ?: fname);
906
907 /* Assign new section numbers. */
908 shdr_info[0].idx = 0;
909 for (cnt = idx = 1; cnt < shnum; ++cnt)
910 if (shdr_info[cnt].idx > 0)
911 {
912 shdr_info[cnt].idx = idx++;
913
914 /* Create a new section. */
915 shdr_info[cnt].newscn = elf_newscn (newelf);
916 if (shdr_info[cnt].newscn == NULL)
917 error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
918 elf_errmsg (-1));
919
920 assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
921
922 /* Add this name to the section header string table. */
923 shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
924 }
925
926 /* Test whether we are doing anything at all. */
927 if (cnt == idx)
928 /* Nope, all removable sections are already gone. */
929 goto fail_close;
930
931 /* Create the reference to the file with the debug info. */
932 if (debug_fname != NULL)
933 {
Roland McGrathce4550a2005-08-10 08:10:07 +0000934 char *debug_basename;
935 off_t crc_offset;
936
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000937 /* Add the section header string table section name. */
938 shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
939 shdr_info[cnt].idx = idx++;
940
941 /* Create the section header. */
942 shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
943 shdr_info[cnt].shdr.sh_flags = 0;
944 shdr_info[cnt].shdr.sh_addr = 0;
945 shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
946 shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
947 shdr_info[cnt].shdr.sh_entsize = 0;
948 shdr_info[cnt].shdr.sh_addralign = 4;
949 /* We set the offset to zero here. Before we write the ELF file the
950 field must have the correct value. This is done in the final
951 loop over all section. Then we have all the information needed. */
952 shdr_info[cnt].shdr.sh_offset = 0;
953
954 /* Create the section. */
955 shdr_info[cnt].newscn = elf_newscn (newelf);
956 if (shdr_info[cnt].newscn == NULL)
957 error (EXIT_FAILURE, 0,
958 gettext ("while create section header section: %s"),
959 elf_errmsg (-1));
960 assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
961
962 shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
963 if (shdr_info[cnt].data == NULL)
964 error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
965 elf_errmsg (-1));
966
Roland McGrathce4550a2005-08-10 08:10:07 +0000967 debug_basename = basename (debug_fname_embed ?: debug_fname);
968 crc_offset = strlen (debug_basename) + 1;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000969 /* Align to 4 byte boundary */
970 crc_offset = ((crc_offset - 1) & ~3) + 4;
971
972 shdr_info[cnt].data->d_align = 4;
973 shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
974 = crc_offset + 4;
975 shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
976
977 strcpy (shdr_info[cnt].data->d_buf, debug_basename);
978
979 /* Cache this Elf_Data describing the CRC32 word in the section.
980 We'll fill this in when we have written the debug file. */
981 debuglink_crc_data = *shdr_info[cnt].data;
982 debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
983 + crc_offset);
984 debuglink_crc_data.d_size = 4;
985
986 /* One more section done. */
987 ++cnt;
988 }
989
990 /* Index of the section header table in the shdr_info array. */
991 size_t shdridx = cnt;
992
993 /* Add the section header string table section name. */
994 shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
995 shdr_info[cnt].idx = idx;
996
997 /* Create the section header. */
998 shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
999 shdr_info[cnt].shdr.sh_flags = 0;
1000 shdr_info[cnt].shdr.sh_addr = 0;
1001 shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
1002 shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
1003 shdr_info[cnt].shdr.sh_entsize = 0;
1004 /* We set the offset to zero here. Before we write the ELF file the
1005 field must have the correct value. This is done in the final
1006 loop over all section. Then we have all the information needed. */
1007 shdr_info[cnt].shdr.sh_offset = 0;
1008 shdr_info[cnt].shdr.sh_addralign = 1;
1009
1010 /* Create the section. */
1011 shdr_info[cnt].newscn = elf_newscn (newelf);
1012 if (shdr_info[cnt].newscn == NULL)
1013 error (EXIT_FAILURE, 0,
1014 gettext ("while create section header section: %s"),
1015 elf_errmsg (-1));
1016 assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
1017
1018 /* Finalize the string table and fill in the correct indices in the
1019 section headers. */
1020 shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
1021 if (shstrtab_data == NULL)
1022 error (EXIT_FAILURE, 0,
1023 gettext ("while create section header string table: %s"),
1024 elf_errmsg (-1));
1025 ebl_strtabfinalize (shst, shstrtab_data);
1026
1027 /* We have to set the section size. */
1028 shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
1029
1030 /* Update the section information. */
1031 GElf_Off lastoffset = 0;
1032 for (cnt = 1; cnt <= shdridx; ++cnt)
1033 if (shdr_info[cnt].idx > 0)
1034 {
1035 Elf_Data *newdata;
1036
1037 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1038 assert (scn != NULL);
1039
1040 /* Update the name. */
1041 shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
1042
1043 /* Update the section header from the input file. Some fields
1044 might be section indeces which now have to be adjusted. */
1045 if (shdr_info[cnt].shdr.sh_link != 0)
1046 shdr_info[cnt].shdr.sh_link =
1047 shdr_info[shdr_info[cnt].shdr.sh_link].idx;
1048
1049 if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1050 {
1051 assert (shdr_info[cnt].data != NULL);
1052
1053 Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
1054 for (size_t inner = 0;
1055 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
1056 ++inner)
1057 grpref[inner] = shdr_info[grpref[inner]].idx;
1058 }
1059
1060 /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
1061 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
1062 shdr_info[cnt].shdr.sh_info =
1063 shdr_info[shdr_info[cnt].shdr.sh_info].idx;
1064
1065 /* Get the data from the old file if necessary. We already
1066 created the data for the section header string table. */
1067 if (cnt < shnum)
1068 {
1069 if (shdr_info[cnt].data == NULL)
1070 {
1071 shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
1072 if (shdr_info[cnt].data == NULL)
1073 INTERNAL_ERROR (fname);
1074 }
1075
1076 /* Set the data. This is done by copying from the old file. */
1077 newdata = elf_newdata (scn);
1078 if (newdata == NULL)
1079 INTERNAL_ERROR (fname);
1080
1081 /* Copy the structure. */
1082 *newdata = *shdr_info[cnt].data;
1083
1084 /* We know the size. */
1085 shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
1086
1087 /* We have to adjust symtol tables. The st_shndx member might
1088 have to be updated. */
1089 if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
1090 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
1091 {
1092 Elf_Data *versiondata = NULL;
1093 Elf_Data *shndxdata = NULL;
1094
1095 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1096 ehdr->e_version);
1097
1098 if (shdr_info[cnt].symtab_idx != 0)
1099 {
1100 assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
1101 /* This section has extended section information.
1102 We have to modify that information, too. */
1103 shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
1104 NULL);
1105
1106 assert ((versiondata->d_size / sizeof (Elf32_Word))
1107 >= shdr_info[cnt].data->d_size / elsize);
1108 }
1109
1110 if (shdr_info[cnt].version_idx != 0)
1111 {
1112 assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
1113 /* This section has associated version
1114 information. We have to modify that
1115 information, too. */
1116 versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
1117 NULL);
1118
1119 assert ((versiondata->d_size / sizeof (GElf_Versym))
1120 >= shdr_info[cnt].data->d_size / elsize);
1121 }
1122
1123 shdr_info[cnt].newsymidx
1124 = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
1125 / elsize, sizeof (Elf32_Word));
1126
1127 bool last_was_local = true;
1128 size_t destidx;
1129 size_t inner;
1130 for (destidx = inner = 1;
1131 inner < shdr_info[cnt].data->d_size / elsize;
1132 ++inner)
1133 {
1134 Elf32_Word sec;
1135 GElf_Sym sym_mem;
1136 Elf32_Word xshndx;
1137 GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
1138 shndxdata, inner,
1139 &sym_mem, &xshndx);
1140 if (sym == NULL)
1141 INTERNAL_ERROR (fname);
1142
1143 if (sym->st_shndx == SHN_UNDEF
1144 || (sym->st_shndx >= shnum
1145 && sym->st_shndx != SHN_XINDEX))
1146 {
1147 /* This is no section index, leave it alone
1148 unless it is moved. */
1149 if (destidx != inner
1150 && gelf_update_symshndx (shdr_info[cnt].data,
1151 shndxdata,
1152 destidx, sym,
1153 xshndx) == 0)
1154 INTERNAL_ERROR (fname);
1155
1156 shdr_info[cnt].newsymidx[inner] = destidx++;
1157
1158 if (last_was_local
1159 && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1160 {
1161 last_was_local = false;
1162 shdr_info[cnt].shdr.sh_info = destidx - 1;
1163 }
1164
1165 continue;
1166 }
1167
1168 /* Get the full section index, if necessary from the
1169 XINDEX table. */
1170 if (sym->st_shndx != SHN_XINDEX)
1171 sec = shdr_info[sym->st_shndx].idx;
1172 else
1173 {
1174 assert (shndxdata != NULL);
1175
1176 sec = shdr_info[xshndx].idx;
1177 }
1178
1179 if (sec != 0)
1180 {
1181 GElf_Section nshndx;
1182 Elf32_Word nxshndx;
1183
1184 if (sec < SHN_LORESERVE)
1185 {
1186 nshndx = sec;
1187 nxshndx = 0;
1188 }
1189 else
1190 {
1191 nshndx = SHN_XINDEX;
1192 nxshndx = sec;
1193 }
1194
1195 assert (sec < SHN_LORESERVE || shndxdata != NULL);
1196
1197 if ((inner != destidx || nshndx != sym->st_shndx
1198 || (shndxdata != NULL && nxshndx != xshndx))
1199 && (sym->st_shndx = nshndx,
1200 gelf_update_symshndx (shdr_info[cnt].data,
1201 shndxdata,
1202 destidx, sym,
1203 nxshndx) == 0))
1204 INTERNAL_ERROR (fname);
1205
1206 shdr_info[cnt].newsymidx[inner] = destidx++;
1207
1208 if (last_was_local
1209 && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
1210 {
1211 last_was_local = false;
1212 shdr_info[cnt].shdr.sh_info = destidx - 1;
1213 }
1214 }
1215 else
1216 /* This is a section symbol for a section which has
1217 been removed. */
1218 assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
1219 }
1220
1221 if (destidx != inner)
1222 {
1223 /* The size of the symbol table changed. */
1224 shdr_info[cnt].shdr.sh_size = newdata->d_size
1225 = destidx * elsize;
1226 any_symtab_changes = true;
1227 }
1228 else
1229 {
1230 /* The symbol table didn't really change. */
1231 free (shdr_info[cnt].newsymidx);
1232 shdr_info[cnt].newsymidx = NULL;
1233 }
1234 }
1235 }
1236
1237 /* If we have to, compute the offset of the section. */
1238 if (shdr_info[cnt].shdr.sh_offset == 0)
1239 shdr_info[cnt].shdr.sh_offset
1240 = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
1241 & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
1242
1243 /* Set the section header in the new file. */
1244 if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
1245 /* There cannot be any overflows. */
1246 INTERNAL_ERROR (fname);
1247
1248 /* Remember the last section written so far. */
1249 GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
1250 ? shdr_info[cnt].shdr.sh_size : 0);
1251 if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
1252 lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
1253 }
1254
1255 /* Adjust symbol references if symbol tables changed. */
1256 if (any_symtab_changes)
1257 {
1258 /* Find all relocation sections which use this
1259 symbol table. */
1260 for (cnt = 1; cnt <= shdridx; ++cnt)
1261 {
1262 if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
1263 /* Ignore sections which are discarded. When we are saving a
1264 relocation section in a separate debug file, we must fix up
1265 the symbol table references. */
1266 continue;
1267
1268 if (shdr_info[cnt].shdr.sh_type == SHT_REL
1269 || shdr_info[cnt].shdr.sh_type == SHT_RELA)
1270 {
1271 /* If the symbol table hasn't changed, do not do anything. */
1272 if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx == NULL)
1273 continue;
1274
1275 Elf32_Word *newsymidx
1276 = shdr_info[shdr_info[cnt].old_sh_link].newsymidx;
1277 Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
1278 ? elf_getscn (debugelf, cnt)
1279 : elf_getscn (newelf,
1280 shdr_info[cnt].idx),
1281 NULL);
1282 assert (d != NULL);
1283 size_t nrels = (shdr_info[cnt].shdr.sh_size
1284 / shdr_info[cnt].shdr.sh_entsize);
1285
1286 if (shdr_info[cnt].shdr.sh_type == SHT_REL)
1287 for (size_t relidx = 0; relidx < nrels; ++relidx)
1288 {
1289 GElf_Rel rel_mem;
1290 if (gelf_getrel (d, relidx, &rel_mem) == NULL)
1291 INTERNAL_ERROR (fname);
1292
1293 size_t symidx = GELF_R_SYM (rel_mem.r_info);
1294 if (newsymidx[symidx] != symidx)
1295 {
1296 rel_mem.r_info
1297 = GELF_R_INFO (newsymidx[symidx],
1298 GELF_R_TYPE (rel_mem.r_info));
1299
1300 if (gelf_update_rel (d, relidx, &rel_mem) == 0)
1301 INTERNAL_ERROR (fname);
1302 }
1303 }
1304 else
1305 for (size_t relidx = 0; relidx < nrels; ++relidx)
1306 {
1307 GElf_Rela rel_mem;
1308 if (gelf_getrela (d, relidx, &rel_mem) == NULL)
1309 INTERNAL_ERROR (fname);
1310
1311 size_t symidx = GELF_R_SYM (rel_mem.r_info);
1312 if (newsymidx[symidx] != symidx)
1313 {
1314 rel_mem.r_info
1315 = GELF_R_INFO (newsymidx[symidx],
1316 GELF_R_TYPE (rel_mem.r_info));
1317
1318 if (gelf_update_rela (d, relidx, &rel_mem) == 0)
1319 INTERNAL_ERROR (fname);
1320 }
1321 }
1322 }
1323 else if (shdr_info[cnt].shdr.sh_type == SHT_HASH)
1324 {
1325 /* We have to recompute the hash table. */
1326 Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1327
1328 /* We do not have to do anything if the symbol table was
1329 not changed. */
1330 if (shdr_info[symtabidx].newsymidx == NULL)
1331 continue;
1332
1333 assert (shdr_info[cnt].idx > 0);
1334
1335 /* The hash section in the new file. */
1336 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1337
1338 /* The symbol table data. */
1339 Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1340 shdr_info[symtabidx].idx),
1341 NULL);
1342 assert (symd != NULL);
1343
1344 /* The hash table data. */
1345 Elf_Data *hashd = elf_getdata (scn, NULL);
1346 assert (hashd != NULL);
1347
1348 if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
1349 {
1350 /* Sane arches first. */
1351 Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
1352
1353 size_t strshndx = shdr_info[symtabidx].old_sh_link;
1354 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1355 ehdr->e_version);
1356
1357 /* Adjust the nchain value. The symbol table size
1358 changed. We keep the same size for the bucket array. */
1359 bucket[1] = symd->d_size / elsize;
1360 Elf32_Word nbucket = bucket[0];
1361 bucket += 2;
1362 Elf32_Word *chain = bucket + nbucket;
1363
1364 /* New size of the section. */
1365 GElf_Shdr shdr_mem;
1366 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1367 shdr->sh_size = hashd->d_size
1368 = (2 + symd->d_size / elsize + nbucket)
1369 * sizeof (Elf32_Word);
1370 (void) gelf_update_shdr (scn, shdr);
1371
1372 /* Clear the arrays. */
1373 memset (bucket, '\0',
1374 (symd->d_size / elsize + nbucket)
1375 * sizeof (Elf32_Word));
1376
1377 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1378 inner < symd->d_size / elsize; ++inner)
1379 {
1380 GElf_Sym sym_mem;
1381 GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1382 assert (sym != NULL);
1383
1384 const char *name = elf_strptr (elf, strshndx,
1385 sym->st_name);
1386 assert (name != NULL);
1387 size_t hidx = elf_hash (name) % nbucket;
1388
1389 if (bucket[hidx] == 0)
1390 bucket[hidx] = inner;
1391 else
1392 {
1393 hidx = bucket[hidx];
1394
1395 while (chain[hidx] != 0)
1396 hidx = chain[hidx];
1397
1398 chain[hidx] = inner;
1399 }
1400 }
1401 }
1402 else
1403 {
1404 /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
1405 assert (shdr_info[cnt].shdr.sh_entsize
1406 == sizeof (Elf64_Xword));
1407
1408 Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
1409
1410 size_t strshndx = shdr_info[symtabidx].old_sh_link;
1411 size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
1412 ehdr->e_version);
1413
1414 /* Adjust the nchain value. The symbol table size
1415 changed. We keep the same size for the bucket array. */
1416 bucket[1] = symd->d_size / elsize;
1417 Elf64_Xword nbucket = bucket[0];
1418 bucket += 2;
1419 Elf64_Xword *chain = bucket + nbucket;
1420
1421 /* New size of the section. */
1422 GElf_Shdr shdr_mem;
1423 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1424 shdr->sh_size = hashd->d_size
1425 = (2 + symd->d_size / elsize + nbucket)
1426 * sizeof (Elf64_Xword);
1427 (void) gelf_update_shdr (scn, shdr);
1428
1429 /* Clear the arrays. */
1430 memset (bucket, '\0',
1431 (symd->d_size / elsize + nbucket)
1432 * sizeof (Elf64_Xword));
1433
1434 for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
1435 inner < symd->d_size / elsize; ++inner)
1436 {
1437 GElf_Sym sym_mem;
1438 GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
1439 assert (sym != NULL);
1440
1441 const char *name = elf_strptr (elf, strshndx,
1442 sym->st_name);
1443 assert (name != NULL);
1444 size_t hidx = elf_hash (name) % nbucket;
1445
1446 if (bucket[hidx] == 0)
1447 bucket[hidx] = inner;
1448 else
1449 {
1450 hidx = bucket[hidx];
1451
1452 while (chain[hidx] != 0)
1453 hidx = chain[hidx];
1454
1455 chain[hidx] = inner;
1456 }
1457 }
1458 }
1459 }
1460 else if (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)
1461 {
1462 /* If the symbol table changed we have to adjust the
1463 entries. */
1464 Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
1465
1466 /* We do not have to do anything if the symbol table was
1467 not changed. */
1468 if (shdr_info[symtabidx].newsymidx == NULL)
1469 continue;
1470
1471 assert (shdr_info[cnt].idx > 0);
1472
1473 /* The symbol version section in the new file. */
1474 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1475
1476 /* The symbol table data. */
1477 Elf_Data *symd = elf_getdata (elf_getscn (newelf,
1478 shdr_info[symtabidx].idx),
1479 NULL);
1480 assert (symd != NULL);
1481
1482 /* The version symbol data. */
1483 Elf_Data *verd = elf_getdata (scn, NULL);
1484 assert (verd != NULL);
1485
1486 /* The symbol version array. */
1487 GElf_Half *verstab = (GElf_Half *) verd->d_buf;
1488
1489 /* New indices of the symbols. */
1490 Elf32_Word *newsymidx = shdr_info[symtabidx].newsymidx;
1491
1492 /* Walk through the list and */
1493 size_t elsize = gelf_fsize (elf, verd->d_type, 1,
1494 ehdr->e_version);
1495 for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
1496 if (newsymidx[inner] != 0)
1497 /* Overwriting the same array works since the
1498 reordering can only move entries to lower indices
1499 in the array. */
1500 verstab[newsymidx[inner]] = verstab[inner];
1501
1502 /* New size of the section. */
1503 GElf_Shdr shdr_mem;
1504 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1505 shdr->sh_size = verd->d_size
1506 = gelf_fsize (newelf, verd->d_type,
1507 symd->d_size / gelf_fsize (elf, symd->d_type, 1,
1508 ehdr->e_version),
1509 ehdr->e_version);
1510 (void) gelf_update_shdr (scn, shdr);
1511 }
1512 else if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
1513 {
1514 /* Check whether the associated symbol table changed. */
1515 if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx != NULL)
1516 {
1517 /* Yes the symbol table changed. Update the section
1518 header of the section group. */
1519 scn = elf_getscn (newelf, shdr_info[cnt].idx);
1520 GElf_Shdr shdr_mem;
1521 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1522 assert (shdr != NULL);
1523
1524 size_t stabidx = shdr_info[cnt].old_sh_link;
1525 shdr->sh_info = shdr_info[stabidx].newsymidx[shdr->sh_info];
1526
1527 (void) gelf_update_shdr (scn, shdr);
1528 }
1529 }
1530 }
1531 }
1532
1533 /* Now that we have done all adjustments to the data,
1534 we can actually write out the debug file. */
1535 if (debug_fname != NULL)
1536 {
1537 uint32_t debug_crc;
1538 Elf_Data debug_crc_data =
1539 {
1540 .d_type = ELF_T_WORD,
1541 .d_buf = &debug_crc,
1542 .d_size = sizeof (debug_crc),
1543 .d_version = EV_CURRENT
1544 };
1545
1546 /* Finally write the file. */
1547 if (unlikely (elf_update (debugelf, ELF_C_WRITE)) == -1)
1548 {
1549 error (0, 0, gettext ("while writing '%s': %s"),
1550 debug_fname, elf_errmsg (-1));
1551 result = 1;
1552 goto fail_close;
1553 }
1554
1555 /* Create the real output file. First rename, then change the
1556 mode. */
1557 if (rename (tmp_debug_fname, debug_fname) != 0
1558 || fchmod (debug_fd, mode) != 0)
1559 {
1560 error (0, errno, gettext ("while creating '%s'"), debug_fname);
1561 result = 1;
1562 goto fail_close;
1563 }
1564
1565 /* The temporary file does not exist anymore. */
1566 tmp_debug_fname = NULL;
1567
1568 /* Compute the checksum which we will add to the executable. */
1569 if (crc32_file (debug_fd, &debug_crc) != 0)
1570 {
1571 error (0, errno,
1572 gettext ("while computing checksum for debug information"));
1573 unlink (debug_fname);
1574 result = 1;
1575 goto fail_close;
1576 }
1577
1578 /* Store it in the debuglink section data. */
1579 if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
1580 &debug_crc_data, ehdr->e_ident[EI_DATA])
1581 != &debuglink_crc_data))
1582 INTERNAL_ERROR (fname);
1583 }
1584
1585 /* Finally finish the ELF header. Fill in the fields not handled by
1586 libelf from the old file. */
1587 newehdr = gelf_getehdr (newelf, &newehdr_mem);
1588 if (newehdr == NULL)
1589 INTERNAL_ERROR (fname);
1590
1591 memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
1592 newehdr->e_type = ehdr->e_type;
1593 newehdr->e_machine = ehdr->e_machine;
1594 newehdr->e_version = ehdr->e_version;
1595 newehdr->e_entry = ehdr->e_entry;
1596 newehdr->e_flags = ehdr->e_flags;
1597 newehdr->e_phoff = ehdr->e_phoff;
1598 /* We need to position the section header table. */
1599 const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
1600 newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
1601 + shdr_info[shdridx].shdr.sh_size + offsize - 1)
1602 & ~((GElf_Off) (offsize - 1)));
1603 newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
1604
1605 /* The new section header string table index. */
1606 if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
1607 newehdr->e_shstrndx = idx;
1608 else
1609 {
1610 /* The index does not fit in the ELF header field. */
1611 shdr_info[0].scn = elf_getscn (elf, 0);
1612
1613 if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
1614 INTERNAL_ERROR (fname);
1615
1616 shdr_info[0].shdr.sh_link = idx;
1617 (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
1618
1619 newehdr->e_shstrndx = SHN_XINDEX;
1620 }
1621
1622 if (gelf_update_ehdr (newelf, newehdr) == 0)
1623 {
1624 error (0, 0, gettext ("%s: error while creating ELF header: %s"),
1625 fname, elf_errmsg (-1));
1626 return 1;
1627 }
1628
1629 /* We have everything from the old file. */
1630 if (elf_cntl (elf, ELF_C_FDDONE) != 0)
1631 {
1632 error (0, 0, gettext ("%s: error while reading the file: %s"),
1633 fname, elf_errmsg (-1));
1634 return 1;
1635 }
1636
1637 /* The ELF library better follows our layout when this is not a
1638 relocatable object file. */
1639 elf_flagelf (newelf, ELF_C_SET,
1640 (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
1641 | (permissive ? ELF_F_PERMISSIVE : 0));
1642
1643 /* Finally write the file. */
1644 if (elf_update (newelf, ELF_C_WRITE) == -1)
1645 {
1646 error (0, 0, gettext ("while writing '%s': %s"),
1647 fname, elf_errmsg (-1));
1648 result = 1;
1649 }
1650
1651 fail_close:
1652 if (shdr_info != NULL)
1653 {
1654 /* For some sections we might have created an table to map symbol
1655 table indices. */
1656 if (any_symtab_changes)
1657 for (cnt = 1; cnt <= shdridx; ++cnt)
1658 free (shdr_info[cnt].newsymidx);
1659
1660 /* Free the memory. */
1661 if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
1662 free (shdr_info);
1663 }
1664
1665 /* Free other resources. */
1666 if (shstrtab_data != NULL)
1667 free (shstrtab_data->d_buf);
1668 if (shst != NULL)
1669 ebl_strtabfree (shst);
1670
1671 /* That was it. Close the descriptors. */
1672 if (elf_end (newelf) != 0)
1673 {
1674 error (0, 0, gettext ("error while finishing '%s': %s"), fname,
1675 elf_errmsg (-1));
1676 result = 1;
1677 }
1678
1679 if (debugelf != NULL && elf_end (debugelf) != 0)
1680 {
1681 error (0, 0, gettext ("error while finishing '%s': %s"), debug_fname,
1682 elf_errmsg (-1));
1683 result = 1;
1684 }
1685
1686 fail:
1687 /* Close the EBL backend. */
1688 if (ebl != NULL)
1689 ebl_closebackend (ebl);
1690
1691 /* Close debug file descriptor, if opened */
1692 if (debug_fd >= 0)
1693 {
1694 if (tmp_debug_fname != NULL)
1695 unlink (tmp_debug_fname);
1696 close (debug_fd);
1697 }
1698
1699 /* If requested, preserve the timestamp. */
1700 if (tvp != NULL)
1701 {
1702 if (futimes (fd, tvp) != 0)
1703 {
1704 error (0, errno, gettext ("\
1705cannot set access and modification date of '%s'"),
1706 output_fname ?: fname);
1707 result = 1;
1708 }
1709 }
1710
1711 /* Close the file descriptor if we created a new file. */
1712 if (output_fname != NULL)
1713 close (fd);
1714
1715 return result;
1716}
1717
1718
1719static int
1720handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
1721 struct timeval tvp[2])
1722{
1723 size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
1724 size_t fname_len = strlen (fname) + 1;
1725 char new_prefix[prefix_len + 1 + fname_len];
1726 char *cp = new_prefix;
1727
1728 /* Create the full name of the file. */
1729 if (prefix != NULL)
1730 {
1731 cp = mempcpy (cp, prefix, prefix_len);
1732 *cp++ = ':';
1733 }
1734 memcpy (cp, fname, fname_len);
1735
1736
1737 /* Process all the files contained in the archive. */
1738 Elf *subelf;
1739 Elf_Cmd cmd = ELF_C_RDWR;
1740 int result = 0;
1741 while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
1742 {
1743 /* The the header for this element. */
1744 Elf_Arhdr *arhdr = elf_getarhdr (subelf);
1745
1746 if (elf_kind (subelf) == ELF_K_ELF)
1747 result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
1748 else if (elf_kind (subelf) == ELF_K_AR)
1749 result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
1750
1751 /* Get next archive element. */
1752 cmd = elf_next (subelf);
1753 if (unlikely (elf_end (subelf) != 0))
1754 INTERNAL_ERROR (fname);
1755 }
1756
1757 if (tvp != NULL)
1758 {
1759 if (unlikely (futimes (fd, tvp) != 0))
1760 {
1761 error (0, errno, gettext ("\
1762cannot set access and modification date of '%s'"), fname);
1763 result = 1;
1764 }
1765 }
1766
1767 if (unlikely (close (fd) != 0))
1768 error (EXIT_FAILURE, errno, gettext ("while closing '%s'"), fname);
1769
1770 return result;
1771}