diff options
Diffstat (limited to 'binutils-2.22/binutils/objcopy.c')
-rw-r--r-- | binutils-2.22/binutils/objcopy.c | 149 |
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; |