Back to index

cell-binutils  2.17cvs20070401
objcopy.c
Go to the documentation of this file.
00001 /* objcopy.c -- copy object file from input to output, optionally massaging it.
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "progress.h"
00025 #include "bucomm.h"
00026 #include "getopt.h"
00027 #include "libiberty.h"
00028 #include "budbg.h"
00029 #include "filenames.h"
00030 #include "fnmatch.h"
00031 #include "elf-bfd.h"
00032 #include <sys/stat.h>
00033 #include "libbfd.h"
00034 
00035 /* A list of symbols to explicitly strip out, or to keep.  A linked
00036    list is good enough for a small number from the command line, but
00037    this will slow things down a lot if many symbols are being
00038    deleted.  */
00039 
00040 struct symlist
00041 {
00042   const char *name;
00043   struct symlist *next;
00044 };
00045 
00046 /* A list to support redefine_sym.  */
00047 struct redefine_node
00048 {
00049   char *source;
00050   char *target;
00051   struct redefine_node *next;
00052 };
00053 
00054 typedef struct section_rename
00055 {
00056   const char *            old_name;
00057   const char *            new_name;
00058   flagword                flags;
00059   struct section_rename * next;
00060 }
00061 section_rename;
00062 
00063 /* List of sections to be renamed.  */
00064 static section_rename *section_rename_list;
00065 
00066 #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
00067 
00068 static asymbol **isympp = NULL;    /* Input symbols.  */
00069 static asymbol **osympp = NULL;    /* Output symbols that survive stripping.  */
00070 
00071 /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
00072 static int copy_byte = -1;
00073 static int interleave = 4;
00074 
00075 static bfd_boolean verbose;        /* Print file and target names.  */
00076 static bfd_boolean preserve_dates; /* Preserve input file timestamp.  */
00077 static int status = 0;             /* Exit status.  */
00078 
00079 enum strip_action
00080   {
00081     STRIP_UNDEF,
00082     STRIP_NONE,                    /* Don't strip.  */
00083     STRIP_DEBUG,            /* Strip all debugger symbols.  */
00084     STRIP_UNNEEDED,         /* Strip unnecessary symbols.  */
00085     STRIP_NONDEBUG,         /* Strip everything but debug info.  */
00086     STRIP_ALL               /* Strip all symbols.  */
00087   };
00088 
00089 /* Which symbols to remove.  */
00090 static enum strip_action strip_symbols;
00091 
00092 enum locals_action
00093   {
00094     LOCALS_UNDEF,
00095     LOCALS_START_L,         /* Discard locals starting with L.  */
00096     LOCALS_ALL                     /* Discard all locals.  */
00097   };
00098 
00099 /* Which local symbols to remove.  Overrides STRIP_ALL.  */
00100 static enum locals_action discard_locals;
00101 
00102 /* What kind of change to perform.  */
00103 enum change_action
00104 {
00105   CHANGE_IGNORE,
00106   CHANGE_MODIFY,
00107   CHANGE_SET
00108 };
00109 
00110 /* Structure used to hold lists of sections and actions to take.  */
00111 struct section_list
00112 {
00113   struct section_list * next;         /* Next section to change.  */
00114   const char *              name;     /* Section name.  */
00115   bfd_boolean        used;     /* Whether this entry was used.  */
00116   bfd_boolean        remove;          /* Whether to remove this section.  */
00117   bfd_boolean        copy;     /* Whether to copy this section.  */
00118   enum change_action change_vma;/* Whether to change or set VMA.  */
00119   bfd_vma            vma_val;   /* Amount to change by or set to.  */
00120   enum change_action change_lma;/* Whether to change or set LMA.  */
00121   bfd_vma            lma_val;   /* Amount to change by or set to.  */
00122   bfd_boolean        set_flags; /* Whether to set the section flags.   */
00123   flagword           flags;    /* What to set the section flags to.    */
00124 };
00125 
00126 static struct section_list *change_sections;
00127 
00128 /* TRUE if some sections are to be removed.  */
00129 static bfd_boolean sections_removed;
00130 
00131 /* TRUE if only some sections are to be copied.  */
00132 static bfd_boolean sections_copied;
00133 
00134 /* Changes to the start address.  */
00135 static bfd_vma change_start = 0;
00136 static bfd_boolean set_start_set = FALSE;
00137 static bfd_vma set_start;
00138 
00139 /* Changes to section addresses.  */
00140 static bfd_vma change_section_address = 0;
00141 
00142 /* Filling gaps between sections.  */
00143 static bfd_boolean gap_fill_set = FALSE;
00144 static bfd_byte gap_fill = 0;
00145 
00146 /* Pad to a given address.  */
00147 static bfd_boolean pad_to_set = FALSE;
00148 static bfd_vma pad_to;
00149 
00150 /* Use alternative machine code?  */
00151 static unsigned long use_alt_mach_code = 0;
00152 
00153 /* Output BFD flags user wants to set or clear */
00154 static flagword bfd_flags_to_set;
00155 static flagword bfd_flags_to_clear;
00156 
00157 /* List of sections to add.  */
00158 struct section_add
00159 {
00160   /* Next section to add.  */
00161   struct section_add *next;
00162   /* Name of section to add.  */
00163   const char *name;
00164   /* Name of file holding section contents.  */
00165   const char *filename;
00166   /* Size of file.  */
00167   size_t size;
00168   /* Contents of file.  */
00169   bfd_byte *contents;
00170   /* BFD section, after it has been added.  */
00171   asection *section;
00172 };
00173 
00174 /* List of sections to add to the output BFD.  */
00175 static struct section_add *add_sections;
00176 
00177 /* If non-NULL the argument to --add-gnu-debuglink.
00178    This should be the filename to store in the .gnu_debuglink section.  */
00179 static const char * gnu_debuglink_filename = NULL;
00180 
00181 /* Whether to convert debugging information.  */
00182 static bfd_boolean convert_debugging = FALSE;
00183 
00184 /* Whether to change the leading character in symbol names.  */
00185 static bfd_boolean change_leading_char = FALSE;
00186 
00187 /* Whether to remove the leading character from global symbol names.  */
00188 static bfd_boolean remove_leading_char = FALSE;
00189 
00190 /* Whether to permit wildcard in symbol comparison.  */
00191 static bfd_boolean wildcard = FALSE;
00192 
00193 /* True if --localize-hidden is in effect.  */
00194 static bfd_boolean localize_hidden = FALSE;
00195 
00196 /* List of symbols to strip, keep, localize, keep-global, weaken,
00197    or redefine.  */
00198 static struct symlist *strip_specific_list = NULL;
00199 static struct symlist *strip_unneeded_list = NULL;
00200 static struct symlist *keep_specific_list = NULL;
00201 static struct symlist *localize_specific_list = NULL;
00202 static struct symlist *globalize_specific_list = NULL;
00203 static struct symlist *keepglobal_specific_list = NULL;
00204 static struct symlist *weaken_specific_list = NULL;
00205 static struct redefine_node *redefine_sym_list = NULL;
00206 
00207 /* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
00208 static bfd_boolean weaken = FALSE;
00209 
00210 /* If this is TRUE, we retain BSF_FILE symbols.  */
00211 static bfd_boolean keep_file_symbols = FALSE;
00212 
00213 /* Prefix symbols/sections.  */
00214 static char *prefix_symbols_string = 0;
00215 static char *prefix_sections_string = 0;
00216 static char *prefix_alloc_sections_string = 0;
00217 
00218 /* True if --extract-symbol was passed on the command line.  */
00219 static bfd_boolean extract_symbol = FALSE;
00220 
00221 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
00222 enum command_line_switch
00223   {
00224     OPTION_ADD_SECTION=150,
00225     OPTION_CHANGE_ADDRESSES,
00226     OPTION_CHANGE_LEADING_CHAR,
00227     OPTION_CHANGE_START,
00228     OPTION_CHANGE_SECTION_ADDRESS,
00229     OPTION_CHANGE_SECTION_LMA,
00230     OPTION_CHANGE_SECTION_VMA,
00231     OPTION_CHANGE_WARNINGS,
00232     OPTION_DEBUGGING,
00233     OPTION_GAP_FILL,
00234     OPTION_NO_CHANGE_WARNINGS,
00235     OPTION_PAD_TO,
00236     OPTION_REMOVE_LEADING_CHAR,
00237     OPTION_SET_SECTION_FLAGS,
00238     OPTION_SET_START,
00239     OPTION_STRIP_UNNEEDED,
00240     OPTION_WEAKEN,
00241     OPTION_REDEFINE_SYM,
00242     OPTION_REDEFINE_SYMS,
00243     OPTION_SREC_LEN,
00244     OPTION_SREC_FORCES3,
00245     OPTION_STRIP_SYMBOLS,
00246     OPTION_STRIP_UNNEEDED_SYMBOL,
00247     OPTION_STRIP_UNNEEDED_SYMBOLS,
00248     OPTION_KEEP_SYMBOLS,
00249     OPTION_LOCALIZE_HIDDEN,
00250     OPTION_LOCALIZE_SYMBOLS,
00251     OPTION_GLOBALIZE_SYMBOL,
00252     OPTION_GLOBALIZE_SYMBOLS,
00253     OPTION_KEEPGLOBAL_SYMBOLS,
00254     OPTION_WEAKEN_SYMBOLS,
00255     OPTION_RENAME_SECTION,
00256     OPTION_ALT_MACH_CODE,
00257     OPTION_PREFIX_SYMBOLS,
00258     OPTION_PREFIX_SECTIONS,
00259     OPTION_PREFIX_ALLOC_SECTIONS,
00260     OPTION_FORMATS_INFO,
00261     OPTION_ADD_GNU_DEBUGLINK,
00262     OPTION_ONLY_KEEP_DEBUG,
00263     OPTION_KEEP_FILE_SYMBOLS,
00264     OPTION_READONLY_TEXT,
00265     OPTION_WRITABLE_TEXT,
00266     OPTION_PURE,
00267     OPTION_IMPURE,
00268     OPTION_EXTRACT_SYMBOL
00269   };
00270 
00271 /* Options to handle if running as "strip".  */
00272 
00273 static struct option strip_options[] =
00274 {
00275   {"discard-all", no_argument, 0, 'x'},
00276   {"discard-locals", no_argument, 0, 'X'},
00277   {"format", required_argument, 0, 'F'}, /* Obsolete */
00278   {"help", no_argument, 0, 'h'},
00279   {"info", no_argument, 0, OPTION_FORMATS_INFO},
00280   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
00281   {"input-target", required_argument, 0, 'I'},
00282   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
00283   {"keep-symbol", required_argument, 0, 'K'},
00284   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
00285   {"output-format", required_argument, 0, 'O'},  /* Obsolete */
00286   {"output-target", required_argument, 0, 'O'},
00287   {"output-file", required_argument, 0, 'o'},
00288   {"preserve-dates", no_argument, 0, 'p'},
00289   {"remove-section", required_argument, 0, 'R'},
00290   {"strip-all", no_argument, 0, 's'},
00291   {"strip-debug", no_argument, 0, 'S'},
00292   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
00293   {"strip-symbol", required_argument, 0, 'N'},
00294   {"target", required_argument, 0, 'F'},
00295   {"verbose", no_argument, 0, 'v'},
00296   {"version", no_argument, 0, 'V'},
00297   {"wildcard", no_argument, 0, 'w'},
00298   {0, no_argument, 0, 0}
00299 };
00300 
00301 /* Options to handle if running as "objcopy".  */
00302 
00303 static struct option copy_options[] =
00304 {
00305   {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
00306   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
00307   {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
00308   {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
00309   {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
00310   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
00311   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
00312   {"binary-architecture", required_argument, 0, 'B'},
00313   {"byte", required_argument, 0, 'b'},
00314   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
00315   {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
00316   {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
00317   {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
00318   {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
00319   {"change-start", required_argument, 0, OPTION_CHANGE_START},
00320   {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
00321   {"debugging", no_argument, 0, OPTION_DEBUGGING},
00322   {"discard-all", no_argument, 0, 'x'},
00323   {"discard-locals", no_argument, 0, 'X'},
00324   {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
00325   {"format", required_argument, 0, 'F'}, /* Obsolete */
00326   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
00327   {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
00328   {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
00329   {"help", no_argument, 0, 'h'},
00330   {"impure", no_argument, 0, OPTION_IMPURE},
00331   {"info", no_argument, 0, OPTION_FORMATS_INFO},
00332   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
00333   {"input-target", required_argument, 0, 'I'},
00334   {"interleave", required_argument, 0, 'i'},
00335   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
00336   {"keep-global-symbol", required_argument, 0, 'G'},
00337   {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
00338   {"keep-symbol", required_argument, 0, 'K'},
00339   {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
00340   {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
00341   {"localize-symbol", required_argument, 0, 'L'},
00342   {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
00343   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
00344   {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
00345   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
00346   {"only-section", required_argument, 0, 'j'},
00347   {"output-format", required_argument, 0, 'O'},  /* Obsolete */
00348   {"output-target", required_argument, 0, 'O'},
00349   {"pad-to", required_argument, 0, OPTION_PAD_TO},
00350   {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
00351   {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
00352   {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
00353   {"preserve-dates", no_argument, 0, 'p'},
00354   {"pure", no_argument, 0, OPTION_PURE},
00355   {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
00356   {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
00357   {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
00358   {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
00359   {"remove-section", required_argument, 0, 'R'},
00360   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
00361   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
00362   {"set-start", required_argument, 0, OPTION_SET_START},
00363   {"srec-len", required_argument, 0, OPTION_SREC_LEN},
00364   {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
00365   {"strip-all", no_argument, 0, 'S'},
00366   {"strip-debug", no_argument, 0, 'g'},
00367   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
00368   {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
00369   {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
00370   {"strip-symbol", required_argument, 0, 'N'},
00371   {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
00372   {"target", required_argument, 0, 'F'},
00373   {"verbose", no_argument, 0, 'v'},
00374   {"version", no_argument, 0, 'V'},
00375   {"weaken", no_argument, 0, OPTION_WEAKEN},
00376   {"weaken-symbol", required_argument, 0, 'W'},
00377   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
00378   {"wildcard", no_argument, 0, 'w'},
00379   {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
00380   {0, no_argument, 0, 0}
00381 };
00382 
00383 /* IMPORTS */
00384 extern char *program_name;
00385 
00386 /* This flag distinguishes between strip and objcopy:
00387    1 means this is 'strip'; 0 means this is 'objcopy'.
00388    -1 means if we should use argv[0] to decide.  */
00389 extern int is_strip;
00390 
00391 /* The maximum length of an S record.  This variable is declared in srec.c
00392    and can be modified by the --srec-len parameter.  */
00393 extern unsigned int Chunk;
00394 
00395 /* Restrict the generation of Srecords to type S3 only.
00396    This variable is declare in bfd/srec.c and can be toggled
00397    on by the --srec-forceS3 command line switch.  */
00398 extern bfd_boolean S3Forced;
00399 
00400 /* Defined in bfd/binary.c.  Used to set architecture and machine of input
00401    binary files.  */
00402 extern enum bfd_architecture  bfd_external_binary_architecture;
00403 extern unsigned long          bfd_external_machine;
00404 
00405 /* Forward declarations.  */
00406 static void setup_section (bfd *, asection *, void *);
00407 static void setup_bfd_headers (bfd *, bfd *);
00408 static void copy_section (bfd *, asection *, void *);
00409 static void get_sections (bfd *, asection *, void *);
00410 static int compare_section_lma (const void *, const void *);
00411 static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
00412 static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
00413 static const char *lookup_sym_redefinition (const char *);
00414 
00415 static void
00416 copy_usage (FILE *stream, int exit_status)
00417 {
00418   fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
00419   fprintf (stream, _(" Copies a binary file, possibly transforming it in the process\n"));
00420   fprintf (stream, _(" The options are:\n"));
00421   fprintf (stream, _("\
00422   -I --input-target <bfdname>      Assume input file is in format <bfdname>\n\
00423   -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
00424   -B --binary-architecture <arch>  Set arch of output file, when input is binary\n\
00425   -F --target <bfdname>            Set both input and output format to <bfdname>\n\
00426      --debugging                   Convert debugging information, if possible\n\
00427   -p --preserve-dates              Copy modified/access timestamps to the output\n\
00428   -j --only-section <name>         Only copy section <name> into the output\n\
00429      --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\n\
00430   -R --remove-section <name>       Remove section <name> from the output\n\
00431   -S --strip-all                   Remove all symbol and relocation information\n\
00432   -g --strip-debug                 Remove all debugging symbols & sections\n\
00433      --strip-unneeded              Remove all symbols not needed by relocations\n\
00434   -N --strip-symbol <name>         Do not copy symbol <name>\n\
00435      --strip-unneeded-symbol <name>\n\
00436                                    Do not copy symbol <name> unless needed by\n\
00437                                      relocations\n\
00438      --only-keep-debug             Strip everything but the debug information\n\
00439      --extract-symbol              Remove section contents but keep symbols\n\
00440   -K --keep-symbol <name>          Do not strip symbol <name>\n\
00441      --keep-file-symbols           Do not strip file symbol(s)\n\
00442      --localize-hidden             Turn all ELF hidden symbols into locals\n\
00443   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
00444      --globalize-symbol <name>     Force symbol <name> to be marked as a global\n\
00445   -G --keep-global-symbol <name>   Localize all symbols except <name>\n\
00446   -W --weaken-symbol <name>        Force symbol <name> to be marked as a weak\n\
00447      --weaken                      Force all global symbols to be marked as weak\n\
00448   -w --wildcard                    Permit wildcard in symbol comparison\n\
00449   -x --discard-all                 Remove all non-global symbols\n\
00450   -X --discard-locals              Remove any compiler-generated symbols\n\
00451   -i --interleave <number>         Only copy one out of every <number> bytes\n\
00452   -b --byte <num>                  Select byte <num> in every interleaved block\n\
00453      --gap-fill <val>              Fill gaps between sections with <val>\n\
00454      --pad-to <addr>               Pad the last section up to address <addr>\n\
00455      --set-start <addr>            Set the start address to <addr>\n\
00456     {--change-start|--adjust-start} <incr>\n\
00457                                    Add <incr> to the start address\n\
00458     {--change-addresses|--adjust-vma} <incr>\n\
00459                                    Add <incr> to LMA, VMA and start addresses\n\
00460     {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\
00461                                    Change LMA and VMA of section <name> by <val>\n\
00462      --change-section-lma <name>{=|+|-}<val>\n\
00463                                    Change the LMA of section <name> by <val>\n\
00464      --change-section-vma <name>{=|+|-}<val>\n\
00465                                    Change the VMA of section <name> by <val>\n\
00466     {--[no-]change-warnings|--[no-]adjust-warnings}\n\
00467                                    Warn if a named section does not exist\n\
00468      --set-section-flags <name>=<flags>\n\
00469                                    Set section <name>'s properties to <flags>\n\
00470      --add-section <name>=<file>   Add section <name> found in <file> to output\n\
00471      --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
00472      --change-leading-char         Force output format's leading character style\n\
00473      --remove-leading-char         Remove leading character from global symbols\n\
00474      --redefine-sym <old>=<new>    Redefine symbol name <old> to <new>\n\
00475      --redefine-syms <file>        --redefine-sym for all symbol pairs \n\
00476                                      listed in <file>\n\
00477      --srec-len <number>           Restrict the length of generated Srecords\n\
00478      --srec-forceS3                Restrict the type of generated Srecords to S3\n\
00479      --strip-symbols <file>        -N for all symbols listed in <file>\n\
00480      --strip-unneeded-symbols <file>\n\
00481                                    --strip-unneeded-symbol for all symbols listed\n\
00482                                      in <file>\n\
00483      --keep-symbols <file>         -K for all symbols listed in <file>\n\
00484      --localize-symbols <file>     -L for all symbols listed in <file>\n\
00485      --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
00486      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
00487      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
00488      --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
00489      --writable-text               Mark the output text as writable\n\
00490      --readonly-text               Make the output text write protected\n\
00491      --pure                        Mark the output file as demand paged\n\
00492      --impure                      Mark the output file as impure\n\
00493      --prefix-symbols <prefix>     Add <prefix> to start of every symbol name\n\
00494      --prefix-sections <prefix>    Add <prefix> to start of every section name\n\
00495      --prefix-alloc-sections <prefix>\n\
00496                                    Add <prefix> to start of every allocatable\n\
00497                                      section name\n\
00498   -v --verbose                     List all object files modified\n\
00499   @<file>                          Read options from <file>\n\
00500   -V --version                     Display this program's version number\n\
00501   -h --help                        Display this output\n\
00502      --info                        List object formats & architectures supported\n\
00503 "));
00504   list_supported_targets (program_name, stream);
00505   if (REPORT_BUGS_TO[0] && exit_status == 0)
00506     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
00507   exit (exit_status);
00508 }
00509 
00510 static void
00511 strip_usage (FILE *stream, int exit_status)
00512 {
00513   fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name);
00514   fprintf (stream, _(" Removes symbols and sections from files\n"));
00515   fprintf (stream, _(" The options are:\n"));
00516   fprintf (stream, _("\
00517   -I --input-target=<bfdname>      Assume input file is in format <bfdname>\n\
00518   -O --output-target=<bfdname>     Create an output file in format <bfdname>\n\
00519   -F --target=<bfdname>            Set both input and output format to <bfdname>\n\
00520   -p --preserve-dates              Copy modified/access timestamps to the output\n\
00521   -R --remove-section=<name>       Remove section <name> from the output\n\
00522   -s --strip-all                   Remove all symbol and relocation information\n\
00523   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
00524      --strip-unneeded              Remove all symbols not needed by relocations\n\
00525      --only-keep-debug             Strip everything but the debug information\n\
00526   -N --strip-symbol=<name>         Do not copy symbol <name>\n\
00527   -K --keep-symbol=<name>          Do not strip symbol <name>\n\
00528      --keep-file-symbols           Do not strip file symbol(s)\n\
00529   -w --wildcard                    Permit wildcard in symbol comparison\n\
00530   -x --discard-all                 Remove all non-global symbols\n\
00531   -X --discard-locals              Remove any compiler-generated symbols\n\
00532   -v --verbose                     List all object files modified\n\
00533   -V --version                     Display this program's version number\n\
00534   -h --help                        Display this output\n\
00535      --info                        List object formats & architectures supported\n\
00536   -o <file>                        Place stripped output into <file>\n\
00537 "));
00538 
00539   list_supported_targets (program_name, stream);
00540   if (REPORT_BUGS_TO[0] && exit_status == 0)
00541     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
00542   exit (exit_status);
00543 }
00544 
00545 /* Parse section flags into a flagword, with a fatal error if the
00546    string can't be parsed.  */
00547 
00548 static flagword
00549 parse_flags (const char *s)
00550 {
00551   flagword ret;
00552   const char *snext;
00553   int len;
00554 
00555   ret = SEC_NO_FLAGS;
00556 
00557   do
00558     {
00559       snext = strchr (s, ',');
00560       if (snext == NULL)
00561        len = strlen (s);
00562       else
00563        {
00564          len = snext - s;
00565          ++snext;
00566        }
00567 
00568       if (0) ;
00569 #define PARSE_FLAG(fname,fval) \
00570   else if (strncasecmp (fname, s, len) == 0) ret |= fval
00571       PARSE_FLAG ("alloc", SEC_ALLOC);
00572       PARSE_FLAG ("load", SEC_LOAD);
00573       PARSE_FLAG ("noload", SEC_NEVER_LOAD);
00574       PARSE_FLAG ("readonly", SEC_READONLY);
00575       PARSE_FLAG ("debug", SEC_DEBUGGING);
00576       PARSE_FLAG ("code", SEC_CODE);
00577       PARSE_FLAG ("data", SEC_DATA);
00578       PARSE_FLAG ("rom", SEC_ROM);
00579       PARSE_FLAG ("share", SEC_COFF_SHARED);
00580       PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
00581 #undef PARSE_FLAG
00582       else
00583        {
00584          char *copy;
00585 
00586          copy = xmalloc (len + 1);
00587          strncpy (copy, s, len);
00588          copy[len] = '\0';
00589          non_fatal (_("unrecognized section flag `%s'"), copy);
00590          fatal (_("supported flags: %s"),
00591                "alloc, load, noload, readonly, debug, code, data, rom, share, contents");
00592        }
00593 
00594       s = snext;
00595     }
00596   while (s != NULL);
00597 
00598   return ret;
00599 }
00600 
00601 /* Find and optionally add an entry in the change_sections list.  */
00602 
00603 static struct section_list *
00604 find_section_list (const char *name, bfd_boolean add)
00605 {
00606   struct section_list *p;
00607 
00608   for (p = change_sections; p != NULL; p = p->next)
00609     if (strcmp (p->name, name) == 0)
00610       return p;
00611 
00612   if (! add)
00613     return NULL;
00614 
00615   p = xmalloc (sizeof (struct section_list));
00616   p->name = name;
00617   p->used = FALSE;
00618   p->remove = FALSE;
00619   p->copy = FALSE;
00620   p->change_vma = CHANGE_IGNORE;
00621   p->change_lma = CHANGE_IGNORE;
00622   p->vma_val = 0;
00623   p->lma_val = 0;
00624   p->set_flags = FALSE;
00625   p->flags = 0;
00626 
00627   p->next = change_sections;
00628   change_sections = p;
00629 
00630   return p;
00631 }
00632 
00633 /* Add a symbol to strip_specific_list.  */
00634 
00635 static void
00636 add_specific_symbol (const char *name, struct symlist **list)
00637 {
00638   struct symlist *tmp_list;
00639 
00640   tmp_list = xmalloc (sizeof (struct symlist));
00641   tmp_list->name = name;
00642   tmp_list->next = *list;
00643   *list = tmp_list;
00644 }
00645 
00646 /* Add symbols listed in `filename' to strip_specific_list.  */
00647 
00648 #define IS_WHITESPACE(c)      ((c) == ' ' || (c) == '\t')
00649 #define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
00650 
00651 static void
00652 add_specific_symbols (const char *filename, struct symlist **list)
00653 {
00654   off_t  size;
00655   FILE * f;
00656   char * line;
00657   char * buffer;
00658   unsigned int line_count;
00659 
00660   size = get_file_size (filename);
00661   if (size == 0)
00662     {
00663       status = 1;
00664       return;
00665     }
00666 
00667   buffer = xmalloc (size + 2);
00668   f = fopen (filename, FOPEN_RT);
00669   if (f == NULL)
00670     fatal (_("cannot open '%s': %s"), filename, strerror (errno));
00671 
00672   if (fread (buffer, 1, size, f) == 0 || ferror (f))
00673     fatal (_("%s: fread failed"), filename);
00674 
00675   fclose (f);
00676   buffer [size] = '\n';
00677   buffer [size + 1] = '\0';
00678 
00679   line_count = 1;
00680 
00681   for (line = buffer; * line != '\0'; line ++)
00682     {
00683       char * eol;
00684       char * name;
00685       char * name_end;
00686       int finished = FALSE;
00687 
00688       for (eol = line;; eol ++)
00689        {
00690          switch (* eol)
00691            {
00692            case '\n':
00693              * eol = '\0';
00694              /* Cope with \n\r.  */
00695              if (eol[1] == '\r')
00696               ++ eol;
00697              finished = TRUE;
00698              break;
00699 
00700            case '\r':
00701              * eol = '\0';
00702              /* Cope with \r\n.  */
00703              if (eol[1] == '\n')
00704               ++ eol;
00705              finished = TRUE;
00706              break;
00707 
00708            case 0:
00709              finished = TRUE;
00710              break;
00711 
00712            case '#':
00713              /* Line comment, Terminate the line here, in case a
00714                name is present and then allow the rest of the
00715                loop to find the real end of the line.  */
00716              * eol = '\0';
00717              break;
00718 
00719            default:
00720              break;
00721            }
00722 
00723          if (finished)
00724            break;
00725        }
00726 
00727       /* A name may now exist somewhere between 'line' and 'eol'.
00728         Strip off leading whitespace and trailing whitespace,
00729         then add it to the list.  */
00730       for (name = line; IS_WHITESPACE (* name); name ++)
00731        ;
00732       for (name_end = name;
00733           (! IS_WHITESPACE (* name_end))
00734           && (! IS_LINE_TERMINATOR (* name_end));
00735           name_end ++)
00736        ;
00737 
00738       if (! IS_LINE_TERMINATOR (* name_end))
00739        {
00740          char * extra;
00741 
00742          for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++)
00743            ;
00744 
00745          if (! IS_LINE_TERMINATOR (* extra))
00746            non_fatal (_("%s:%d: Ignoring rubbish found on this line"),
00747                      filename, line_count);
00748        }
00749 
00750       * name_end = '\0';
00751 
00752       if (name_end > name)
00753        add_specific_symbol (name, list);
00754 
00755       /* Advance line pointer to end of line.  The 'eol ++' in the for
00756         loop above will then advance us to the start of the next line.  */
00757       line = eol;
00758       line_count ++;
00759     }
00760 }
00761 
00762 /* See whether a symbol should be stripped or kept based on
00763    strip_specific_list and keep_symbols.  */
00764 
00765 static bfd_boolean
00766 is_specified_symbol (const char *name, struct symlist *list)
00767 {
00768   struct symlist *tmp_list;
00769 
00770   if (wildcard)
00771     {
00772       for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
00773        if (*(tmp_list->name) != '!')
00774          {
00775            if (!fnmatch (tmp_list->name, name, 0))
00776              return TRUE;
00777          }
00778        else
00779          {
00780            if (fnmatch (tmp_list->name + 1, name, 0))
00781              return TRUE;
00782          }
00783     }
00784   else
00785     {
00786       for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
00787        if (strcmp (name, tmp_list->name) == 0)
00788          return TRUE;
00789     }
00790 
00791   return FALSE;
00792 }
00793 
00794 /* Return a pointer to the symbol used as a signature for GROUP.  */
00795 
00796 static asymbol *
00797 group_signature (asection *group)
00798 {
00799   bfd *abfd = group->owner;
00800   Elf_Internal_Shdr *ghdr;
00801 
00802   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
00803     return NULL;
00804 
00805   ghdr = &elf_section_data (group)->this_hdr;
00806   if (ghdr->sh_link < elf_numsections (abfd))
00807     {
00808       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
00809       Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
00810 
00811       if (symhdr->sh_type == SHT_SYMTAB
00812          && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
00813        return isympp[ghdr->sh_info - 1];
00814     }
00815   return NULL;
00816 }
00817 
00818 /* See if a section is being removed.  */
00819 
00820 static bfd_boolean
00821 is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
00822 {
00823   if (sections_removed || sections_copied)
00824     {
00825       struct section_list *p;
00826 
00827       p = find_section_list (bfd_get_section_name (abfd, sec), FALSE);
00828 
00829       if (sections_removed && p != NULL && p->remove)
00830        return TRUE;
00831       if (sections_copied && (p == NULL || ! p->copy))
00832        return TRUE;
00833     }
00834 
00835   if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0)
00836     {
00837       if (strip_symbols == STRIP_DEBUG
00838          || strip_symbols == STRIP_UNNEEDED
00839          || strip_symbols == STRIP_ALL
00840          || discard_locals == LOCALS_ALL
00841          || convert_debugging)
00842        return TRUE;
00843 
00844       if (strip_symbols == STRIP_NONDEBUG)
00845        return FALSE;
00846     }
00847 
00848   if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
00849     {
00850       asymbol *gsym;
00851       const char *gname;
00852 
00853       /* PR binutils/3166
00854         Group sections look like debugging sections but they are not.
00855         (They have a non-zero size but they are not ALLOCated).  */
00856       if (strip_symbols == STRIP_NONDEBUG)
00857        return TRUE;
00858 
00859       /* PR binutils/3181
00860         If we are going to strip the group signature symbol, then
00861         strip the group section too.  */
00862       gsym = group_signature (sec);
00863       if (gsym != NULL)
00864        gname = gsym->name;
00865       else
00866        gname = sec->name;
00867       if ((strip_symbols == STRIP_ALL
00868           && !is_specified_symbol (gname, keep_specific_list))
00869          || is_specified_symbol (gname, strip_specific_list))
00870        return TRUE;
00871     }
00872 
00873   return FALSE;
00874 }
00875 
00876 /* Return true if SYM is a hidden symbol.  */
00877 
00878 static bfd_boolean
00879 is_hidden_symbol (asymbol *sym)
00880 {
00881   elf_symbol_type *elf_sym;
00882 
00883   elf_sym = elf_symbol_from (sym->the_bfd, sym);
00884   if (elf_sym != NULL)
00885     switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
00886       {
00887       case STV_HIDDEN:
00888       case STV_INTERNAL:
00889        return TRUE;
00890       }
00891   return FALSE;
00892 }
00893 
00894 /* Choose which symbol entries to copy; put the result in OSYMS.
00895    We don't copy in place, because that confuses the relocs.
00896    Return the number of symbols to print.  */
00897 
00898 static unsigned int
00899 filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
00900               asymbol **isyms, long symcount)
00901 {
00902   asymbol **from = isyms, **to = osyms;
00903   long src_count = 0, dst_count = 0;
00904   int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC))
00905                   == HAS_RELOC;
00906 
00907   for (; src_count < symcount; src_count++)
00908     {
00909       asymbol *sym = from[src_count];
00910       flagword flags = sym->flags;
00911       char *name = (char *) bfd_asymbol_name (sym);
00912       int keep;
00913       bfd_boolean undefined;
00914       bfd_boolean rem_leading_char;
00915       bfd_boolean add_leading_char;
00916 
00917       undefined = bfd_is_und_section (bfd_get_section (sym));
00918 
00919       if (redefine_sym_list)
00920        {
00921          char *old_name, *new_name;
00922 
00923          old_name = (char *) bfd_asymbol_name (sym);
00924          new_name = (char *) lookup_sym_redefinition (old_name);
00925          bfd_asymbol_name (sym) = new_name;
00926          name = new_name;
00927        }
00928 
00929       /* Check if we will remove the current leading character.  */
00930       rem_leading_char =
00931        (name[0] == bfd_get_symbol_leading_char (abfd))
00932        && (change_leading_char
00933            || (remove_leading_char
00934               && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
00935                   || undefined
00936                   || bfd_is_com_section (bfd_get_section (sym)))));
00937 
00938       /* Check if we will add a new leading character.  */
00939       add_leading_char =
00940        change_leading_char
00941        && (bfd_get_symbol_leading_char (obfd) != '\0')
00942        && (bfd_get_symbol_leading_char (abfd) == '\0'
00943            || (name[0] == bfd_get_symbol_leading_char (abfd)));
00944 
00945       /* Short circuit for change_leading_char if we can do it in-place.  */
00946       if (rem_leading_char && add_leading_char && !prefix_symbols_string)
00947         {
00948          name[0] = bfd_get_symbol_leading_char (obfd);
00949          bfd_asymbol_name (sym) = name;
00950          rem_leading_char = FALSE;
00951          add_leading_char = FALSE;
00952         }
00953 
00954       /* Remove leading char.  */
00955       if (rem_leading_char)
00956        bfd_asymbol_name (sym) = ++name;
00957 
00958       /* Add new leading char and/or prefix.  */
00959       if (add_leading_char || prefix_symbols_string)
00960         {
00961           char *n, *ptr;
00962 
00963           ptr = n = xmalloc (1 + strlen (prefix_symbols_string)
00964                           + strlen (name) + 1);
00965           if (add_leading_char)
00966            *ptr++ = bfd_get_symbol_leading_char (obfd);
00967 
00968           if (prefix_symbols_string)
00969             {
00970               strcpy (ptr, prefix_symbols_string);
00971               ptr += strlen (prefix_symbols_string);
00972            }
00973 
00974           strcpy (ptr, name);
00975           bfd_asymbol_name (sym) = n;
00976           name = n;
00977        }
00978 
00979       if (strip_symbols == STRIP_ALL)
00980        keep = 0;
00981       else if ((flags & BSF_KEEP) != 0           /* Used in relocation.  */
00982               || ((flags & BSF_SECTION_SYM) != 0
00983                  && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
00984                      & BSF_KEEP) != 0))
00985        keep = 1;
00986       else if (relocatable                /* Relocatable file.  */
00987               && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
00988        keep = 1;
00989       else if (bfd_decode_symclass (sym) == 'I')
00990        /* Global symbols in $idata sections need to be retained
00991           even if relocatable is FALSE.  External users of the
00992           library containing the $idata section may reference these
00993           symbols.  */
00994        keep = 1;
00995       else if ((flags & BSF_GLOBAL) != 0  /* Global symbol.  */
00996               || (flags & BSF_WEAK) != 0
00997               || undefined
00998               || bfd_is_com_section (bfd_get_section (sym)))
00999        keep = strip_symbols != STRIP_UNNEEDED;
01000       else if ((flags & BSF_DEBUGGING) != 0)     /* Debugging symbol.  */
01001        keep = (strip_symbols != STRIP_DEBUG
01002               && strip_symbols != STRIP_UNNEEDED
01003               && ! convert_debugging);
01004       else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
01005        /* COMDAT sections store special information in local
01006           symbols, so we cannot risk stripping any of them.  */
01007        keep = 1;
01008       else                  /* Local symbol.  */
01009        keep = (strip_symbols != STRIP_UNNEEDED
01010               && (discard_locals != LOCALS_ALL
01011                   && (discard_locals != LOCALS_START_L
01012                      || ! bfd_is_local_label (abfd, sym))));
01013 
01014       if (keep && is_specified_symbol (name, strip_specific_list))
01015        keep = 0;
01016       if (keep
01017          && !(flags & BSF_KEEP)
01018          && is_specified_symbol (name, strip_unneeded_list))
01019        keep = 0;
01020       if (!keep
01021          && ((keep_file_symbols && (flags & BSF_FILE))
01022              || is_specified_symbol (name, keep_specific_list)))
01023        keep = 1;
01024       if (keep && is_strip_section (abfd, bfd_get_section (sym)))
01025        keep = 0;
01026 
01027       if (keep)
01028        {
01029          if ((flags & BSF_GLOBAL) != 0
01030              && (weaken || is_specified_symbol (name, weaken_specific_list)))
01031            {
01032              sym->flags &= ~ BSF_GLOBAL;
01033              sym->flags |= BSF_WEAK;
01034            }
01035 
01036          if (!undefined
01037              && (flags & (BSF_GLOBAL | BSF_WEAK))
01038              && (is_specified_symbol (name, localize_specific_list)
01039                 || (keepglobal_specific_list != NULL
01040                     && ! is_specified_symbol (name, keepglobal_specific_list))
01041                 || (localize_hidden && is_hidden_symbol (sym))))
01042            {
01043              sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
01044              sym->flags |= BSF_LOCAL;
01045            }
01046 
01047          if (!undefined
01048              && (flags & BSF_LOCAL) 
01049              && is_specified_symbol (name, globalize_specific_list))
01050            {
01051              sym->flags &= ~ BSF_LOCAL;
01052              sym->flags |= BSF_GLOBAL;
01053            }
01054 
01055          to[dst_count++] = sym;
01056        }
01057     }
01058 
01059   to[dst_count] = NULL;
01060 
01061   return dst_count;
01062 }
01063 
01064 /* Find the redefined name of symbol SOURCE.  */
01065 
01066 static const char *
01067 lookup_sym_redefinition (const char *source)
01068 {
01069   struct redefine_node *list;
01070 
01071   for (list = redefine_sym_list; list != NULL; list = list->next)
01072     if (strcmp (source, list->source) == 0)
01073       return list->target;
01074 
01075   return source;
01076 }
01077 
01078 /* Add a node to a symbol redefine list.  */
01079 
01080 static void
01081 redefine_list_append (const char *cause, const char *source, const char *target)
01082 {
01083   struct redefine_node **p;
01084   struct redefine_node *list;
01085   struct redefine_node *new_node;
01086 
01087   for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
01088     {
01089       if (strcmp (source, list->source) == 0)
01090        fatal (_("%s: Multiple redefinition of symbol \"%s\""),
01091               cause, source);
01092 
01093       if (strcmp (target, list->target) == 0)
01094        fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
01095               cause, target);
01096     }
01097 
01098   new_node = xmalloc (sizeof (struct redefine_node));
01099 
01100   new_node->source = strdup (source);
01101   new_node->target = strdup (target);
01102   new_node->next = NULL;
01103 
01104   *p = new_node;
01105 }
01106 
01107 /* Handle the --redefine-syms option.  Read lines containing "old new"
01108    from the file, and add them to the symbol redefine list.  */
01109 
01110 static void
01111 add_redefine_syms_file (const char *filename)
01112 {
01113   FILE *file;
01114   char *buf;
01115   size_t bufsize;
01116   size_t len;
01117   size_t outsym_off;
01118   int c, lineno;
01119 
01120   file = fopen (filename, "r");
01121   if (file == NULL)
01122     fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
01123           filename, strerror (errno));
01124 
01125   bufsize = 100;
01126   buf = xmalloc (bufsize);
01127 
01128   lineno = 1;
01129   c = getc (file);
01130   len = 0;
01131   outsym_off = 0;
01132   while (c != EOF)
01133     {
01134       /* Collect the input symbol name.  */
01135       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
01136        {
01137          if (c == '#')
01138            goto comment;
01139          buf[len++] = c;
01140          if (len >= bufsize)
01141            {
01142              bufsize *= 2;
01143              buf = xrealloc (buf, bufsize);
01144            }
01145          c = getc (file);
01146        }
01147       buf[len++] = '\0';
01148       if (c == EOF)
01149        break;
01150 
01151       /* Eat white space between the symbol names.  */
01152       while (IS_WHITESPACE (c))
01153        c = getc (file);
01154       if (c == '#' || IS_LINE_TERMINATOR (c))
01155        goto comment;
01156       if (c == EOF)
01157        break;
01158 
01159       /* Collect the output symbol name.  */
01160       outsym_off = len;
01161       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
01162        {
01163          if (c == '#')
01164            goto comment;
01165          buf[len++] = c;
01166          if (len >= bufsize)
01167            {
01168              bufsize *= 2;
01169              buf = xrealloc (buf, bufsize);
01170            }
01171          c = getc (file);
01172        }
01173       buf[len++] = '\0';
01174       if (c == EOF)
01175        break;
01176 
01177       /* Eat white space at end of line.  */
01178       while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c))
01179        c = getc (file);
01180       if (c == '#')
01181        goto comment;
01182       /* Handle \r\n.  */
01183       if ((c == '\r' && (c = getc (file)) == '\n')
01184          || c == '\n' || c == EOF)
01185        {
01186  end_of_line:
01187          /* Append the redefinition to the list.  */
01188          if (buf[0] != '\0')
01189            redefine_list_append (filename, &buf[0], &buf[outsym_off]);
01190 
01191          lineno++;   
01192          len = 0;
01193          outsym_off = 0;
01194          if (c == EOF)
01195            break;
01196          c = getc (file);
01197          continue;
01198        }
01199       else
01200        fatal (_("%s:%d: garbage found at end of line"), filename, lineno);
01201  comment:
01202       if (len != 0 && (outsym_off == 0 || outsym_off == len))
01203        fatal (_("%s:%d: missing new symbol name"), filename, lineno);
01204       buf[len++] = '\0';
01205 
01206       /* Eat the rest of the line and finish it.  */
01207       while (c != '\n' && c != EOF)
01208        c = getc (file);
01209       goto end_of_line;
01210     }
01211 
01212   if (len != 0)
01213     fatal (_("%s:%d: premature end of file"), filename, lineno);
01214 
01215   free (buf);
01216 }
01217 
01218 /* Copy unkown object file IBFD onto OBFD.
01219    Returns TRUE upon success, FALSE otherwise.  */
01220 
01221 static bfd_boolean
01222 copy_unknown_object (bfd *ibfd, bfd *obfd)
01223 {
01224   char *cbuf;
01225   int tocopy;
01226   long ncopied;
01227   long size;
01228   struct stat buf;
01229 
01230   if (bfd_stat_arch_elt (ibfd, &buf) != 0)
01231     {
01232       bfd_nonfatal (bfd_get_archive_filename (ibfd));
01233       return FALSE;
01234     }
01235 
01236   size = buf.st_size;
01237   if (size < 0)
01238     {
01239       non_fatal (_("stat returns negative size for `%s'"),
01240                bfd_get_archive_filename (ibfd));
01241       return FALSE;
01242     }
01243 
01244   if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0)
01245     {
01246       bfd_nonfatal (bfd_get_archive_filename (ibfd));
01247       return FALSE;
01248     }
01249 
01250   if (verbose)
01251     printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
01252            bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
01253 
01254   cbuf = xmalloc (BUFSIZE);
01255   ncopied = 0;
01256   while (ncopied < size)
01257     {
01258       tocopy = size - ncopied;
01259       if (tocopy > BUFSIZE)
01260        tocopy = BUFSIZE;
01261 
01262       if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
01263          != (bfd_size_type) tocopy)
01264        {
01265          bfd_nonfatal (bfd_get_archive_filename (ibfd));
01266          free (cbuf);
01267          return FALSE;
01268        }
01269 
01270       if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
01271          != (bfd_size_type) tocopy)
01272        {
01273          bfd_nonfatal (bfd_get_filename (obfd));
01274          free (cbuf);
01275          return FALSE;
01276        }
01277 
01278       ncopied += tocopy;
01279     }
01280 
01281   chmod (bfd_get_filename (obfd), buf.st_mode);
01282   free (cbuf);
01283   return TRUE;
01284 }
01285 
01286 /* Copy object file IBFD onto OBFD.
01287    Returns TRUE upon success, FALSE otherwise.  */
01288 
01289 static bfd_boolean
01290 copy_object (bfd *ibfd, bfd *obfd)
01291 {
01292   bfd_vma start;
01293   long symcount;
01294   asection **osections = NULL;
01295   asection *gnu_debuglink_section = NULL;
01296   bfd_size_type *gaps = NULL;
01297   bfd_size_type max_gap = 0;
01298   long symsize;
01299   void *dhandle;
01300   enum bfd_architecture iarch;
01301   unsigned int imach;
01302 
01303   if (ibfd->xvec->byteorder != obfd->xvec->byteorder
01304       && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
01305       && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
01306     fatal (_("Unable to change endianness of input file(s)"));
01307 
01308   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
01309     {
01310       bfd_nonfatal (bfd_get_filename (obfd));
01311       return FALSE;
01312     }
01313 
01314   if (verbose)
01315     printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
01316            bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
01317            bfd_get_filename (obfd), bfd_get_target (obfd));
01318 
01319   if (extract_symbol)
01320     start = 0;
01321   else
01322     {
01323       if (set_start_set)
01324        start = set_start;
01325       else
01326        start = bfd_get_start_address (ibfd);
01327       start += change_start;
01328     }
01329 
01330   /* Neither the start address nor the flags
01331      need to be set for a core file.  */
01332   if (bfd_get_format (obfd) != bfd_core)
01333     {
01334       flagword flags;
01335 
01336       flags = bfd_get_file_flags (ibfd);
01337       flags |= bfd_flags_to_set;
01338       flags &= ~bfd_flags_to_clear;
01339       flags &= bfd_applicable_file_flags (obfd);
01340 
01341       if (!bfd_set_start_address (obfd, start)
01342          || !bfd_set_file_flags (obfd, flags))
01343        {
01344          bfd_nonfatal (bfd_get_archive_filename (ibfd));
01345          return FALSE;
01346        }
01347     }
01348 
01349   /* Copy architecture of input file to output file.  */
01350   iarch = bfd_get_arch (ibfd);
01351   imach = bfd_get_mach (ibfd);
01352   if (!bfd_set_arch_mach (obfd, iarch, imach)
01353       && (ibfd->target_defaulted
01354          || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
01355     {
01356       if (bfd_get_arch (ibfd) == bfd_arch_unknown)
01357        non_fatal (_("Unable to recognise the format of the input file `%s'"),
01358                  bfd_get_archive_filename (ibfd));
01359       else
01360        non_fatal (_("Warning: Output file cannot represent architecture `%s'"),
01361                  bfd_printable_arch_mach (bfd_get_arch (ibfd),
01362                                        bfd_get_mach (ibfd)));
01363       return FALSE;
01364     }
01365 
01366   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
01367     {
01368       bfd_nonfatal (bfd_get_archive_filename (ibfd));
01369       return FALSE;
01370     }
01371 
01372   if (isympp)
01373     free (isympp);
01374 
01375   if (osympp != isympp)
01376     free (osympp);
01377 
01378   isympp = NULL;
01379   osympp = NULL;
01380 
01381   symsize = bfd_get_symtab_upper_bound (ibfd);
01382   if (symsize < 0)
01383     {
01384       bfd_nonfatal (bfd_get_archive_filename (ibfd));
01385       return FALSE;
01386     }
01387 
01388   osympp = isympp = xmalloc (symsize);
01389   symcount = bfd_canonicalize_symtab (ibfd, isympp);
01390   if (symcount < 0)
01391     {
01392       bfd_nonfatal (bfd_get_filename (ibfd));
01393       return FALSE;
01394     }
01395 
01396   /* BFD mandates that all output sections be created and sizes set before
01397      any output is done.  Thus, we traverse all sections multiple times.  */
01398   bfd_map_over_sections (ibfd, setup_section, obfd);
01399 
01400   setup_bfd_headers (ibfd, obfd);
01401 
01402   if (add_sections != NULL)
01403     {
01404       struct section_add *padd;
01405       struct section_list *pset;
01406 
01407       for (padd = add_sections; padd != NULL; padd = padd->next)
01408        {
01409          flagword flags;
01410 
01411          pset = find_section_list (padd->name, FALSE);
01412          if (pset != NULL)
01413            pset->used = TRUE;
01414 
01415          flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
01416          if (pset != NULL && pset->set_flags)
01417            flags = pset->flags | SEC_HAS_CONTENTS;
01418 
01419          /* bfd_make_section_with_flags() does not return very helpful
01420             error codes, so check for the most likely user error first.  */
01421          if (bfd_get_section_by_name (obfd, padd->name))
01422            {
01423              non_fatal (_("can't add section '%s' - it already exists!"), padd->name);
01424              return FALSE;
01425            }
01426          else
01427            {
01428              padd->section = bfd_make_section_with_flags (obfd, padd->name, flags);
01429              if (padd->section == NULL)
01430               {
01431                 non_fatal (_("can't create section `%s': %s"),
01432                           padd->name, bfd_errmsg (bfd_get_error ()));
01433                 return FALSE;
01434               }
01435            }
01436 
01437          if (! bfd_set_section_size (obfd, padd->section, padd->size))
01438            {
01439              bfd_nonfatal (bfd_get_filename (obfd));
01440              return FALSE;
01441            }
01442 
01443          if (pset != NULL)
01444            {
01445              if (pset->change_vma != CHANGE_IGNORE)
01446               if (! bfd_set_section_vma (obfd, padd->section,
01447                                       pset->vma_val))
01448                 {
01449                   bfd_nonfatal (bfd_get_filename (obfd));
01450                   return FALSE;
01451                 }
01452 
01453              if (pset->change_lma != CHANGE_IGNORE)
01454               {
01455                 padd->section->lma = pset->lma_val;
01456 
01457                 if (! bfd_set_section_alignment
01458                     (obfd, padd->section,
01459                      bfd_section_alignment (obfd, padd->section)))
01460                   {
01461                     bfd_nonfatal (bfd_get_filename (obfd));
01462                     return FALSE;
01463                   }
01464               }
01465            }
01466        }
01467     }
01468 
01469   if (gnu_debuglink_filename != NULL)
01470     {
01471       gnu_debuglink_section = bfd_create_gnu_debuglink_section
01472        (obfd, gnu_debuglink_filename);
01473 
01474       if (gnu_debuglink_section == NULL)
01475        {
01476          bfd_nonfatal (gnu_debuglink_filename);
01477          return FALSE;
01478        }
01479 
01480       /* Special processing for PE format files.  We
01481         have no way to distinguish PE from COFF here.  */
01482       if (bfd_get_flavour (obfd) == bfd_target_coff_flavour)
01483        {
01484          bfd_vma debuglink_vma;
01485          asection * highest_section;
01486          asection * sec;
01487 
01488          /* The PE spec requires that all sections be adjacent and sorted
01489             in ascending order of VMA.  It also specifies that debug
01490             sections should be last.  This is despite the fact that debug
01491             sections are not loaded into memory and so in theory have no
01492             use for a VMA.
01493 
01494             This means that the debuglink section must be given a non-zero
01495             VMA which makes it contiguous with other debug sections.  So
01496             walk the current section list, find the section with the
01497             highest VMA and start the debuglink section after that one.  */
01498          for (sec = obfd->sections, highest_section = NULL;
01499               sec != NULL;
01500               sec = sec->next)
01501            if (sec->vma > 0
01502               && (highest_section == NULL
01503                   || sec->vma > highest_section->vma))
01504              highest_section = sec;
01505 
01506          if (highest_section)
01507            debuglink_vma = BFD_ALIGN (highest_section->vma
01508                                    + highest_section->size,
01509                                    /* FIXME: We ought to be using
01510                                      COFF_PAGE_SIZE here or maybe
01511                                      bfd_get_section_alignment() (if it
01512                                      was set) but since this is for PE
01513                                      and we know the required alignment
01514                                      it is easier just to hard code it.  */
01515                                    0x1000);
01516          else
01517            /* Umm, not sure what to do in this case.  */
01518            debuglink_vma = 0x1000;
01519 
01520          bfd_set_section_vma (obfd, gnu_debuglink_section, debuglink_vma);
01521        }
01522     }
01523 
01524   if (bfd_count_sections (obfd) == 0)
01525     {
01526       non_fatal (_("there are no sections to be copied!"));
01527       return FALSE;
01528     }
01529 
01530   if (gap_fill_set || pad_to_set)
01531     {
01532       asection **set;
01533       unsigned int c, i;
01534 
01535       /* We must fill in gaps between the sections and/or we must pad
01536         the last section to a specified address.  We do this by
01537         grabbing a list of the sections, sorting them by VMA, and
01538         increasing the section sizes as required to fill the gaps.
01539         We write out the gap contents below.  */
01540 
01541       c = bfd_count_sections (obfd);
01542       osections = xmalloc (c * sizeof (asection *));
01543       set = osections;
01544       bfd_map_over_sections (obfd, get_sections, &set);
01545 
01546       qsort (osections, c, sizeof (asection *), compare_section_lma);
01547 
01548       gaps = xmalloc (c * sizeof (bfd_size_type));
01549       memset (gaps, 0, c * sizeof (bfd_size_type));
01550 
01551       if (gap_fill_set)
01552        {
01553          for (i = 0; i < c - 1; i++)
01554            {
01555              flagword flags;
01556              bfd_size_type size;
01557              bfd_vma gap_start, gap_stop;
01558 
01559              flags = bfd_get_section_flags (obfd, osections[i]);
01560              if ((flags & SEC_HAS_CONTENTS) == 0
01561                 || (flags & SEC_LOAD) == 0)
01562               continue;
01563 
01564              size = bfd_section_size (obfd, osections[i]);
01565              gap_start = bfd_section_lma (obfd, osections[i]) + size;
01566              gap_stop = bfd_section_lma (obfd, osections[i + 1]);
01567              if (gap_start < gap_stop)
01568               {
01569                 if (! bfd_set_section_size (obfd, osections[i],
01570                                          size + (gap_stop - gap_start)))
01571                   {
01572                     non_fatal (_("Can't fill gap after %s: %s"),
01573                              bfd_get_section_name (obfd, osections[i]),
01574                              bfd_errmsg (bfd_get_error ()));
01575                     status = 1;
01576                     break;
01577                   }
01578                 gaps[i] = gap_stop - gap_start;
01579                 if (max_gap < gap_stop - gap_start)
01580                   max_gap = gap_stop - gap_start;
01581               }
01582            }
01583        }
01584 
01585       if (pad_to_set)
01586        {
01587          bfd_vma lma;
01588          bfd_size_type size;
01589 
01590          lma = bfd_section_lma (obfd, osections[c - 1]);
01591          size = bfd_section_size (obfd, osections[c - 1]);
01592          if (lma + size < pad_to)
01593            {
01594              if (! bfd_set_section_size (obfd, osections[c - 1],
01595                                      pad_to - lma))
01596               {
01597                 non_fatal (_("Can't add padding to %s: %s"),
01598                           bfd_get_section_name (obfd, osections[c - 1]),
01599                           bfd_errmsg (bfd_get_error ()));
01600                 status = 1;
01601               }
01602              else
01603               {
01604                 gaps[c - 1] = pad_to - (lma + size);
01605                 if (max_gap < pad_to - (lma + size))
01606                   max_gap = pad_to - (lma + size);
01607               }
01608            }
01609        }
01610     }
01611 
01612   /* Symbol filtering must happen after the output sections
01613      have been created, but before their contents are set.  */
01614   dhandle = NULL;
01615   if (convert_debugging)
01616     dhandle = read_debugging_info (ibfd, isympp, symcount);
01617 
01618   if (strip_symbols == STRIP_DEBUG
01619       || strip_symbols == STRIP_ALL
01620       || strip_symbols == STRIP_UNNEEDED
01621       || strip_symbols == STRIP_NONDEBUG
01622       || discard_locals != LOCALS_UNDEF
01623       || localize_hidden
01624       || strip_specific_list != NULL
01625       || keep_specific_list != NULL
01626       || localize_specific_list != NULL
01627       || globalize_specific_list != NULL
01628       || keepglobal_specific_list != NULL
01629       || weaken_specific_list != NULL
01630       || prefix_symbols_string
01631       || sections_removed
01632       || sections_copied
01633       || convert_debugging
01634       || change_leading_char
01635       || remove_leading_char
01636       || redefine_sym_list
01637       || weaken)
01638     {
01639       /* Mark symbols used in output relocations so that they
01640         are kept, even if they are local labels or static symbols.
01641 
01642         Note we iterate over the input sections examining their
01643         relocations since the relocations for the output sections
01644         haven't been set yet.  mark_symbols_used_in_relocations will
01645         ignore input sections which have no corresponding output
01646         section.  */
01647       if (strip_symbols != STRIP_ALL)
01648        bfd_map_over_sections (ibfd,
01649                             mark_symbols_used_in_relocations,
01650                             isympp);
01651       osympp = xmalloc ((symcount + 1) * sizeof (asymbol *));
01652       symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
01653     }
01654 
01655   if (convert_debugging && dhandle != NULL)
01656     {
01657       if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
01658        {
01659          status = 1;
01660          return FALSE;
01661        }
01662     }
01663 
01664   bfd_set_symtab (obfd, osympp, symcount);
01665 
01666   /* This has to happen after the symbol table has been set.  */
01667   bfd_map_over_sections (ibfd, copy_section, obfd);
01668 
01669   if (add_sections != NULL)
01670     {
01671       struct section_add *padd;
01672 
01673       for (padd = add_sections; padd != NULL; padd = padd->next)
01674        {
01675          if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
01676                                      0, padd->size))
01677            {
01678              bfd_nonfatal (bfd_get_filename (obfd));
01679              return FALSE;
01680            }
01681        }
01682     }
01683 
01684   if (gnu_debuglink_filename != NULL)
01685     {
01686       if (! bfd_fill_in_gnu_debuglink_section
01687          (obfd, gnu_debuglink_section, gnu_debuglink_filename))
01688        {
01689          bfd_nonfatal (gnu_debuglink_filename);
01690          return FALSE;
01691        }
01692     }
01693 
01694   if (gap_fill_set || pad_to_set)
01695     {
01696       bfd_byte *buf;
01697       int c, i;
01698 
01699       /* Fill in the gaps.  */
01700       if (max_gap > 8192)
01701        max_gap = 8192;
01702       buf = xmalloc (max_gap);
01703       memset (buf, gap_fill, max_gap);
01704 
01705       c = bfd_count_sections (obfd);
01706       for (i = 0; i < c; i++)
01707        {
01708          if (gaps[i] != 0)
01709            {
01710              bfd_size_type left;
01711              file_ptr off;
01712 
01713              left = gaps[i];
01714              off = bfd_section_size (obfd, osections[i]) - left;
01715 
01716              while (left > 0)
01717               {
01718                 bfd_size_type now;
01719 
01720                 if (left > 8192)
01721                   now = 8192;
01722                 else
01723                   now = left;
01724 
01725                 if (! bfd_set_section_contents (obfd, osections[i], buf,
01726                                             off, now))
01727                   {
01728                     bfd_nonfatal (bfd_get_filename (obfd));
01729                     return FALSE;
01730                   }
01731 
01732                 left -= now;
01733                 off += now;
01734               }
01735            }
01736        }
01737     }
01738 
01739   /* Do not copy backend data if --extract-symbol is passed; anything
01740      that needs to look at the section contents will fail.  */
01741   if (extract_symbol)
01742     return TRUE;
01743 
01744   /* Allow the BFD backend to copy any private data it understands
01745      from the input BFD to the output BFD.  This is done last to
01746      permit the routine to look at the filtered symbol table, which is
01747      important for the ECOFF code at least.  */
01748   if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
01749       && strip_symbols == STRIP_NONDEBUG)
01750     /* Do not copy the private data when creating an ELF format
01751        debug info file.  We do not want the program headers.  */
01752     ;
01753   else if (! bfd_copy_private_bfd_data (ibfd, obfd))
01754     {
01755       non_fatal (_("%s: error copying private BFD data: %s"),
01756                bfd_get_filename (obfd),
01757                bfd_errmsg (bfd_get_error ()));
01758       return FALSE;
01759     }
01760 
01761   /* Switch to the alternate machine code.  We have to do this at the
01762      very end, because we only initialize the header when we create
01763      the first section.  */
01764   if (use_alt_mach_code != 0)
01765     {
01766       if (! bfd_alt_mach_code (obfd, use_alt_mach_code))
01767        {
01768          non_fatal (_("this target does not support %lu alternative machine codes"),
01769                    use_alt_mach_code);
01770          if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
01771            {
01772              non_fatal (_("treating that number as an absolute e_machine value instead"));
01773              elf_elfheader (obfd)->e_machine = use_alt_mach_code;
01774            }
01775          else
01776            non_fatal (_("ignoring the alternative value"));
01777        }
01778     }
01779 
01780   return TRUE;
01781 }
01782 
01783 /* Read each archive element in turn from IBFD, copy the
01784    contents to temp file, and keep the temp file handle.
01785    If 'force_output_target' is TRUE then make sure that
01786    all elements in the new archive are of the type
01787    'output_target'.  */
01788 
01789 static void
01790 copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
01791              bfd_boolean force_output_target)
01792 {
01793   struct name_list
01794     {
01795       struct name_list *next;
01796       const char *name;
01797       bfd *obfd;
01798     } *list, *l;
01799   bfd **ptr = &obfd->archive_head;
01800   bfd *this_element;
01801   char * dir;
01802 
01803   /* Make a temp directory to hold the contents.  */
01804   dir = make_tempdir (bfd_get_filename (obfd));
01805   if (dir == NULL)
01806       fatal (_("cannot create tempdir for archive copying (error: %s)"),
01807           strerror (errno));
01808 
01809   obfd->has_armap = ibfd->has_armap;
01810 
01811   list = NULL;
01812 
01813   this_element = bfd_openr_next_archived_file (ibfd, NULL);
01814 
01815   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
01816     RETURN_NONFATAL (bfd_get_filename (obfd));
01817 
01818   while (!status && this_element != NULL)
01819     {
01820       char *output_name;
01821       bfd *output_bfd;
01822       bfd *last_element;
01823       struct stat buf;
01824       int stat_status = 0;
01825       bfd_boolean delete = TRUE;
01826 
01827       /* Create an output file for this member.  */
01828       output_name = concat (dir, "/",
01829                          bfd_get_filename (this_element), (char *) 0);
01830 
01831       /* If the file already exists, make another temp dir.  */
01832       if (stat (output_name, &buf) >= 0)
01833        {
01834          output_name = make_tempdir (output_name);
01835          if (output_name == NULL)
01836            fatal (_("cannot create tempdir for archive copying (error: %s)"),
01837                  strerror (errno));
01838 
01839          l = xmalloc (sizeof (struct name_list));
01840          l->name = output_name;
01841          l->next = list;
01842          l->obfd = NULL;
01843          list = l;
01844          output_name = concat (output_name, "/",
01845                             bfd_get_filename (this_element), (char *) 0);
01846        }
01847 
01848       if (preserve_dates)
01849        {
01850          stat_status = bfd_stat_arch_elt (this_element, &buf);
01851 
01852          if (stat_status != 0)
01853            non_fatal (_("internal stat error on %s"),
01854                      bfd_get_filename (this_element));
01855        }
01856 
01857       l = xmalloc (sizeof (struct name_list));
01858       l->name = output_name;
01859       l->next = list;
01860       l->obfd = NULL;
01861       list = l;
01862 
01863       if (bfd_check_format (this_element, bfd_object))
01864        {
01865          /* PR binutils/3110: Cope with archives
01866             containing multiple target types.  */
01867          if (force_output_target)
01868            output_bfd = bfd_openw (output_name, output_target);
01869          else
01870            output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
01871 
01872          if (output_bfd == NULL)
01873            RETURN_NONFATAL (output_name);
01874 
01875          delete = ! copy_object (this_element, output_bfd);
01876 
01877          if (! delete
01878              || bfd_get_arch (this_element) != bfd_arch_unknown)
01879            {
01880              if (!bfd_close (output_bfd))
01881               {
01882                 bfd_nonfatal (bfd_get_filename (output_bfd));
01883                 /* Error in new object file. Don't change archive.  */
01884                 status = 1;
01885               }
01886            }
01887          else
01888            goto copy_unknown_element;
01889        }
01890       else
01891        {
01892          non_fatal (_("Unable to recognise the format of the input file `%s'"),
01893                    bfd_get_archive_filename (this_element));
01894 
01895          output_bfd = bfd_openw (output_name, output_target);
01896 copy_unknown_element:
01897          delete = !copy_unknown_object (this_element, output_bfd);
01898          if (!bfd_close_all_done (output_bfd))
01899            {
01900              bfd_nonfatal (bfd_get_filename (output_bfd));
01901              /* Error in new object file. Don't change archive.  */
01902              status = 1;
01903            }
01904        }
01905 
01906       if (delete)
01907        {
01908          unlink (output_name);
01909          status = 1;
01910        }
01911       else
01912        {
01913          if (preserve_dates && stat_status == 0)
01914            set_times (output_name, &buf);
01915 
01916          /* Open the newly output file and attach to our list.  */
01917          output_bfd = bfd_openr (output_name, output_target);
01918 
01919          l->obfd = output_bfd;
01920 
01921          *ptr = output_bfd;
01922          ptr = &output_bfd->next;
01923 
01924          last_element = this_element;
01925 
01926          this_element = bfd_openr_next_archived_file (ibfd, last_element);
01927 
01928          bfd_close (last_element);
01929        }
01930     }
01931   *ptr = NULL;
01932 
01933   if (!bfd_close (obfd))
01934     RETURN_NONFATAL (bfd_get_filename (obfd));
01935 
01936   if (!bfd_close (ibfd))
01937     RETURN_NONFATAL (bfd_get_filename (ibfd));
01938 
01939   /* Delete all the files that we opened.  */
01940   for (l = list; l != NULL; l = l->next)
01941     {
01942       if (l->obfd == NULL)
01943        rmdir (l->name);
01944       else
01945        {
01946          bfd_close (l->obfd);
01947          unlink (l->name);
01948        }
01949     }
01950   rmdir (dir);
01951 }
01952 
01953 /* The top-level control.  */
01954 
01955 static void
01956 copy_file (const char *input_filename, const char *output_filename,
01957           const char *input_target,   const char *output_target)
01958 {
01959   bfd *ibfd;
01960   char **obj_matching;
01961   char **core_matching;
01962 
01963   if (get_file_size (input_filename) < 1)
01964     {
01965       status = 1;
01966       return;
01967     }
01968 
01969   /* To allow us to do "strip *" without dying on the first
01970      non-object file, failures are nonfatal.  */
01971   ibfd = bfd_openr (input_filename, input_target);
01972   if (ibfd == NULL)
01973     RETURN_NONFATAL (input_filename);
01974 
01975   if (bfd_check_format (ibfd, bfd_archive))
01976     {
01977       bfd_boolean force_output_target;
01978       bfd *obfd;
01979 
01980       /* bfd_get_target does not return the correct value until
01981          bfd_check_format succeeds.  */
01982       if (output_target == NULL)
01983        {
01984          output_target = bfd_get_target (ibfd);
01985          force_output_target = FALSE;
01986        }
01987       else
01988        force_output_target = TRUE;
01989 
01990       obfd = bfd_openw (output_filename, output_target);
01991       if (obfd == NULL)
01992        RETURN_NONFATAL (output_filename);
01993 
01994       copy_archive (ibfd, obfd, output_target, force_output_target);
01995     }
01996   else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
01997     {
01998       bfd *obfd;
01999     do_copy:
02000 
02001       /* bfd_get_target does not return the correct value until
02002          bfd_check_format succeeds.  */
02003       if (output_target == NULL)
02004        output_target = bfd_get_target (ibfd);
02005 
02006       obfd = bfd_openw (output_filename, output_target);
02007       if (obfd == NULL)
02008        RETURN_NONFATAL (output_filename);
02009 
02010       if (! copy_object (ibfd, obfd))
02011        status = 1;
02012 
02013       if (!bfd_close (obfd))
02014        RETURN_NONFATAL (output_filename);
02015 
02016       if (!bfd_close (ibfd))
02017        RETURN_NONFATAL (input_filename);
02018 
02019     }
02020   else
02021     {
02022       bfd_error_type obj_error = bfd_get_error ();
02023       bfd_error_type core_error;
02024 
02025       if (bfd_check_format_matches (ibfd, bfd_core, &core_matching))
02026        {
02027          /* This probably can't happen..  */
02028          if (obj_error == bfd_error_file_ambiguously_recognized)
02029            free (obj_matching);
02030          goto do_copy;
02031        }
02032 
02033       core_error = bfd_get_error ();
02034       /* Report the object error in preference to the core error.  */
02035       if (obj_error != core_error)
02036        bfd_set_error (obj_error);
02037 
02038       bfd_nonfatal (input_filename);
02039 
02040       if (obj_error == bfd_error_file_ambiguously_recognized)
02041        {
02042          list_matching_formats (obj_matching);
02043          free (obj_matching);
02044        }
02045       if (core_error == bfd_error_file_ambiguously_recognized)
02046        {
02047          list_matching_formats (core_matching);
02048          free (core_matching);
02049        }
02050 
02051       status = 1;
02052     }
02053 }
02054 
02055 /* Add a name to the section renaming list.  */
02056 
02057 static void
02058 add_section_rename (const char * old_name, const char * new_name,
02059                   flagword flags)
02060 {
02061   section_rename * rename;
02062 
02063   /* Check for conflicts first.  */
02064   for (rename = section_rename_list; rename != NULL; rename = rename->next)
02065     if (strcmp (rename->old_name, old_name) == 0)
02066       {
02067        /* Silently ignore duplicate definitions.  */
02068        if (strcmp (rename->new_name, new_name) == 0
02069            && rename->flags == flags)
02070          return;
02071 
02072        fatal (_("Multiple renames of section %s"), old_name);
02073       }
02074 
02075   rename = xmalloc (sizeof (* rename));
02076 
02077   rename->old_name = old_name;
02078   rename->new_name = new_name;
02079   rename->flags    = flags;
02080   rename->next     = section_rename_list;
02081 
02082   section_rename_list = rename;
02083 }
02084 
02085 /* Check the section rename list for a new name of the input section
02086    ISECTION.  Return the new name if one is found.
02087    Also set RETURNED_FLAGS to the flags to be used for this section.  */
02088 
02089 static const char *
02090 find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
02091                    flagword * returned_flags)
02092 {
02093   const char * old_name = bfd_section_name (ibfd, isection);
02094   section_rename * rename;
02095 
02096   /* Default to using the flags of the input section.  */
02097   * returned_flags = bfd_get_section_flags (ibfd, isection);
02098 
02099   for (rename = section_rename_list; rename != NULL; rename = rename->next)
02100     if (strcmp (rename->old_name, old_name) == 0)
02101       {
02102        if (rename->flags != (flagword) -1)
02103          * returned_flags = rename->flags;
02104 
02105        return rename->new_name;
02106       }
02107 
02108   return old_name;
02109 }
02110 
02111 /* Once each of the sections is copied, we may still need to do some
02112    finalization work for private section headers.  Do that here.  */
02113 
02114 static void
02115 setup_bfd_headers (bfd *ibfd, bfd *obfd)
02116 {
02117   const char *err;
02118 
02119   /* Allow the BFD backend to copy any private data it understands
02120      from the input section to the output section.  */
02121   if (! bfd_copy_private_header_data (ibfd, obfd))
02122     {
02123       err = _("private header data");
02124       goto loser;
02125     }
02126 
02127   /* All went well.  */
02128   return;
02129 
02130 loser:
02131   non_fatal (_("%s: error in %s: %s"),
02132             bfd_get_filename (ibfd),
02133             err, bfd_errmsg (bfd_get_error ()));
02134   status = 1;
02135 }
02136 
02137 /* Create a section in OBFD with the same
02138    name and attributes as ISECTION in IBFD.  */
02139 
02140 static void
02141 setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
02142 {
02143   bfd *obfd = obfdarg;
02144   struct section_list *p;
02145   sec_ptr osection;
02146   bfd_size_type size;
02147   bfd_vma vma;
02148   bfd_vma lma;
02149   flagword flags;
02150   const char *err;
02151   const char * name;
02152   char *prefix = NULL;
02153 
02154   if (is_strip_section (ibfd, isection))
02155     return;
02156 
02157   p = find_section_list (bfd_section_name (ibfd, isection), FALSE);
02158   if (p != NULL)
02159     p->used = TRUE;
02160 
02161   /* Get the, possibly new, name of the output section.  */
02162   name = find_section_rename (ibfd, isection, & flags);
02163 
02164   /* Prefix sections.  */
02165   if ((prefix_alloc_sections_string)
02166       && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
02167     prefix = prefix_alloc_sections_string;
02168   else if (prefix_sections_string)
02169     prefix = prefix_sections_string;
02170 
02171   if (prefix)
02172     {
02173       char *n;
02174 
02175       n = xmalloc (strlen (prefix) + strlen (name) + 1);
02176       strcpy (n, prefix);
02177       strcat (n, name);
02178       name = n;
02179     }
02180 
02181   if (p != NULL && p->set_flags)
02182     flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
02183   else if (strip_symbols == STRIP_NONDEBUG && (flags & SEC_ALLOC) != 0)
02184     flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
02185 
02186   osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
02187 
02188   if (osection == NULL)
02189     {
02190       err = _("making");
02191       goto loser;
02192     }
02193 
02194   if (strip_symbols == STRIP_NONDEBUG
02195       && obfd->xvec->flavour == bfd_target_elf_flavour
02196       && (flags & SEC_ALLOC) != 0
02197       && (p == NULL || !p->set_flags))
02198     elf_section_type (osection) = SHT_NOBITS;
02199 
02200   size = bfd_section_size (ibfd, isection);
02201   if (copy_byte >= 0)
02202     size = (size + interleave - 1) / interleave;
02203   else if (extract_symbol)
02204     size = 0;
02205   if (! bfd_set_section_size (obfd, osection, size))
02206     {
02207       err = _("size");
02208       goto loser;
02209     }
02210 
02211   vma = bfd_section_vma (ibfd, isection);
02212   if (p != NULL && p->change_vma == CHANGE_MODIFY)
02213     vma += p->vma_val;
02214   else if (p != NULL && p->change_vma == CHANGE_SET)
02215     vma = p->vma_val;
02216   else
02217     vma += change_section_address;
02218 
02219   if (! bfd_set_section_vma (obfd, osection, extract_symbol ? 0 : vma))
02220     {
02221       err = _("vma");
02222       goto loser;
02223     }
02224 
02225   lma = isection->lma;
02226   if ((p != NULL) && p->change_lma != CHANGE_IGNORE)
02227     {
02228       if (p->change_lma == CHANGE_MODIFY)
02229        lma += p->lma_val;
02230       else if (p->change_lma == CHANGE_SET)
02231        lma = p->lma_val;
02232       else
02233        abort ();
02234     }
02235   else
02236     lma += change_section_address;
02237 
02238   osection->lma = extract_symbol ? 0 : lma;
02239 
02240   /* FIXME: This is probably not enough.  If we change the LMA we
02241      may have to recompute the header for the file as well.  */
02242   if (!bfd_set_section_alignment (obfd,
02243                               osection,
02244                               bfd_section_alignment (ibfd, isection)))
02245     {
02246       err = _("alignment");
02247       goto loser;
02248     }
02249 
02250   /* Copy merge entity size.  */
02251   osection->entsize = isection->entsize;
02252 
02253   /* This used to be mangle_section; we do here to avoid using
02254      bfd_get_section_by_name since some formats allow multiple
02255      sections with the same name.  */
02256   isection->output_section = osection;
02257   isection->output_offset = extract_symbol ? vma : 0;
02258 
02259   /* Do not copy backend data if --extract-symbol is passed; anything
02260      that needs to look at the section contents will fail.  */
02261   if (extract_symbol)
02262     return;
02263 
02264   /* Allow the BFD backend to copy any private data it understands
02265      from the input section to the output section.  */
02266   if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
02267       && strip_symbols == STRIP_NONDEBUG)
02268     /* Do not copy the private data when creating an ELF format
02269        debug info file.  We do not want the program headers.  */
02270     ;
02271   else if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
02272     {
02273       err = _("private data");
02274       goto loser;
02275     }
02276   else if ((isection->flags & SEC_GROUP) != 0)
02277     {
02278       asymbol *gsym = group_signature (isection);
02279 
02280       if (gsym != NULL)
02281        gsym->flags |= BSF_KEEP;
02282     }
02283 
02284   /* All went well.  */
02285   return;
02286 
02287 loser:
02288   non_fatal (_("%s: section `%s': error in %s: %s"),
02289             bfd_get_filename (ibfd),
02290             bfd_section_name (ibfd, isection),
02291             err, bfd_errmsg (bfd_get_error ()));
02292   status = 1;
02293 }
02294 
02295 /* Copy the data of input section ISECTION of IBFD
02296    to an output section with the same name in OBFD.
02297    If stripping then don't copy any relocation info.  */
02298 
02299 static void
02300 copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
02301 {
02302   bfd *obfd = obfdarg;
02303   struct section_list *p;
02304   arelent **relpp;
02305   long relcount;
02306   sec_ptr osection;
02307   bfd_size_type size;
02308   long relsize;
02309   flagword flags;
02310 
02311   /* If we have already failed earlier on,
02312      do not keep on generating complaints now.  */
02313   if (status != 0)
02314     return;
02315 
02316   if (is_strip_section (ibfd, isection))
02317     return;
02318 
02319   flags = bfd_get_section_flags (ibfd, isection);
02320   if ((flags & SEC_GROUP) != 0)
02321     return;
02322 
02323   osection = isection->output_section;
02324   size = bfd_get_section_size (isection);
02325 
02326   if (size == 0 || osection == 0)
02327     return;
02328 
02329   p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
02330 
02331   /* Core files do not need to be relocated.  */
02332   if (bfd_get_format (obfd) == bfd_core)
02333     relsize = 0;
02334   else
02335     {
02336       relsize = bfd_get_reloc_upper_bound (ibfd, isection);
02337 
02338       if (relsize < 0)
02339        {
02340          /* Do not complain if the target does not support relocations.  */
02341          if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
02342            relsize = 0;
02343          else
02344            RETURN_NONFATAL (bfd_get_filename (ibfd));
02345        }
02346     }
02347 
02348   if (relsize == 0)
02349     bfd_set_reloc (obfd, osection, NULL, 0);
02350   else
02351     {
02352       relpp = xmalloc (relsize);
02353       relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
02354       if (relcount < 0)
02355        RETURN_NONFATAL (bfd_get_filename (ibfd));
02356 
02357       if (strip_symbols == STRIP_ALL)
02358        {
02359          /* Remove relocations which are not in
02360             keep_strip_specific_list.  */
02361          arelent **temp_relpp;
02362          long temp_relcount = 0;
02363          long i;
02364 
02365          temp_relpp = xmalloc (relsize);
02366          for (i = 0; i < relcount; i++)
02367            if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
02368                                  keep_specific_list))
02369              temp_relpp [temp_relcount++] = relpp [i];
02370          relcount = temp_relcount;
02371          free (relpp);
02372          relpp = temp_relpp;
02373        }
02374 
02375       bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
02376       if (relcount == 0)
02377        free (relpp);
02378     }
02379 
02380   if (extract_symbol)
02381     return;
02382 
02383   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
02384       && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
02385     {
02386       void *memhunk = xmalloc (size);
02387 
02388       if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
02389        RETURN_NONFATAL (bfd_get_filename (ibfd));
02390 
02391       if (copy_byte >= 0)
02392        {
02393          /* Keep only every `copy_byte'th byte in MEMHUNK.  */
02394          char *from = (char *) memhunk + copy_byte;
02395          char *to = memhunk;
02396          char *end = (char *) memhunk + size;
02397 
02398          for (; from < end; from += interleave)
02399            *to++ = *from;
02400 
02401          size = (size + interleave - 1 - copy_byte) / interleave;
02402          osection->lma /= interleave;
02403        }
02404 
02405       if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
02406        RETURN_NONFATAL (bfd_get_filename (obfd));
02407 
02408       free (memhunk);
02409     }
02410   else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
02411     {
02412       void *memhunk = xmalloc (size);
02413 
02414       /* We don't permit the user to turn off the SEC_HAS_CONTENTS
02415         flag--they can just remove the section entirely and add it
02416         back again.  However, we do permit them to turn on the
02417         SEC_HAS_CONTENTS flag, and take it to mean that the section
02418         contents should be zeroed out.  */
02419 
02420       memset (memhunk, 0, size);
02421       if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
02422        RETURN_NONFATAL (bfd_get_filename (obfd));
02423       free (memhunk);
02424     }
02425 }
02426 
02427 /* Get all the sections.  This is used when --gap-fill or --pad-to is
02428    used.  */
02429 
02430 static void
02431 get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
02432 {
02433   asection ***secppp = secppparg;
02434 
02435   **secppp = osection;
02436   ++(*secppp);
02437 }
02438 
02439 /* Sort sections by VMA.  This is called via qsort, and is used when
02440    --gap-fill or --pad-to is used.  We force non loadable or empty
02441    sections to the front, where they are easier to ignore.  */
02442 
02443 static int
02444 compare_section_lma (const void *arg1, const void *arg2)
02445 {
02446   const asection *const *sec1 = arg1;
02447   const asection *const *sec2 = arg2;
02448   flagword flags1, flags2;
02449 
02450   /* Sort non loadable sections to the front.  */
02451   flags1 = (*sec1)->flags;
02452   flags2 = (*sec2)->flags;
02453   if ((flags1 & SEC_HAS_CONTENTS) == 0
02454       || (flags1 & SEC_LOAD) == 0)
02455     {
02456       if ((flags2 & SEC_HAS_CONTENTS) != 0
02457          && (flags2 & SEC_LOAD) != 0)
02458        return -1;
02459     }
02460   else
02461     {
02462       if ((flags2 & SEC_HAS_CONTENTS) == 0
02463          || (flags2 & SEC_LOAD) == 0)
02464        return 1;
02465     }
02466 
02467   /* Sort sections by LMA.  */
02468   if ((*sec1)->lma > (*sec2)->lma)
02469     return 1;
02470   else if ((*sec1)->lma < (*sec2)->lma)
02471     return -1;
02472 
02473   /* Sort sections with the same LMA by size.  */
02474   if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2))
02475     return 1;
02476   else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2))
02477     return -1;
02478 
02479   return 0;
02480 }
02481 
02482 /* Mark all the symbols which will be used in output relocations with
02483    the BSF_KEEP flag so that those symbols will not be stripped.
02484 
02485    Ignore relocations which will not appear in the output file.  */
02486 
02487 static void
02488 mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
02489 {
02490   asymbol **symbols = symbolsarg;
02491   long relsize;
02492   arelent **relpp;
02493   long relcount, i;
02494 
02495   /* Ignore an input section with no corresponding output section.  */
02496   if (isection->output_section == NULL)
02497     return;
02498 
02499   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
02500   if (relsize < 0)
02501     {
02502       /* Do not complain if the target does not support relocations.  */
02503       if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
02504        return;
02505       bfd_fatal (bfd_get_filename (ibfd));
02506     }
02507 
02508   if (relsize == 0)
02509     return;
02510 
02511   relpp = xmalloc (relsize);
02512   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
02513   if (relcount < 0)
02514     bfd_fatal (bfd_get_filename (ibfd));
02515 
02516   /* Examine each symbol used in a relocation.  If it's not one of the
02517      special bfd section symbols, then mark it with BSF_KEEP.  */
02518   for (i = 0; i < relcount; i++)
02519     {
02520       if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
02521          && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
02522          && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
02523        (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
02524     }
02525 
02526   if (relpp != NULL)
02527     free (relpp);
02528 }
02529 
02530 /* Write out debugging information.  */
02531 
02532 static bfd_boolean
02533 write_debugging_info (bfd *obfd, void *dhandle,
02534                     long *symcountp ATTRIBUTE_UNUSED,
02535                     asymbol ***symppp ATTRIBUTE_UNUSED)
02536 {
02537   if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
02538     return write_ieee_debugging_info (obfd, dhandle);
02539 
02540   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
02541       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
02542     {
02543       bfd_byte *syms, *strings;
02544       bfd_size_type symsize, stringsize;
02545       asection *stabsec, *stabstrsec;
02546       flagword flags;
02547 
02548       if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
02549                                               &symsize, &strings,
02550                                               &stringsize))
02551        return FALSE;
02552 
02553       flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
02554       stabsec = bfd_make_section_with_flags (obfd, ".stab", flags);
02555       stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags);
02556       if (stabsec == NULL
02557          || stabstrsec == NULL
02558          || ! bfd_set_section_size (obfd, stabsec, symsize)
02559          || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
02560          || ! bfd_set_section_alignment (obfd, stabsec, 2)
02561          || ! bfd_set_section_alignment (obfd, stabstrsec, 0))
02562        {
02563          non_fatal (_("%s: can't create debugging section: %s"),
02564                    bfd_get_filename (obfd),
02565                    bfd_errmsg (bfd_get_error ()));
02566          return FALSE;
02567        }
02568 
02569       /* We can get away with setting the section contents now because
02570          the next thing the caller is going to do is copy over the
02571          real sections.  We may someday have to split the contents
02572          setting out of this function.  */
02573       if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
02574          || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
02575                                     stringsize))
02576        {
02577          non_fatal (_("%s: can't set debugging section contents: %s"),
02578                    bfd_get_filename (obfd),
02579                    bfd_errmsg (bfd_get_error ()));
02580          return FALSE;
02581        }
02582 
02583       return TRUE;
02584     }
02585 
02586   non_fatal (_("%s: don't know how to write debugging information for %s"),
02587             bfd_get_filename (obfd), bfd_get_target (obfd));
02588   return FALSE;
02589 }
02590 
02591 static int
02592 strip_main (int argc, char *argv[])
02593 {
02594   char *input_target = NULL;
02595   char *output_target = NULL;
02596   bfd_boolean show_version = FALSE;
02597   bfd_boolean formats_info = FALSE;
02598   int c;
02599   int i;
02600   struct section_list *p;
02601   char *output_file = NULL;
02602 
02603   while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw",
02604                         strip_options, (int *) 0)) != EOF)
02605     {
02606       switch (c)
02607        {
02608        case 'I':
02609          input_target = optarg;
02610          break;
02611        case 'O':
02612          output_target = optarg;
02613          break;
02614        case 'F':
02615          input_target = output_target = optarg;
02616          break;
02617        case 'R':
02618          p = find_section_list (optarg, TRUE);
02619          p->remove = TRUE;
02620          sections_removed = TRUE;
02621          break;
02622        case 's':
02623          strip_symbols = STRIP_ALL;
02624          break;
02625        case 'S':
02626        case 'g':
02627        case 'd':     /* Historic BSD alias for -g.  Used by early NetBSD.  */
02628          strip_symbols = STRIP_DEBUG;
02629          break;
02630        case OPTION_STRIP_UNNEEDED:
02631          strip_symbols = STRIP_UNNEEDED;
02632          break;
02633        case 'K':
02634          add_specific_symbol (optarg, &keep_specific_list);
02635          break;
02636        case 'N':
02637          add_specific_symbol (optarg, &strip_specific_list);
02638          break;
02639        case 'o':
02640          output_file = optarg;
02641          break;
02642        case 'p':
02643          preserve_dates = TRUE;
02644          break;
02645        case 'x':
02646          discard_locals = LOCALS_ALL;
02647          break;
02648        case 'X':
02649          discard_locals = LOCALS_START_L;
02650          break;
02651        case 'v':
02652          verbose = TRUE;
02653          break;
02654        case 'V':
02655          show_version = TRUE;
02656          break;
02657        case OPTION_FORMATS_INFO:
02658          formats_info = TRUE;
02659          break;
02660        case OPTION_ONLY_KEEP_DEBUG:
02661          strip_symbols = STRIP_NONDEBUG;
02662          break;
02663        case OPTION_KEEP_FILE_SYMBOLS:
02664          keep_file_symbols = 1;
02665          break;
02666        case 0:
02667          /* We've been given a long option.  */
02668          break;
02669        case 'w':
02670          wildcard = TRUE;
02671          break;
02672        case 'H':
02673        case 'h':
02674          strip_usage (stdout, 0);
02675        default:
02676          strip_usage (stderr, 1);
02677        }
02678     }
02679 
02680   if (formats_info)
02681     {
02682       display_info ();
02683       return 0;
02684     }
02685  
02686   if (show_version)
02687     print_version ("strip");
02688 
02689   /* Default is to strip all symbols.  */
02690   if (strip_symbols == STRIP_UNDEF
02691       && discard_locals == LOCALS_UNDEF
02692       && strip_specific_list == NULL)
02693     strip_symbols = STRIP_ALL;
02694 
02695   if (output_target == NULL)
02696     output_target = input_target;
02697 
02698   i = optind;
02699   if (i == argc
02700       || (output_file != NULL && (i + 1) < argc))
02701     strip_usage (stderr, 1);
02702 
02703   for (; i < argc; i++)
02704     {
02705       int hold_status = status;
02706       struct stat statbuf;
02707       char *tmpname;
02708 
02709       if (get_file_size (argv[i]) < 1)
02710        {
02711          status = 1;
02712          continue;
02713        }
02714 
02715       if (preserve_dates)
02716        /* No need to check the return value of stat().
02717           It has already been checked in get_file_size().  */
02718        stat (argv[i], &statbuf);
02719 
02720       if (output_file != NULL)
02721        tmpname = output_file;
02722       else
02723        tmpname = make_tempname (argv[i]);
02724 
02725       if (tmpname == NULL)
02726        {
02727          non_fatal (_("could not create temporary file to hold stripped copy of '%s'"),
02728                    argv[i]);
02729          status = 1;
02730          continue;
02731        }
02732 
02733       status = 0;
02734       copy_file (argv[i], tmpname, input_target, output_target);
02735       if (status == 0)
02736        {
02737          if (preserve_dates)
02738            set_times (tmpname, &statbuf);
02739          if (output_file == NULL)
02740            smart_rename (tmpname, argv[i], preserve_dates);
02741          status = hold_status;
02742        }
02743       else
02744        unlink_if_ordinary (tmpname);
02745       if (output_file == NULL)
02746        free (tmpname);
02747     }
02748 
02749   return status;
02750 }
02751 
02752 static int
02753 copy_main (int argc, char *argv[])
02754 {
02755   char * binary_architecture = NULL;
02756   char *input_filename = NULL;
02757   char *output_filename = NULL;
02758   char *input_target = NULL;
02759   char *output_target = NULL;
02760   bfd_boolean show_version = FALSE;
02761   bfd_boolean change_warn = TRUE;
02762   bfd_boolean formats_info = FALSE;
02763   int c;
02764   struct section_list *p;
02765   struct stat statbuf;
02766 
02767   while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w",
02768                         copy_options, (int *) 0)) != EOF)
02769     {
02770       switch (c)
02771        {
02772        case 'b':
02773          copy_byte = atoi (optarg);
02774          if (copy_byte < 0)
02775            fatal (_("byte number must be non-negative"));
02776          break;
02777 
02778        case 'B':
02779          binary_architecture = optarg;
02780          break;
02781 
02782        case 'i':
02783          interleave = atoi (optarg);
02784          if (interleave < 1)
02785            fatal (_("interleave must be positive"));
02786          break;
02787 
02788        case 'I':
02789        case 's':            /* "source" - 'I' is preferred */
02790          input_target = optarg;
02791          break;
02792 
02793        case 'O':
02794        case 'd':            /* "destination" - 'O' is preferred */
02795          output_target = optarg;
02796          break;
02797 
02798        case 'F':
02799          input_target = output_target = optarg;
02800          break;
02801 
02802        case 'j':
02803          p = find_section_list (optarg, TRUE);
02804          if (p->remove)
02805            fatal (_("%s both copied and removed"), optarg);
02806          p->copy = TRUE;
02807          sections_copied = TRUE;
02808          break;
02809 
02810        case 'R':
02811          p = find_section_list (optarg, TRUE);
02812          if (p->copy)
02813            fatal (_("%s both copied and removed"), optarg);
02814          p->remove = TRUE;
02815          sections_removed = TRUE;
02816          break;
02817 
02818        case 'S':
02819          strip_symbols = STRIP_ALL;
02820          break;
02821 
02822        case 'g':
02823          strip_symbols = STRIP_DEBUG;
02824          break;
02825 
02826        case OPTION_STRIP_UNNEEDED:
02827          strip_symbols = STRIP_UNNEEDED;
02828          break;
02829 
02830        case OPTION_ONLY_KEEP_DEBUG:
02831          strip_symbols = STRIP_NONDEBUG;
02832          break;
02833 
02834        case OPTION_KEEP_FILE_SYMBOLS:
02835          keep_file_symbols = 1;
02836          break;
02837 
02838        case OPTION_ADD_GNU_DEBUGLINK:
02839          gnu_debuglink_filename = optarg;
02840          break;
02841 
02842        case 'K':
02843          add_specific_symbol (optarg, &keep_specific_list);
02844          break;
02845 
02846        case 'N':
02847          add_specific_symbol (optarg, &strip_specific_list);
02848          break;
02849 
02850        case OPTION_STRIP_UNNEEDED_SYMBOL:
02851          add_specific_symbol (optarg, &strip_unneeded_list);
02852          break;
02853 
02854        case 'L':
02855          add_specific_symbol (optarg, &localize_specific_list);
02856          break;
02857 
02858        case OPTION_GLOBALIZE_SYMBOL:
02859          add_specific_symbol (optarg, &globalize_specific_list);
02860          break;
02861 
02862        case 'G':
02863          add_specific_symbol (optarg, &keepglobal_specific_list);
02864          break;
02865 
02866        case 'W':
02867          add_specific_symbol (optarg, &weaken_specific_list);
02868          break;
02869 
02870        case 'p':
02871          preserve_dates = TRUE;
02872          break;
02873 
02874        case 'w':
02875          wildcard = TRUE;
02876          break;
02877 
02878        case 'x':
02879          discard_locals = LOCALS_ALL;
02880          break;
02881 
02882        case 'X':
02883          discard_locals = LOCALS_START_L;
02884          break;
02885 
02886        case 'v':
02887          verbose = TRUE;
02888          break;
02889 
02890        case 'V':
02891          show_version = TRUE;
02892          break;
02893 
02894        case OPTION_FORMATS_INFO:
02895          formats_info = TRUE;
02896          break;
02897 
02898        case OPTION_WEAKEN:
02899          weaken = TRUE;
02900          break;
02901 
02902        case OPTION_ADD_SECTION:
02903          {
02904            const char *s;
02905            off_t size;
02906            struct section_add *pa;
02907            int len;
02908            char *name;
02909            FILE *f;
02910 
02911            s = strchr (optarg, '=');
02912 
02913            if (s == NULL)
02914              fatal (_("bad format for %s"), "--add-section");
02915 
02916            size = get_file_size (s + 1);
02917            if (size < 1)
02918              {
02919               status = 1;
02920               break;
02921              }
02922 
02923            pa = xmalloc (sizeof (struct section_add));
02924 
02925            len = s - optarg;
02926            name = xmalloc (len + 1);
02927            strncpy (name, optarg, len);
02928            name[len] = '\0';
02929            pa->name = name;
02930 
02931            pa->filename = s + 1;
02932            pa->size = size;
02933            pa->contents = xmalloc (size);
02934 
02935            f = fopen (pa->filename, FOPEN_RB);
02936 
02937            if (f == NULL)
02938              fatal (_("cannot open: %s: %s"),
02939                    pa->filename, strerror (errno));
02940 
02941            if (fread (pa->contents, 1, pa->size, f) == 0
02942               || ferror (f))
02943              fatal (_("%s: fread failed"), pa->filename);
02944 
02945            fclose (f);
02946 
02947            pa->next = add_sections;
02948            add_sections = pa;
02949          }
02950          break;
02951 
02952        case OPTION_CHANGE_START:
02953          change_start = parse_vma (optarg, "--change-start");
02954          break;
02955 
02956        case OPTION_CHANGE_SECTION_ADDRESS:
02957        case OPTION_CHANGE_SECTION_LMA:
02958        case OPTION_CHANGE_SECTION_VMA:
02959          {
02960            const char *s;
02961            int len;
02962            char *name;
02963            char *option = NULL;
02964            bfd_vma val;
02965            enum change_action what = CHANGE_IGNORE;
02966 
02967            switch (c)
02968              {
02969              case OPTION_CHANGE_SECTION_ADDRESS:
02970               option = "--change-section-address";
02971               break;
02972              case OPTION_CHANGE_SECTION_LMA:
02973               option = "--change-section-lma";
02974               break;
02975              case OPTION_CHANGE_SECTION_VMA:
02976               option = "--change-section-vma";
02977               break;
02978              }
02979 
02980            s = strchr (optarg, '=');
02981            if (s == NULL)
02982              {
02983               s = strchr (optarg, '+');
02984               if (s == NULL)
02985                 {
02986                   s = strchr (optarg, '-');
02987                   if (s == NULL)
02988                     fatal (_("bad format for %s"), option);
02989                 }
02990              }
02991 
02992            len = s - optarg;
02993            name = xmalloc (len + 1);
02994            strncpy (name, optarg, len);
02995            name[len] = '\0';
02996 
02997            p = find_section_list (name, TRUE);
02998 
02999            val = parse_vma (s + 1, option);
03000 
03001            switch (*s)
03002              {
03003              case '=': what = CHANGE_SET; break;
03004              case '-': val  = - val; /* Drop through.  */
03005              case '+': what = CHANGE_MODIFY; break;
03006              }
03007 
03008            switch (c)
03009              {
03010              case OPTION_CHANGE_SECTION_ADDRESS:
03011               p->change_vma = what;
03012               p->vma_val    = val;
03013               /* Drop through.  */
03014 
03015              case OPTION_CHANGE_SECTION_LMA:
03016               p->change_lma = what;
03017               p->lma_val    = val;
03018               break;
03019 
03020              case OPTION_CHANGE_SECTION_VMA:
03021               p->change_vma = what;
03022               p->vma_val    = val;
03023               break;
03024              }
03025          }
03026          break;
03027 
03028        case OPTION_CHANGE_ADDRESSES:
03029          change_section_address = parse_vma (optarg, "--change-addresses");
03030          change_start = change_section_address;
03031          break;
03032 
03033        case OPTION_CHANGE_WARNINGS:
03034          change_warn = TRUE;
03035          break;
03036 
03037        case OPTION_CHANGE_LEADING_CHAR:
03038          change_leading_char = TRUE;
03039          break;
03040 
03041        case OPTION_DEBUGGING:
03042          convert_debugging = TRUE;
03043          break;
03044 
03045        case OPTION_GAP_FILL:
03046          {
03047            bfd_vma gap_fill_vma;
03048 
03049            gap_fill_vma = parse_vma (optarg, "--gap-fill");
03050            gap_fill = (bfd_byte) gap_fill_vma;
03051            if ((bfd_vma) gap_fill != gap_fill_vma)
03052              {
03053               char buff[20];
03054 
03055               sprintf_vma (buff, gap_fill_vma);
03056 
03057               non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
03058                         buff, gap_fill);
03059              }
03060            gap_fill_set = TRUE;
03061          }
03062          break;
03063 
03064        case OPTION_NO_CHANGE_WARNINGS:
03065          change_warn = FALSE;
03066          break;
03067 
03068        case OPTION_PAD_TO:
03069          pad_to = parse_vma (optarg, "--pad-to");
03070          pad_to_set = TRUE;
03071          break;
03072 
03073        case OPTION_REMOVE_LEADING_CHAR:
03074          remove_leading_char = TRUE;
03075          break;
03076 
03077        case OPTION_REDEFINE_SYM:
03078          {
03079            /* Push this redefinition onto redefine_symbol_list.  */
03080 
03081            int len;
03082            const char *s;
03083            const char *nextarg;
03084            char *source, *target;
03085 
03086            s = strchr (optarg, '=');
03087            if (s == NULL)
03088              fatal (_("bad format for %s"), "--redefine-sym");
03089 
03090            len = s - optarg;
03091            source = xmalloc (len + 1);
03092            strncpy (source, optarg, len);
03093            source[len] = '\0';
03094 
03095            nextarg = s + 1;
03096            len = strlen (nextarg);
03097            target = xmalloc (len + 1);
03098            strcpy (target, nextarg);
03099 
03100            redefine_list_append ("--redefine-sym", source, target);
03101 
03102            free (source);
03103            free (target);
03104          }
03105          break;
03106 
03107        case OPTION_REDEFINE_SYMS:
03108          add_redefine_syms_file (optarg);
03109          break;
03110 
03111        case OPTION_SET_SECTION_FLAGS:
03112          {
03113            const char *s;
03114            int len;
03115            char *name;
03116 
03117            s = strchr (optarg, '=');
03118            if (s == NULL)
03119              fatal (_("bad format for %s"), "--set-section-flags");
03120 
03121            len = s - optarg;
03122            name = xmalloc (len + 1);
03123            strncpy (name, optarg, len);
03124            name[len] = '\0';
03125 
03126            p = find_section_list (name, TRUE);
03127 
03128            p->set_flags = TRUE;
03129            p->flags = parse_flags (s + 1);
03130          }
03131          break;
03132 
03133        case OPTION_RENAME_SECTION:
03134          {
03135            flagword flags;
03136            const char *eq, *fl;
03137            char *old_name;
03138            char *new_name;
03139            unsigned int len;
03140 
03141            eq = strchr (optarg, '=');
03142            if (eq == NULL)
03143              fatal (_("bad format for %s"), "--rename-section");
03144 
03145            len = eq - optarg;
03146            if (len == 0)
03147              fatal (_("bad format for %s"), "--rename-section");
03148 
03149            old_name = xmalloc (len + 1);
03150            strncpy (old_name, optarg, len);
03151            old_name[len] = 0;
03152 
03153            eq++;
03154            fl = strchr (eq, ',');
03155            if (fl)
03156              {
03157               flags = parse_flags (fl + 1);
03158               len = fl - eq;
03159              }
03160            else
03161              {
03162               flags = -1;
03163               len = strlen (eq);
03164              }
03165 
03166            if (len == 0)
03167              fatal (_("bad format for %s"), "--rename-section");
03168 
03169            new_name = xmalloc (len + 1);
03170            strncpy (new_name, eq, len);
03171            new_name[len] = 0;
03172 
03173            add_section_rename (old_name, new_name, flags);
03174          }
03175          break;
03176 
03177        case OPTION_SET_START:
03178          set_start = parse_vma (optarg, "--set-start");
03179          set_start_set = TRUE;
03180          break;
03181 
03182        case OPTION_SREC_LEN:
03183          Chunk = parse_vma (optarg, "--srec-len");
03184          break;
03185 
03186        case OPTION_SREC_FORCES3:
03187          S3Forced = TRUE;
03188          break;
03189 
03190        case OPTION_STRIP_SYMBOLS:
03191          add_specific_symbols (optarg, &strip_specific_list);
03192          break;
03193 
03194        case OPTION_STRIP_UNNEEDED_SYMBOLS:
03195          add_specific_symbols (optarg, &strip_unneeded_list);
03196          break;
03197 
03198        case OPTION_KEEP_SYMBOLS:
03199          add_specific_symbols (optarg, &keep_specific_list);
03200          break;
03201 
03202        case OPTION_LOCALIZE_HIDDEN:
03203          localize_hidden = TRUE;
03204          break;
03205 
03206        case OPTION_LOCALIZE_SYMBOLS:
03207          add_specific_symbols (optarg, &localize_specific_list);
03208          break;
03209 
03210        case OPTION_GLOBALIZE_SYMBOLS:
03211          add_specific_symbols (optarg, &globalize_specific_list);
03212          break;
03213 
03214        case OPTION_KEEPGLOBAL_SYMBOLS:
03215          add_specific_symbols (optarg, &keepglobal_specific_list);
03216          break;
03217 
03218        case OPTION_WEAKEN_SYMBOLS:
03219          add_specific_symbols (optarg, &weaken_specific_list);
03220          break;
03221 
03222        case OPTION_ALT_MACH_CODE:
03223          use_alt_mach_code = strtoul (optarg, NULL, 0);
03224          if (use_alt_mach_code == 0)
03225            fatal (_("unable to parse alternative machine code"));
03226          break;
03227 
03228        case OPTION_PREFIX_SYMBOLS:
03229          prefix_symbols_string = optarg;
03230          break;
03231 
03232        case OPTION_PREFIX_SECTIONS:
03233          prefix_sections_string = optarg;
03234          break;
03235 
03236        case OPTION_PREFIX_ALLOC_SECTIONS:
03237          prefix_alloc_sections_string = optarg;
03238          break;
03239 
03240        case OPTION_READONLY_TEXT:
03241          bfd_flags_to_set |= WP_TEXT;
03242          bfd_flags_to_clear &= ~WP_TEXT;
03243          break;
03244 
03245        case OPTION_WRITABLE_TEXT:
03246          bfd_flags_to_clear |= WP_TEXT;
03247          bfd_flags_to_set &= ~WP_TEXT;
03248          break;
03249 
03250        case OPTION_PURE:
03251          bfd_flags_to_set |= D_PAGED;
03252          bfd_flags_to_clear &= ~D_PAGED;
03253          break;
03254 
03255        case OPTION_IMPURE:
03256          bfd_flags_to_clear |= D_PAGED;
03257          bfd_flags_to_set &= ~D_PAGED;
03258          break;
03259 
03260        case OPTION_EXTRACT_SYMBOL:
03261          extract_symbol = TRUE;
03262          break;
03263 
03264        case 0:
03265          /* We've been given a long option.  */
03266          break;
03267 
03268        case 'H':
03269        case 'h':
03270          copy_usage (stdout, 0);
03271 
03272        default:
03273          copy_usage (stderr, 1);
03274        }
03275     }
03276 
03277   if (formats_info)
03278     {
03279       display_info ();
03280       return 0;
03281     }
03282  
03283   if (show_version)
03284     print_version ("objcopy");
03285 
03286   if (copy_byte >= interleave)
03287     fatal (_("byte number must be less than interleave"));
03288 
03289   if (optind == argc || optind + 2 < argc)
03290     copy_usage (stderr, 1);
03291 
03292   input_filename = argv[optind];
03293   if (optind + 1 < argc)
03294     output_filename = argv[optind + 1];
03295 
03296   /* Default is to strip no symbols.  */
03297   if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
03298     strip_symbols = STRIP_NONE;
03299 
03300   if (output_target == NULL)
03301     output_target = input_target;
03302 
03303   if (binary_architecture != NULL)
03304     {
03305       if (input_target && strcmp (input_target, "binary") == 0)
03306        {
03307          const bfd_arch_info_type * temp_arch_info;
03308 
03309          temp_arch_info = bfd_scan_arch (binary_architecture);
03310 
03311          if (temp_arch_info != NULL)
03312            {
03313              bfd_external_binary_architecture = temp_arch_info->arch;
03314              bfd_external_machine             = temp_arch_info->mach;
03315            }
03316          else
03317            fatal (_("architecture %s unknown"), binary_architecture);
03318        }
03319       else
03320        {
03321          non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
03322          non_fatal (_(" Argument %s ignored"), binary_architecture);
03323        }
03324     }
03325 
03326   if (preserve_dates)
03327     if (stat (input_filename, & statbuf) < 0)
03328       fatal (_("warning: could not locate '%s'.  System error message: %s"),
03329             input_filename, strerror (errno));
03330 
03331   /* If there is no destination file, or the source and destination files
03332      are the same, then create a temp and rename the result into the input.  */
03333   if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
03334     {
03335       char *tmpname = make_tempname (input_filename);
03336 
03337       if (tmpname == NULL)
03338        fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
03339               input_filename, strerror (errno));
03340 
03341       copy_file (input_filename, tmpname, input_target, output_target);
03342       if (status == 0)
03343        {
03344          if (preserve_dates)
03345            set_times (tmpname, &statbuf);
03346          smart_rename (tmpname, input_filename, preserve_dates);
03347        }
03348       else
03349        unlink (tmpname);
03350     }
03351   else
03352     {
03353       copy_file (input_filename, output_filename, input_target, output_target);
03354 
03355       if (status == 0 && preserve_dates)
03356        set_times (output_filename, &statbuf);
03357       else if (status != 0)
03358        unlink_if_ordinary (output_filename);
03359     }
03360 
03361   if (change_warn)
03362     {
03363       for (p = change_sections; p != NULL; p = p->next)
03364        {
03365          if (! p->used)
03366            {
03367              if (p->change_vma != CHANGE_IGNORE)
03368               {
03369                 char buff [20];
03370 
03371                 sprintf_vma (buff, p->vma_val);
03372 
03373                 /* xgettext:c-format */
03374                 non_fatal (_("%s %s%c0x%s never used"),
03375                           "--change-section-vma",
03376                           p->name,
03377                           p->change_vma == CHANGE_SET ? '=' : '+',
03378                           buff);
03379               }
03380 
03381              if (p->change_lma != CHANGE_IGNORE)
03382               {
03383                 char buff [20];
03384 
03385                 sprintf_vma (buff, p->lma_val);
03386 
03387                 /* xgettext:c-format */
03388                 non_fatal (_("%s %s%c0x%s never used"),
03389                           "--change-section-lma",
03390                           p->name,
03391                           p->change_lma == CHANGE_SET ? '=' : '+',
03392                           buff);
03393               }
03394            }
03395        }
03396     }
03397 
03398   return 0;
03399 }
03400 
03401 int
03402 main (int argc, char *argv[])
03403 {
03404 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
03405   setlocale (LC_MESSAGES, "");
03406 #endif
03407 #if defined (HAVE_SETLOCALE)
03408   setlocale (LC_CTYPE, "");
03409 #endif
03410   bindtextdomain (PACKAGE, LOCALEDIR);
03411   textdomain (PACKAGE);
03412 
03413   program_name = argv[0];
03414   xmalloc_set_program_name (program_name);
03415 
03416   START_PROGRESS (program_name, 0);
03417 
03418   expandargv (&argc, &argv);
03419 
03420   strip_symbols = STRIP_UNDEF;
03421   discard_locals = LOCALS_UNDEF;
03422 
03423   bfd_init ();
03424   set_default_bfd_target ();
03425 
03426   if (is_strip < 0)
03427     {
03428       int i = strlen (program_name);
03429 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
03430       /* Drop the .exe suffix, if any.  */
03431       if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0)
03432        {
03433          i -= 4;
03434          program_name[i] = '\0';
03435        }
03436 #endif
03437       is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
03438     }
03439 
03440   if (is_strip)
03441     strip_main (argc, argv);
03442   else
03443     copy_main (argc, argv);
03444 
03445   END_PROGRESS (program_name);
03446 
03447   return status;
03448 }