summaryrefslogtreecommitdiffstats
path: root/binutils-2.22/binutils/objcopy.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.22/binutils/objcopy.c')
-rw-r--r--binutils-2.22/binutils/objcopy.c149
1 files changed, 125 insertions, 24 deletions
diff --git a/binutils-2.22/binutils/objcopy.c b/binutils-2.22/binutils/objcopy.c
index 31ac0a2..40250ad 100644
--- a/binutils-2.22/binutils/objcopy.c
+++ b/binutils-2.22/binutils/objcopy.c
@@ -1,6 +1,6 @@
/* objcopy.c -- copy object file from input to output, optionally massaging it.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GNU Binutils.
@@ -30,7 +30,6 @@
#include "filenames.h"
#include "fnmatch.h"
#include "elf-bfd.h"
-#include <sys/stat.h>
#include "libbfd.h"
#include "coff/internal.h"
#include "libcoff.h"
@@ -87,6 +86,7 @@ static int copy_width = 1;
static bfd_boolean verbose; /* Print file and target names. */
static bfd_boolean preserve_dates; /* Preserve input file timestamp. */
+static bfd_boolean deterministic; /* Enable deterministic archives. */
static int status = 0; /* Exit status. */
enum strip_action
@@ -96,6 +96,8 @@ enum strip_action
STRIP_DEBUG, /* Strip all debugger symbols. */
STRIP_UNNEEDED, /* Strip unnecessary symbols. */
STRIP_NONDEBUG, /* Strip everything but debug info. */
+ STRIP_DWO, /* Strip all DWO info. */
+ STRIP_NONDWO, /* Strip everything but DWO info. */
STRIP_ALL /* Strip all symbols. */
};
@@ -314,7 +316,9 @@ enum command_line_switch
OPTION_SECTION_ALIGNMENT,
OPTION_STACK,
OPTION_INTERLEAVE_WIDTH,
- OPTION_SUBSYSTEM
+ OPTION_SUBSYSTEM,
+ OPTION_EXTRACT_DWO,
+ OPTION_STRIP_DWO
};
/* Options to handle if running as "strip". */
@@ -323,6 +327,7 @@ static struct option strip_options[] =
{
{"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'},
+ {"enable-deterministic-archives", no_argument, 0, 'D'},
{"format", required_argument, 0, 'F'}, /* Obsolete */
{"help", no_argument, 0, 'h'},
{"info", no_argument, 0, OPTION_FORMATS_INFO},
@@ -338,6 +343,7 @@ static struct option strip_options[] =
{"remove-section", required_argument, 0, 'R'},
{"strip-all", no_argument, 0, 's'},
{"strip-debug", no_argument, 0, 'S'},
+ {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
{"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
{"strip-symbol", required_argument, 0, 'N'},
{"target", required_argument, 0, 'F'},
@@ -372,6 +378,8 @@ static struct option copy_options[] =
{"decompress-debug-sections", no_argument, 0, OPTION_DECOMPRESS_DEBUG_SECTIONS},
{"discard-all", no_argument, 0, 'x'},
{"discard-locals", no_argument, 0, 'X'},
+ {"enable-deterministic-archives", no_argument, 0, 'D'},
+ {"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
{"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
{"format", required_argument, 0, 'F'}, /* Obsolete */
{"gap-fill", required_argument, 0, OPTION_GAP_FILL},
@@ -418,6 +426,7 @@ static struct option copy_options[] =
{"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
{"strip-all", no_argument, 0, 'S'},
{"strip-debug", no_argument, 0, 'g'},
+ {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
{"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
{"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
{"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
@@ -460,6 +469,7 @@ extern bfd_boolean S3Forced;
/* Forward declarations. */
static void setup_section (bfd *, asection *, void *);
static void setup_bfd_headers (bfd *, bfd *);
+static void copy_relocations_in_section (bfd *, asection *, void *);
static void copy_section (bfd *, asection *, void *);
static void get_sections (bfd *, asection *, void *);
static int compare_section_lma (const void *, const void *);
@@ -480,17 +490,21 @@ copy_usage (FILE *stream, int exit_status)
-F --target <bfdname> Set both input and output format to <bfdname>\n\
--debugging Convert debugging information, if possible\n\
-p --preserve-dates Copy modified/access timestamps to the output\n\
+ -D --enable-deterministic-archives\n\
+ Produce deterministic output when stripping archives\n\
-j --only-section <name> Only copy section <name> into the output\n\
--add-gnu-debuglink=<file> Add section .gnu_debuglink linking to <file>\n\
-R --remove-section <name> Remove section <name> from the output\n\
-S --strip-all Remove all symbol and relocation information\n\
-g --strip-debug Remove all debugging symbols & sections\n\
+ --strip-dwo Remove all DWO sections\n\
--strip-unneeded Remove all symbols not needed by relocations\n\
-N --strip-symbol <name> Do not copy symbol <name>\n\
--strip-unneeded-symbol <name>\n\
Do not copy symbol <name> unless needed by\n\
relocations\n\
--only-keep-debug Strip everything but the debug information\n\
+ --extract-dwo Copy only DWO sections\n\
--extract-symbol Remove section contents but keep symbols\n\
-K --keep-symbol <name> Do not strip symbol <name>\n\
--keep-file-symbols Do not strip file symbol(s)\n\
@@ -588,9 +602,12 @@ strip_usage (FILE *stream, int exit_status)
-O --output-target=<bfdname> Create an output file in format <bfdname>\n\
-F --target=<bfdname> Set both input and output format to <bfdname>\n\
-p --preserve-dates Copy modified/access timestamps to the output\n\
+ -D --enable-deterministic-archives\n\
+ Produce deterministic output when stripping archives\n\
-R --remove-section=<name> Remove section <name> from the output\n\
-s --strip-all Remove all symbol and relocation information\n\
-g -S -d --strip-debug Remove all debugging symbols & sections\n\
+ --strip-dwo Remove all DWO sections\n\
--strip-unneeded Remove all symbols not needed by relocations\n\
--only-keep-debug Strip everything but the debug information\n\
-N --strip-symbol=<name> Do not copy symbol <name>\n\
@@ -925,6 +942,17 @@ group_signature (asection *group)
return NULL;
}
+/* Return TRUE if the section is a DWO section. */
+
+static bfd_boolean
+is_dwo_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+{
+ const char *name = bfd_get_section_name (abfd, sec);
+ int len = strlen (name);
+
+ return strncmp (name + len - 4, ".dwo", 4) == 0;
+}
+
/* See if a non-group section is being removed. */
static bfd_boolean
@@ -951,10 +979,16 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
|| convert_debugging)
return TRUE;
+ if (strip_symbols == STRIP_DWO)
+ return is_dwo_section (abfd, sec);
+
if (strip_symbols == STRIP_NONDEBUG)
return FALSE;
}
+ if (strip_symbols == STRIP_NONDWO)
+ return !is_dwo_section (abfd, sec);
+
return FALSE;
}
@@ -1842,6 +1876,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
|| strip_symbols == STRIP_ALL
|| strip_symbols == STRIP_UNNEEDED
|| strip_symbols == STRIP_NONDEBUG
+ || strip_symbols == STRIP_DWO
+ || strip_symbols == STRIP_NONDWO
|| discard_locals != LOCALS_UNDEF
|| localize_hidden
|| htab_elements (strip_specific_htab) != 0
@@ -1886,6 +1922,9 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
bfd_set_symtab (obfd, osympp, symcount);
+ /* This has to happen before section positions are set. */
+ bfd_map_over_sections (ibfd, copy_relocations_in_section, obfd);
+
/* This has to happen after the symbol table has been set. */
bfd_map_over_sections (ibfd, copy_section, obfd);
@@ -2027,9 +2066,15 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
fatal (_("cannot create tempdir for archive copying (error: %s)"),
strerror (errno));
- obfd->has_armap = ibfd->has_armap;
+ if (strip_symbols == STRIP_ALL)
+ obfd->has_armap = FALSE;
+ else
+ obfd->has_armap = ibfd->has_armap;
obfd->is_thin_archive = ibfd->is_thin_archive;
+ if (deterministic)
+ obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
+
list = NULL;
this_element = bfd_openr_next_archived_file (ibfd, NULL);
@@ -2589,47 +2634,59 @@ loser:
bfd_nonfatal_message (NULL, obfd, osection, err);
}
-/* Copy the data of input section ISECTION of IBFD
- to an output section with the same name in OBFD.
- If stripping then don't copy any relocation info. */
+/* Return TRUE if input section ISECTION should be skipped. */
-static void
-copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+static bfd_boolean
+skip_section (bfd *ibfd, sec_ptr isection)
{
- bfd *obfd = (bfd *) obfdarg;
- struct section_list *p;
- arelent **relpp;
- long relcount;
sec_ptr osection;
bfd_size_type size;
- long relsize;
flagword flags;
/* If we have already failed earlier on,
do not keep on generating complaints now. */
if (status != 0)
- return;
+ return TRUE;
+
+ if (extract_symbol)
+ return TRUE;
if (is_strip_section (ibfd, isection))
- return;
+ return TRUE;
flags = bfd_get_section_flags (ibfd, isection);
if ((flags & SEC_GROUP) != 0)
- return;
+ return TRUE;
osection = isection->output_section;
size = bfd_get_section_size (isection);
if (size == 0 || osection == 0)
- return;
+ return TRUE;
- if (extract_symbol)
+ return FALSE;
+}
+
+/* Copy relocations in input section ISECTION of IBFD to an output
+ section with the same name in OBFDARG. If stripping then don't
+ copy any relocation info. */
+
+static void
+copy_relocations_in_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+{
+ bfd *obfd = (bfd *) obfdarg;
+ long relsize;
+ arelent **relpp;
+ long relcount;
+ sec_ptr osection;
+
+ if (skip_section (ibfd, isection))
return;
- p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
+ osection = isection->output_section;
- /* Core files do not need to be relocated. */
- if (bfd_get_format (obfd) == bfd_core)
+ /* Core files and DWO files do not need to be relocated. */
+ if (bfd_get_format (obfd) == bfd_core || strip_symbols == STRIP_NONDWO)
relsize = 0;
else
{
@@ -2650,7 +2707,10 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
}
if (relsize == 0)
- bfd_set_reloc (obfd, osection, NULL, 0);
+ {
+ bfd_set_reloc (obfd, osection, NULL, 0);
+ osection->flags &= ~SEC_RELOC;
+ }
else
{
relpp = (arelent **) xmalloc (relsize);
@@ -2683,8 +2743,31 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
if (relcount == 0)
- free (relpp);
+ {
+ osection->flags &= ~SEC_RELOC;
+ free (relpp);
+ }
}
+}
+
+/* Copy the data of input section ISECTION of IBFD
+ to an output section with the same name in OBFD. */
+
+static void
+copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
+{
+ bfd *obfd = (bfd *) obfdarg;
+ struct section_list *p;
+ sec_ptr osection;
+ bfd_size_type size;
+
+ if (skip_section (ibfd, isection))
+ return;
+
+ osection = isection->output_section;
+ size = bfd_get_section_size (isection);
+
+ p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
@@ -2971,6 +3054,9 @@ strip_main (int argc, char *argv[])
case 'd': /* Historic BSD alias for -g. Used by early NetBSD. */
strip_symbols = STRIP_DEBUG;
break;
+ case OPTION_STRIP_DWO:
+ strip_symbols = STRIP_DWO;
+ break;
case OPTION_STRIP_UNNEEDED:
strip_symbols = STRIP_UNNEEDED;
break;
@@ -2986,6 +3072,9 @@ strip_main (int argc, char *argv[])
case 'p':
preserve_dates = TRUE;
break;
+ case 'D':
+ deterministic = TRUE;
+ break;
case 'x':
discard_locals = LOCALS_ALL;
break;
@@ -3298,6 +3387,10 @@ copy_main (int argc, char *argv[])
strip_symbols = STRIP_DEBUG;
break;
+ case OPTION_STRIP_DWO:
+ strip_symbols = STRIP_DWO;
+ break;
+
case OPTION_STRIP_UNNEEDED:
strip_symbols = STRIP_UNNEEDED;
break;
@@ -3346,6 +3439,10 @@ copy_main (int argc, char *argv[])
preserve_dates = TRUE;
break;
+ case 'D':
+ deterministic = TRUE;
+ break;
+
case 'w':
wildcard = TRUE;
break;
@@ -3755,6 +3852,10 @@ copy_main (int argc, char *argv[])
bfd_flags_to_set &= ~D_PAGED;
break;
+ case OPTION_EXTRACT_DWO:
+ strip_symbols = STRIP_NONDWO;
+ break;
+
case OPTION_EXTRACT_SYMBOL:
extract_symbol = TRUE;
break;