xref: /openbsd-src/gnu/usr.bin/binutils-2.17/binutils/objcopy.c (revision d983f9a75cb7bf3ac4a8174836a2525232e37901)
13d8817e4Smiod /* objcopy.c -- copy object file from input to output, optionally massaging it.
23d8817e4Smiod    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
33d8817e4Smiod    2001, 2002, 2003, 2004, 2005, 2006
43d8817e4Smiod    Free Software Foundation, Inc.
53d8817e4Smiod 
63d8817e4Smiod    This file is part of GNU Binutils.
73d8817e4Smiod 
83d8817e4Smiod    This program is free software; you can redistribute it and/or modify
93d8817e4Smiod    it under the terms of the GNU General Public License as published by
103d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
113d8817e4Smiod    (at your option) any later version.
123d8817e4Smiod 
133d8817e4Smiod    This program is distributed in the hope that it will be useful,
143d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163d8817e4Smiod    GNU General Public License for more details.
173d8817e4Smiod 
183d8817e4Smiod    You should have received a copy of the GNU General Public License
193d8817e4Smiod    along with this program; if not, write to the Free Software
203d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
213d8817e4Smiod    02110-1301, USA.  */
223d8817e4Smiod 
233d8817e4Smiod #include "bfd.h"
243d8817e4Smiod #include "progress.h"
253d8817e4Smiod #include "bucomm.h"
263d8817e4Smiod #include "getopt.h"
273d8817e4Smiod #include "libiberty.h"
283d8817e4Smiod #include "budbg.h"
293d8817e4Smiod #include "filenames.h"
303d8817e4Smiod #include "fnmatch.h"
313d8817e4Smiod #include "elf-bfd.h"
323d8817e4Smiod #include <sys/stat.h>
333d8817e4Smiod #include "libbfd.h"
343d8817e4Smiod 
353d8817e4Smiod /* A list of symbols to explicitly strip out, or to keep.  A linked
363d8817e4Smiod    list is good enough for a small number from the command line, but
373d8817e4Smiod    this will slow things down a lot if many symbols are being
383d8817e4Smiod    deleted.  */
393d8817e4Smiod 
403d8817e4Smiod struct symlist
413d8817e4Smiod {
423d8817e4Smiod   const char *name;
433d8817e4Smiod   struct symlist *next;
443d8817e4Smiod };
453d8817e4Smiod 
463d8817e4Smiod /* A list to support redefine_sym.  */
473d8817e4Smiod struct redefine_node
483d8817e4Smiod {
493d8817e4Smiod   char *source;
503d8817e4Smiod   char *target;
513d8817e4Smiod   struct redefine_node *next;
523d8817e4Smiod };
533d8817e4Smiod 
543d8817e4Smiod typedef struct section_rename
553d8817e4Smiod {
563d8817e4Smiod   const char *            old_name;
573d8817e4Smiod   const char *            new_name;
583d8817e4Smiod   flagword                flags;
593d8817e4Smiod   struct section_rename * next;
603d8817e4Smiod }
613d8817e4Smiod section_rename;
623d8817e4Smiod 
633d8817e4Smiod /* List of sections to be renamed.  */
643d8817e4Smiod static section_rename *section_rename_list;
653d8817e4Smiod 
663d8817e4Smiod #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
673d8817e4Smiod 
683d8817e4Smiod static asymbol **isympp = NULL;	/* Input symbols.  */
693d8817e4Smiod static asymbol **osympp = NULL;	/* Output symbols that survive stripping.  */
703d8817e4Smiod 
713d8817e4Smiod /* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes.  */
723d8817e4Smiod static int copy_byte = -1;
733d8817e4Smiod static int interleave = 4;
743d8817e4Smiod 
753d8817e4Smiod static bfd_boolean verbose;		/* Print file and target names.  */
763d8817e4Smiod static bfd_boolean preserve_dates;	/* Preserve input file timestamp.  */
773d8817e4Smiod static int status = 0;		/* Exit status.  */
783d8817e4Smiod 
793d8817e4Smiod enum strip_action
803d8817e4Smiod   {
813d8817e4Smiod     STRIP_UNDEF,
823d8817e4Smiod     STRIP_NONE,			/* Don't strip.  */
833d8817e4Smiod     STRIP_DEBUG,		/* Strip all debugger symbols.  */
843d8817e4Smiod     STRIP_UNNEEDED,		/* Strip unnecessary symbols.  */
853d8817e4Smiod     STRIP_NONDEBUG,		/* Strip everything but debug info.  */
863d8817e4Smiod     STRIP_ALL			/* Strip all symbols.  */
873d8817e4Smiod   };
883d8817e4Smiod 
893d8817e4Smiod /* Which symbols to remove.  */
903d8817e4Smiod static enum strip_action strip_symbols;
913d8817e4Smiod 
923d8817e4Smiod enum locals_action
933d8817e4Smiod   {
943d8817e4Smiod     LOCALS_UNDEF,
953d8817e4Smiod     LOCALS_START_L,		/* Discard locals starting with L.  */
963d8817e4Smiod     LOCALS_ALL			/* Discard all locals.  */
973d8817e4Smiod   };
983d8817e4Smiod 
993d8817e4Smiod /* Which local symbols to remove.  Overrides STRIP_ALL.  */
1003d8817e4Smiod static enum locals_action discard_locals;
1013d8817e4Smiod 
1023d8817e4Smiod /* What kind of change to perform.  */
1033d8817e4Smiod enum change_action
1043d8817e4Smiod {
1053d8817e4Smiod   CHANGE_IGNORE,
1063d8817e4Smiod   CHANGE_MODIFY,
1073d8817e4Smiod   CHANGE_SET
1083d8817e4Smiod };
1093d8817e4Smiod 
1103d8817e4Smiod /* Structure used to hold lists of sections and actions to take.  */
1113d8817e4Smiod struct section_list
1123d8817e4Smiod {
1133d8817e4Smiod   struct section_list * next;	   /* Next section to change.  */
1143d8817e4Smiod   const char *		name;	   /* Section name.  */
1153d8817e4Smiod   bfd_boolean		used;	   /* Whether this entry was used.  */
1163d8817e4Smiod   bfd_boolean		remove;	   /* Whether to remove this section.  */
1173d8817e4Smiod   bfd_boolean		copy;	   /* Whether to copy this section.  */
1183d8817e4Smiod   enum change_action	change_vma;/* Whether to change or set VMA.  */
1193d8817e4Smiod   bfd_vma		vma_val;   /* Amount to change by or set to.  */
1203d8817e4Smiod   enum change_action	change_lma;/* Whether to change or set LMA.  */
1213d8817e4Smiod   bfd_vma		lma_val;   /* Amount to change by or set to.  */
1223d8817e4Smiod   bfd_boolean		set_flags; /* Whether to set the section flags.	 */
1233d8817e4Smiod   flagword		flags;	   /* What to set the section flags to.	 */
1243d8817e4Smiod };
1253d8817e4Smiod 
1263d8817e4Smiod static struct section_list *change_sections;
1273d8817e4Smiod 
1283d8817e4Smiod /* TRUE if some sections are to be removed.  */
1293d8817e4Smiod static bfd_boolean sections_removed;
1303d8817e4Smiod 
1313d8817e4Smiod /* TRUE if only some sections are to be copied.  */
1323d8817e4Smiod static bfd_boolean sections_copied;
1333d8817e4Smiod 
1343d8817e4Smiod /* Changes to the start address.  */
1353d8817e4Smiod static bfd_vma change_start = 0;
1363d8817e4Smiod static bfd_boolean set_start_set = FALSE;
1373d8817e4Smiod static bfd_vma set_start;
1383d8817e4Smiod 
1393d8817e4Smiod /* Changes to section addresses.  */
1403d8817e4Smiod static bfd_vma change_section_address = 0;
1413d8817e4Smiod 
1423d8817e4Smiod /* Filling gaps between sections.  */
1433d8817e4Smiod static bfd_boolean gap_fill_set = FALSE;
1443d8817e4Smiod static bfd_byte gap_fill = 0;
1453d8817e4Smiod 
1463d8817e4Smiod /* Pad to a given address.  */
1473d8817e4Smiod static bfd_boolean pad_to_set = FALSE;
1483d8817e4Smiod static bfd_vma pad_to;
1493d8817e4Smiod 
1503d8817e4Smiod /* Use alternative machine code?  */
1513d8817e4Smiod static unsigned long use_alt_mach_code = 0;
1523d8817e4Smiod 
1533d8817e4Smiod /* Output BFD flags user wants to set or clear */
1543d8817e4Smiod static flagword bfd_flags_to_set;
1553d8817e4Smiod static flagword bfd_flags_to_clear;
1563d8817e4Smiod 
1573d8817e4Smiod /* List of sections to add.  */
1583d8817e4Smiod struct section_add
1593d8817e4Smiod {
1603d8817e4Smiod   /* Next section to add.  */
1613d8817e4Smiod   struct section_add *next;
1623d8817e4Smiod   /* Name of section to add.  */
1633d8817e4Smiod   const char *name;
1643d8817e4Smiod   /* Name of file holding section contents.  */
1653d8817e4Smiod   const char *filename;
1663d8817e4Smiod   /* Size of file.  */
1673d8817e4Smiod   size_t size;
1683d8817e4Smiod   /* Contents of file.  */
1693d8817e4Smiod   bfd_byte *contents;
1703d8817e4Smiod   /* BFD section, after it has been added.  */
1713d8817e4Smiod   asection *section;
1723d8817e4Smiod };
1733d8817e4Smiod 
1743d8817e4Smiod /* List of sections to add to the output BFD.  */
1753d8817e4Smiod static struct section_add *add_sections;
1763d8817e4Smiod 
1773d8817e4Smiod /* If non-NULL the argument to --add-gnu-debuglink.
1783d8817e4Smiod    This should be the filename to store in the .gnu_debuglink section.  */
1793d8817e4Smiod static const char * gnu_debuglink_filename = NULL;
1803d8817e4Smiod 
1813d8817e4Smiod /* Whether to convert debugging information.  */
1823d8817e4Smiod static bfd_boolean convert_debugging = FALSE;
1833d8817e4Smiod 
1843d8817e4Smiod /* Whether to change the leading character in symbol names.  */
1853d8817e4Smiod static bfd_boolean change_leading_char = FALSE;
1863d8817e4Smiod 
1873d8817e4Smiod /* Whether to remove the leading character from global symbol names.  */
1883d8817e4Smiod static bfd_boolean remove_leading_char = FALSE;
1893d8817e4Smiod 
1903d8817e4Smiod /* Whether to permit wildcard in symbol comparison.  */
1913d8817e4Smiod static bfd_boolean wildcard = FALSE;
1923d8817e4Smiod 
193c065f989Skettenis /* True if --localize-hidden is in effect.  */
194c065f989Skettenis static bfd_boolean localize_hidden = FALSE;
195c065f989Skettenis 
1963d8817e4Smiod /* List of symbols to strip, keep, localize, keep-global, weaken,
1973d8817e4Smiod    or redefine.  */
1983d8817e4Smiod static struct symlist *strip_specific_list = NULL;
1993d8817e4Smiod static struct symlist *strip_unneeded_list = NULL;
2003d8817e4Smiod static struct symlist *keep_specific_list = NULL;
2013d8817e4Smiod static struct symlist *localize_specific_list = NULL;
2023d8817e4Smiod static struct symlist *globalize_specific_list = NULL;
2033d8817e4Smiod static struct symlist *keepglobal_specific_list = NULL;
2043d8817e4Smiod static struct symlist *weaken_specific_list = NULL;
2053d8817e4Smiod static struct redefine_node *redefine_sym_list = NULL;
2063d8817e4Smiod 
2073d8817e4Smiod /* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
2083d8817e4Smiod static bfd_boolean weaken = FALSE;
2093d8817e4Smiod 
2103d8817e4Smiod /* If this is TRUE, we retain BSF_FILE symbols.  */
2113d8817e4Smiod static bfd_boolean keep_file_symbols = FALSE;
2123d8817e4Smiod 
2133d8817e4Smiod /* Prefix symbols/sections.  */
2143d8817e4Smiod static char *prefix_symbols_string = 0;
2153d8817e4Smiod static char *prefix_sections_string = 0;
2163d8817e4Smiod static char *prefix_alloc_sections_string = 0;
2173d8817e4Smiod 
2183d8817e4Smiod /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
2193d8817e4Smiod enum command_line_switch
2203d8817e4Smiod   {
2213d8817e4Smiod     OPTION_ADD_SECTION=150,
2223d8817e4Smiod     OPTION_CHANGE_ADDRESSES,
2233d8817e4Smiod     OPTION_CHANGE_LEADING_CHAR,
2243d8817e4Smiod     OPTION_CHANGE_START,
2253d8817e4Smiod     OPTION_CHANGE_SECTION_ADDRESS,
2263d8817e4Smiod     OPTION_CHANGE_SECTION_LMA,
2273d8817e4Smiod     OPTION_CHANGE_SECTION_VMA,
2283d8817e4Smiod     OPTION_CHANGE_WARNINGS,
2293d8817e4Smiod     OPTION_DEBUGGING,
2303d8817e4Smiod     OPTION_GAP_FILL,
2313d8817e4Smiod     OPTION_NO_CHANGE_WARNINGS,
2323d8817e4Smiod     OPTION_PAD_TO,
2333d8817e4Smiod     OPTION_REMOVE_LEADING_CHAR,
2343d8817e4Smiod     OPTION_SET_SECTION_FLAGS,
2353d8817e4Smiod     OPTION_SET_START,
2363d8817e4Smiod     OPTION_STRIP_UNNEEDED,
2373d8817e4Smiod     OPTION_WEAKEN,
2383d8817e4Smiod     OPTION_REDEFINE_SYM,
2393d8817e4Smiod     OPTION_REDEFINE_SYMS,
2403d8817e4Smiod     OPTION_SREC_LEN,
2413d8817e4Smiod     OPTION_SREC_FORCES3,
2423d8817e4Smiod     OPTION_STRIP_SYMBOLS,
2433d8817e4Smiod     OPTION_STRIP_UNNEEDED_SYMBOL,
2443d8817e4Smiod     OPTION_STRIP_UNNEEDED_SYMBOLS,
2453d8817e4Smiod     OPTION_KEEP_SYMBOLS,
246c065f989Skettenis     OPTION_LOCALIZE_HIDDEN,
2473d8817e4Smiod     OPTION_LOCALIZE_SYMBOLS,
2483d8817e4Smiod     OPTION_GLOBALIZE_SYMBOL,
2493d8817e4Smiod     OPTION_GLOBALIZE_SYMBOLS,
2503d8817e4Smiod     OPTION_KEEPGLOBAL_SYMBOLS,
2513d8817e4Smiod     OPTION_WEAKEN_SYMBOLS,
2523d8817e4Smiod     OPTION_RENAME_SECTION,
2533d8817e4Smiod     OPTION_ALT_MACH_CODE,
2543d8817e4Smiod     OPTION_PREFIX_SYMBOLS,
2553d8817e4Smiod     OPTION_PREFIX_SECTIONS,
2563d8817e4Smiod     OPTION_PREFIX_ALLOC_SECTIONS,
2573d8817e4Smiod     OPTION_FORMATS_INFO,
2583d8817e4Smiod     OPTION_ADD_GNU_DEBUGLINK,
2593d8817e4Smiod     OPTION_ONLY_KEEP_DEBUG,
2603d8817e4Smiod     OPTION_KEEP_FILE_SYMBOLS,
2613d8817e4Smiod     OPTION_READONLY_TEXT,
2623d8817e4Smiod     OPTION_WRITABLE_TEXT,
2633d8817e4Smiod     OPTION_PURE,
2643d8817e4Smiod     OPTION_IMPURE
2653d8817e4Smiod   };
2663d8817e4Smiod 
2673d8817e4Smiod /* Options to handle if running as "strip".  */
2683d8817e4Smiod 
2693d8817e4Smiod static struct option strip_options[] =
2703d8817e4Smiod {
2713d8817e4Smiod   {"discard-all", no_argument, 0, 'x'},
2723d8817e4Smiod   {"discard-locals", no_argument, 0, 'X'},
2733d8817e4Smiod   {"format", required_argument, 0, 'F'}, /* Obsolete */
2743d8817e4Smiod   {"help", no_argument, 0, 'h'},
2753d8817e4Smiod   {"info", no_argument, 0, OPTION_FORMATS_INFO},
2763d8817e4Smiod   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
2773d8817e4Smiod   {"input-target", required_argument, 0, 'I'},
2783d8817e4Smiod   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
2793d8817e4Smiod   {"keep-symbol", required_argument, 0, 'K'},
2803d8817e4Smiod   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
2813d8817e4Smiod   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
2823d8817e4Smiod   {"output-target", required_argument, 0, 'O'},
2833d8817e4Smiod   {"output-file", required_argument, 0, 'o'},
2843d8817e4Smiod   {"preserve-dates", no_argument, 0, 'p'},
2853d8817e4Smiod   {"remove-section", required_argument, 0, 'R'},
2863d8817e4Smiod   {"strip-all", no_argument, 0, 's'},
2873d8817e4Smiod   {"strip-debug", no_argument, 0, 'S'},
2883d8817e4Smiod   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
2893d8817e4Smiod   {"strip-symbol", required_argument, 0, 'N'},
2903d8817e4Smiod   {"target", required_argument, 0, 'F'},
2913d8817e4Smiod   {"verbose", no_argument, 0, 'v'},
2923d8817e4Smiod   {"version", no_argument, 0, 'V'},
2933d8817e4Smiod   {"wildcard", no_argument, 0, 'w'},
2943d8817e4Smiod   {0, no_argument, 0, 0}
2953d8817e4Smiod };
2963d8817e4Smiod 
2973d8817e4Smiod /* Options to handle if running as "objcopy".  */
2983d8817e4Smiod 
2993d8817e4Smiod static struct option copy_options[] =
3003d8817e4Smiod {
3013d8817e4Smiod   {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
3023d8817e4Smiod   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
3033d8817e4Smiod   {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
3043d8817e4Smiod   {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
3053d8817e4Smiod   {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
3063d8817e4Smiod   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
3073d8817e4Smiod   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
3083d8817e4Smiod   {"binary-architecture", required_argument, 0, 'B'},
3093d8817e4Smiod   {"byte", required_argument, 0, 'b'},
3103d8817e4Smiod   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
3113d8817e4Smiod   {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
3123d8817e4Smiod   {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
3133d8817e4Smiod   {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
3143d8817e4Smiod   {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
3153d8817e4Smiod   {"change-start", required_argument, 0, OPTION_CHANGE_START},
3163d8817e4Smiod   {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
3173d8817e4Smiod   {"debugging", no_argument, 0, OPTION_DEBUGGING},
3183d8817e4Smiod   {"discard-all", no_argument, 0, 'x'},
3193d8817e4Smiod   {"discard-locals", no_argument, 0, 'X'},
3203d8817e4Smiod   {"format", required_argument, 0, 'F'}, /* Obsolete */
3213d8817e4Smiod   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
3223d8817e4Smiod   {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
3233d8817e4Smiod   {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
3243d8817e4Smiod   {"help", no_argument, 0, 'h'},
3253d8817e4Smiod   {"impure", no_argument, 0, OPTION_IMPURE},
3263d8817e4Smiod   {"info", no_argument, 0, OPTION_FORMATS_INFO},
3273d8817e4Smiod   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
3283d8817e4Smiod   {"input-target", required_argument, 0, 'I'},
3293d8817e4Smiod   {"interleave", required_argument, 0, 'i'},
3303d8817e4Smiod   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
3313d8817e4Smiod   {"keep-global-symbol", required_argument, 0, 'G'},
3323d8817e4Smiod   {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
3333d8817e4Smiod   {"keep-symbol", required_argument, 0, 'K'},
3343d8817e4Smiod   {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
335c065f989Skettenis   {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
3363d8817e4Smiod   {"localize-symbol", required_argument, 0, 'L'},
3373d8817e4Smiod   {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
3383d8817e4Smiod   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
3393d8817e4Smiod   {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
3403d8817e4Smiod   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
3413d8817e4Smiod   {"only-section", required_argument, 0, 'j'},
3423d8817e4Smiod   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
3433d8817e4Smiod   {"output-target", required_argument, 0, 'O'},
3443d8817e4Smiod   {"pad-to", required_argument, 0, OPTION_PAD_TO},
3453d8817e4Smiod   {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
3463d8817e4Smiod   {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
3473d8817e4Smiod   {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
3483d8817e4Smiod   {"preserve-dates", no_argument, 0, 'p'},
3493d8817e4Smiod   {"pure", no_argument, 0, OPTION_PURE},
3503d8817e4Smiod   {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
3513d8817e4Smiod   {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
3523d8817e4Smiod   {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
3533d8817e4Smiod   {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
3543d8817e4Smiod   {"remove-section", required_argument, 0, 'R'},
3553d8817e4Smiod   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
3563d8817e4Smiod   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
3573d8817e4Smiod   {"set-start", required_argument, 0, OPTION_SET_START},
3583d8817e4Smiod   {"srec-len", required_argument, 0, OPTION_SREC_LEN},
3593d8817e4Smiod   {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
3603d8817e4Smiod   {"strip-all", no_argument, 0, 'S'},
3613d8817e4Smiod   {"strip-debug", no_argument, 0, 'g'},
3623d8817e4Smiod   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
3633d8817e4Smiod   {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
3643d8817e4Smiod   {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
3653d8817e4Smiod   {"strip-symbol", required_argument, 0, 'N'},
3663d8817e4Smiod   {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
3673d8817e4Smiod   {"target", required_argument, 0, 'F'},
3683d8817e4Smiod   {"verbose", no_argument, 0, 'v'},
3693d8817e4Smiod   {"version", no_argument, 0, 'V'},
3703d8817e4Smiod   {"weaken", no_argument, 0, OPTION_WEAKEN},
3713d8817e4Smiod   {"weaken-symbol", required_argument, 0, 'W'},
3723d8817e4Smiod   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
3733d8817e4Smiod   {"wildcard", no_argument, 0, 'w'},
3743d8817e4Smiod   {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
3753d8817e4Smiod   {0, no_argument, 0, 0}
3763d8817e4Smiod };
3773d8817e4Smiod 
3783d8817e4Smiod /* IMPORTS */
3793d8817e4Smiod extern char *program_name;
3803d8817e4Smiod 
3813d8817e4Smiod /* This flag distinguishes between strip and objcopy:
3823d8817e4Smiod    1 means this is 'strip'; 0 means this is 'objcopy'.
3833d8817e4Smiod    -1 means if we should use argv[0] to decide.  */
3843d8817e4Smiod extern int is_strip;
3853d8817e4Smiod 
3863d8817e4Smiod /* The maximum length of an S record.  This variable is declared in srec.c
3873d8817e4Smiod    and can be modified by the --srec-len parameter.  */
3883d8817e4Smiod extern unsigned int Chunk;
3893d8817e4Smiod 
3903d8817e4Smiod /* Restrict the generation of Srecords to type S3 only.
3913d8817e4Smiod    This variable is declare in bfd/srec.c and can be toggled
3923d8817e4Smiod    on by the --srec-forceS3 command line switch.  */
3933d8817e4Smiod extern bfd_boolean S3Forced;
3943d8817e4Smiod 
3953d8817e4Smiod /* Defined in bfd/binary.c.  Used to set architecture and machine of input
3963d8817e4Smiod    binary files.  */
3973d8817e4Smiod extern enum bfd_architecture  bfd_external_binary_architecture;
3983d8817e4Smiod extern unsigned long          bfd_external_machine;
3993d8817e4Smiod 
4003d8817e4Smiod /* Forward declarations.  */
4013d8817e4Smiod static void setup_section (bfd *, asection *, void *);
4023d8817e4Smiod static void setup_bfd_headers (bfd *, bfd *);
4033d8817e4Smiod static void copy_section (bfd *, asection *, void *);
4043d8817e4Smiod static void get_sections (bfd *, asection *, void *);
4053d8817e4Smiod static int compare_section_lma (const void *, const void *);
4063d8817e4Smiod static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
4073d8817e4Smiod static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
4083d8817e4Smiod static const char *lookup_sym_redefinition (const char *);
4093d8817e4Smiod 
4103d8817e4Smiod static void
copy_usage(FILE * stream,int exit_status)4113d8817e4Smiod copy_usage (FILE *stream, int exit_status)
4123d8817e4Smiod {
4133d8817e4Smiod   fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
4143d8817e4Smiod   fprintf (stream, _(" Copies a binary file, possibly transforming it in the process\n"));
4153d8817e4Smiod   fprintf (stream, _(" The options are:\n"));
4163d8817e4Smiod   fprintf (stream, _("\
4173d8817e4Smiod   -I --input-target <bfdname>      Assume input file is in format <bfdname>\n\
4183d8817e4Smiod   -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
4193d8817e4Smiod   -B --binary-architecture <arch>  Set arch of output file, when input is binary\n\
4203d8817e4Smiod   -F --target <bfdname>            Set both input and output format to <bfdname>\n\
4213d8817e4Smiod      --debugging                   Convert debugging information, if possible\n\
4223d8817e4Smiod   -p --preserve-dates              Copy modified/access timestamps to the output\n\
4233d8817e4Smiod   -j --only-section <name>         Only copy section <name> into the output\n\
4243d8817e4Smiod      --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\n\
4253d8817e4Smiod   -R --remove-section <name>       Remove section <name> from the output\n\
4263d8817e4Smiod   -S --strip-all                   Remove all symbol and relocation information\n\
4273d8817e4Smiod   -g --strip-debug                 Remove all debugging symbols & sections\n\
4283d8817e4Smiod      --strip-unneeded              Remove all symbols not needed by relocations\n\
4293d8817e4Smiod   -N --strip-symbol <name>         Do not copy symbol <name>\n\
4303d8817e4Smiod      --strip-unneeded-symbol <name>\n\
4313d8817e4Smiod                                    Do not copy symbol <name> unless needed by\n\
4323d8817e4Smiod                                      relocations\n\
4333d8817e4Smiod      --only-keep-debug             Strip everything but the debug information\n\
4343d8817e4Smiod   -K --keep-symbol <name>          Do not strip symbol <name>\n\
4353d8817e4Smiod      --keep-file-symbols           Do not strip file symbol(s)\n\
436c065f989Skettenis      --localize-hidden             Turn all ELF hidden symbols into locals\n\
4373d8817e4Smiod   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
4383d8817e4Smiod      --globalize-symbol <name>     Force symbol <name> to be marked as a global\n\
4393d8817e4Smiod   -G --keep-global-symbol <name>   Localize all symbols except <name>\n\
4403d8817e4Smiod   -W --weaken-symbol <name>        Force symbol <name> to be marked as a weak\n\
4413d8817e4Smiod      --weaken                      Force all global symbols to be marked as weak\n\
4423d8817e4Smiod   -w --wildcard                    Permit wildcard in symbol comparison\n\
4433d8817e4Smiod   -x --discard-all                 Remove all non-global symbols\n\
4443d8817e4Smiod   -X --discard-locals              Remove any compiler-generated symbols\n\
4453d8817e4Smiod   -i --interleave <number>         Only copy one out of every <number> bytes\n\
4463d8817e4Smiod   -b --byte <num>                  Select byte <num> in every interleaved block\n\
4473d8817e4Smiod      --gap-fill <val>              Fill gaps between sections with <val>\n\
4483d8817e4Smiod      --pad-to <addr>               Pad the last section up to address <addr>\n\
4493d8817e4Smiod      --set-start <addr>            Set the start address to <addr>\n\
4503d8817e4Smiod     {--change-start|--adjust-start} <incr>\n\
4513d8817e4Smiod                                    Add <incr> to the start address\n\
4523d8817e4Smiod     {--change-addresses|--adjust-vma} <incr>\n\
4533d8817e4Smiod                                    Add <incr> to LMA, VMA and start addresses\n\
4543d8817e4Smiod     {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\
4553d8817e4Smiod                                    Change LMA and VMA of section <name> by <val>\n\
4563d8817e4Smiod      --change-section-lma <name>{=|+|-}<val>\n\
4573d8817e4Smiod                                    Change the LMA of section <name> by <val>\n\
4583d8817e4Smiod      --change-section-vma <name>{=|+|-}<val>\n\
4593d8817e4Smiod                                    Change the VMA of section <name> by <val>\n\
4603d8817e4Smiod     {--[no-]change-warnings|--[no-]adjust-warnings}\n\
4613d8817e4Smiod                                    Warn if a named section does not exist\n\
4623d8817e4Smiod      --set-section-flags <name>=<flags>\n\
4633d8817e4Smiod                                    Set section <name>'s properties to <flags>\n\
4643d8817e4Smiod      --add-section <name>=<file>   Add section <name> found in <file> to output\n\
4653d8817e4Smiod      --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
4663d8817e4Smiod      --change-leading-char         Force output format's leading character style\n\
4673d8817e4Smiod      --remove-leading-char         Remove leading character from global symbols\n\
4683d8817e4Smiod      --redefine-sym <old>=<new>    Redefine symbol name <old> to <new>\n\
4693d8817e4Smiod      --redefine-syms <file>        --redefine-sym for all symbol pairs \n\
4703d8817e4Smiod                                      listed in <file>\n\
4713d8817e4Smiod      --srec-len <number>           Restrict the length of generated Srecords\n\
4723d8817e4Smiod      --srec-forceS3                Restrict the type of generated Srecords to S3\n\
4733d8817e4Smiod      --strip-symbols <file>        -N for all symbols listed in <file>\n\
4743d8817e4Smiod      --strip-unneeded-symbols <file>\n\
4753d8817e4Smiod                                    --strip-unneeded-symbol for all symbols listed\n\
4763d8817e4Smiod                                      in <file>\n\
4773d8817e4Smiod      --keep-symbols <file>         -K for all symbols listed in <file>\n\
4783d8817e4Smiod      --localize-symbols <file>     -L for all symbols listed in <file>\n\
4793d8817e4Smiod      --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
4803d8817e4Smiod      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
4813d8817e4Smiod      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
4823d8817e4Smiod      --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
4833d8817e4Smiod      --writable-text               Mark the output text as writable\n\
4843d8817e4Smiod      --readonly-text               Make the output text write protected\n\
4853d8817e4Smiod      --pure                        Mark the output file as demand paged\n\
4863d8817e4Smiod      --impure                      Mark the output file as impure\n\
4873d8817e4Smiod      --prefix-symbols <prefix>     Add <prefix> to start of every symbol name\n\
4883d8817e4Smiod      --prefix-sections <prefix>    Add <prefix> to start of every section name\n\
4893d8817e4Smiod      --prefix-alloc-sections <prefix>\n\
4903d8817e4Smiod                                    Add <prefix> to start of every allocatable\n\
4913d8817e4Smiod                                      section name\n\
4923d8817e4Smiod   -v --verbose                     List all object files modified\n\
4933d8817e4Smiod   @<file>                          Read options from <file>\n\
4943d8817e4Smiod   -V --version                     Display this program's version number\n\
4953d8817e4Smiod   -h --help                        Display this output\n\
4963d8817e4Smiod      --info                        List object formats & architectures supported\n\
4973d8817e4Smiod "));
4983d8817e4Smiod   list_supported_targets (program_name, stream);
4993d8817e4Smiod   if (exit_status == 0)
5003d8817e4Smiod     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
5013d8817e4Smiod   exit (exit_status);
5023d8817e4Smiod }
5033d8817e4Smiod 
5043d8817e4Smiod static void
strip_usage(FILE * stream,int exit_status)5053d8817e4Smiod strip_usage (FILE *stream, int exit_status)
5063d8817e4Smiod {
5073d8817e4Smiod   fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name);
5083d8817e4Smiod   fprintf (stream, _(" Removes symbols and sections from files\n"));
5093d8817e4Smiod   fprintf (stream, _(" The options are:\n"));
5103d8817e4Smiod   fprintf (stream, _("\
5113d8817e4Smiod   -I --input-target=<bfdname>      Assume input file is in format <bfdname>\n\
5123d8817e4Smiod   -O --output-target=<bfdname>     Create an output file in format <bfdname>\n\
5133d8817e4Smiod   -F --target=<bfdname>            Set both input and output format to <bfdname>\n\
5143d8817e4Smiod   -p --preserve-dates              Copy modified/access timestamps to the output\n\
5153d8817e4Smiod   -R --remove-section=<name>       Remove section <name> from the output\n\
5163d8817e4Smiod   -s --strip-all                   Remove all symbol and relocation information\n\
5173d8817e4Smiod   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
5183d8817e4Smiod      --strip-unneeded              Remove all symbols not needed by relocations\n\
5193d8817e4Smiod      --only-keep-debug             Strip everything but the debug information\n\
5203d8817e4Smiod   -N --strip-symbol=<name>         Do not copy symbol <name>\n\
5213d8817e4Smiod   -K --keep-symbol=<name>          Do not strip symbol <name>\n\
5223d8817e4Smiod      --keep-file-symbols           Do not strip file symbol(s)\n\
5233d8817e4Smiod   -w --wildcard                    Permit wildcard in symbol comparison\n\
5243d8817e4Smiod   -x --discard-all                 Remove all non-global symbols\n\
5253d8817e4Smiod   -X --discard-locals              Remove any compiler-generated symbols\n\
5263d8817e4Smiod   -v --verbose                     List all object files modified\n\
5273d8817e4Smiod   -V --version                     Display this program's version number\n\
5283d8817e4Smiod   -h --help                        Display this output\n\
5293d8817e4Smiod      --info                        List object formats & architectures supported\n\
5303d8817e4Smiod   -o <file>                        Place stripped output into <file>\n\
5313d8817e4Smiod "));
5323d8817e4Smiod 
5333d8817e4Smiod   list_supported_targets (program_name, stream);
5343d8817e4Smiod   if (exit_status == 0)
5353d8817e4Smiod     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
5363d8817e4Smiod   exit (exit_status);
5373d8817e4Smiod }
5383d8817e4Smiod 
5393d8817e4Smiod /* Parse section flags into a flagword, with a fatal error if the
5403d8817e4Smiod    string can't be parsed.  */
5413d8817e4Smiod 
5423d8817e4Smiod static flagword
parse_flags(const char * s)5433d8817e4Smiod parse_flags (const char *s)
5443d8817e4Smiod {
5453d8817e4Smiod   flagword ret;
5463d8817e4Smiod   const char *snext;
5473d8817e4Smiod   int len;
5483d8817e4Smiod 
5493d8817e4Smiod   ret = SEC_NO_FLAGS;
5503d8817e4Smiod 
5513d8817e4Smiod   do
5523d8817e4Smiod     {
5533d8817e4Smiod       snext = strchr (s, ',');
5543d8817e4Smiod       if (snext == NULL)
5553d8817e4Smiod 	len = strlen (s);
5563d8817e4Smiod       else
5573d8817e4Smiod 	{
5583d8817e4Smiod 	  len = snext - s;
5593d8817e4Smiod 	  ++snext;
5603d8817e4Smiod 	}
5613d8817e4Smiod 
5623d8817e4Smiod       if (0) ;
5633d8817e4Smiod #define PARSE_FLAG(fname,fval) \
5643d8817e4Smiod   else if (strncasecmp (fname, s, len) == 0) ret |= fval
5653d8817e4Smiod       PARSE_FLAG ("alloc", SEC_ALLOC);
5663d8817e4Smiod       PARSE_FLAG ("load", SEC_LOAD);
5673d8817e4Smiod       PARSE_FLAG ("noload", SEC_NEVER_LOAD);
5683d8817e4Smiod       PARSE_FLAG ("readonly", SEC_READONLY);
5693d8817e4Smiod       PARSE_FLAG ("debug", SEC_DEBUGGING);
5703d8817e4Smiod       PARSE_FLAG ("code", SEC_CODE);
5713d8817e4Smiod       PARSE_FLAG ("data", SEC_DATA);
5723d8817e4Smiod       PARSE_FLAG ("rom", SEC_ROM);
5733d8817e4Smiod       PARSE_FLAG ("share", SEC_COFF_SHARED);
5743d8817e4Smiod       PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
5753d8817e4Smiod #undef PARSE_FLAG
5763d8817e4Smiod       else
5773d8817e4Smiod 	{
5783d8817e4Smiod 	  char *copy;
5793d8817e4Smiod 
5803d8817e4Smiod 	  copy = xmalloc (len + 1);
5813d8817e4Smiod 	  strncpy (copy, s, len);
5823d8817e4Smiod 	  copy[len] = '\0';
5833d8817e4Smiod 	  non_fatal (_("unrecognized section flag `%s'"), copy);
5843d8817e4Smiod 	  fatal (_("supported flags: %s"),
5853d8817e4Smiod 		 "alloc, load, noload, readonly, debug, code, data, rom, share, contents");
5863d8817e4Smiod 	}
5873d8817e4Smiod 
5883d8817e4Smiod       s = snext;
5893d8817e4Smiod     }
5903d8817e4Smiod   while (s != NULL);
5913d8817e4Smiod 
5923d8817e4Smiod   return ret;
5933d8817e4Smiod }
5943d8817e4Smiod 
5953d8817e4Smiod /* Find and optionally add an entry in the change_sections list.  */
5963d8817e4Smiod 
5973d8817e4Smiod static struct section_list *
find_section_list(const char * name,bfd_boolean add)5983d8817e4Smiod find_section_list (const char *name, bfd_boolean add)
5993d8817e4Smiod {
6003d8817e4Smiod   struct section_list *p;
6013d8817e4Smiod 
6023d8817e4Smiod   for (p = change_sections; p != NULL; p = p->next)
6033d8817e4Smiod     if (strcmp (p->name, name) == 0)
6043d8817e4Smiod       return p;
6053d8817e4Smiod 
6063d8817e4Smiod   if (! add)
6073d8817e4Smiod     return NULL;
6083d8817e4Smiod 
6093d8817e4Smiod   p = xmalloc (sizeof (struct section_list));
6103d8817e4Smiod   p->name = name;
6113d8817e4Smiod   p->used = FALSE;
6123d8817e4Smiod   p->remove = FALSE;
6133d8817e4Smiod   p->copy = FALSE;
6143d8817e4Smiod   p->change_vma = CHANGE_IGNORE;
6153d8817e4Smiod   p->change_lma = CHANGE_IGNORE;
6163d8817e4Smiod   p->vma_val = 0;
6173d8817e4Smiod   p->lma_val = 0;
6183d8817e4Smiod   p->set_flags = FALSE;
6193d8817e4Smiod   p->flags = 0;
6203d8817e4Smiod 
6213d8817e4Smiod   p->next = change_sections;
6223d8817e4Smiod   change_sections = p;
6233d8817e4Smiod 
6243d8817e4Smiod   return p;
6253d8817e4Smiod }
6263d8817e4Smiod 
6273d8817e4Smiod /* Add a symbol to strip_specific_list.  */
6283d8817e4Smiod 
6293d8817e4Smiod static void
add_specific_symbol(const char * name,struct symlist ** list)6303d8817e4Smiod add_specific_symbol (const char *name, struct symlist **list)
6313d8817e4Smiod {
6323d8817e4Smiod   struct symlist *tmp_list;
6333d8817e4Smiod 
6343d8817e4Smiod   tmp_list = xmalloc (sizeof (struct symlist));
6353d8817e4Smiod   tmp_list->name = name;
6363d8817e4Smiod   tmp_list->next = *list;
6373d8817e4Smiod   *list = tmp_list;
6383d8817e4Smiod }
6393d8817e4Smiod 
6403d8817e4Smiod /* Add symbols listed in `filename' to strip_specific_list.  */
6413d8817e4Smiod 
6423d8817e4Smiod #define IS_WHITESPACE(c)      ((c) == ' ' || (c) == '\t')
6433d8817e4Smiod #define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
6443d8817e4Smiod 
6453d8817e4Smiod static void
add_specific_symbols(const char * filename,struct symlist ** list)6463d8817e4Smiod add_specific_symbols (const char *filename, struct symlist **list)
6473d8817e4Smiod {
6483d8817e4Smiod   off_t  size;
6493d8817e4Smiod   FILE * f;
6503d8817e4Smiod   char * line;
6513d8817e4Smiod   char * buffer;
6523d8817e4Smiod   unsigned int line_count;
6533d8817e4Smiod 
6543d8817e4Smiod   size = get_file_size (filename);
6553d8817e4Smiod   if (size == 0)
6563d8817e4Smiod     return;
6573d8817e4Smiod 
6583d8817e4Smiod   buffer = xmalloc (size + 2);
6593d8817e4Smiod   f = fopen (filename, FOPEN_RT);
6603d8817e4Smiod   if (f == NULL)
6613d8817e4Smiod     fatal (_("cannot open '%s': %s"), filename, strerror (errno));
6623d8817e4Smiod 
6633d8817e4Smiod   if (fread (buffer, 1, size, f) == 0 || ferror (f))
6643d8817e4Smiod     fatal (_("%s: fread failed"), filename);
6653d8817e4Smiod 
6663d8817e4Smiod   fclose (f);
6673d8817e4Smiod   buffer [size] = '\n';
6683d8817e4Smiod   buffer [size + 1] = '\0';
6693d8817e4Smiod 
6703d8817e4Smiod   line_count = 1;
6713d8817e4Smiod 
6723d8817e4Smiod   for (line = buffer; * line != '\0'; line ++)
6733d8817e4Smiod     {
6743d8817e4Smiod       char * eol;
6753d8817e4Smiod       char * name;
6763d8817e4Smiod       char * name_end;
6773d8817e4Smiod       int finished = FALSE;
6783d8817e4Smiod 
6793d8817e4Smiod       for (eol = line;; eol ++)
6803d8817e4Smiod 	{
6813d8817e4Smiod 	  switch (* eol)
6823d8817e4Smiod 	    {
6833d8817e4Smiod 	    case '\n':
6843d8817e4Smiod 	      * eol = '\0';
6853d8817e4Smiod 	      /* Cope with \n\r.  */
6863d8817e4Smiod 	      if (eol[1] == '\r')
6873d8817e4Smiod 		++ eol;
6883d8817e4Smiod 	      finished = TRUE;
6893d8817e4Smiod 	      break;
6903d8817e4Smiod 
6913d8817e4Smiod 	    case '\r':
6923d8817e4Smiod 	      * eol = '\0';
6933d8817e4Smiod 	      /* Cope with \r\n.  */
6943d8817e4Smiod 	      if (eol[1] == '\n')
6953d8817e4Smiod 		++ eol;
6963d8817e4Smiod 	      finished = TRUE;
6973d8817e4Smiod 	      break;
6983d8817e4Smiod 
6993d8817e4Smiod 	    case 0:
7003d8817e4Smiod 	      finished = TRUE;
7013d8817e4Smiod 	      break;
7023d8817e4Smiod 
7033d8817e4Smiod 	    case '#':
7043d8817e4Smiod 	      /* Line comment, Terminate the line here, in case a
7053d8817e4Smiod 		 name is present and then allow the rest of the
7063d8817e4Smiod 		 loop to find the real end of the line.  */
7073d8817e4Smiod 	      * eol = '\0';
7083d8817e4Smiod 	      break;
7093d8817e4Smiod 
7103d8817e4Smiod 	    default:
7113d8817e4Smiod 	      break;
7123d8817e4Smiod 	    }
7133d8817e4Smiod 
7143d8817e4Smiod 	  if (finished)
7153d8817e4Smiod 	    break;
7163d8817e4Smiod 	}
7173d8817e4Smiod 
7183d8817e4Smiod       /* A name may now exist somewhere between 'line' and 'eol'.
7193d8817e4Smiod 	 Strip off leading whitespace and trailing whitespace,
7203d8817e4Smiod 	 then add it to the list.  */
7213d8817e4Smiod       for (name = line; IS_WHITESPACE (* name); name ++)
7223d8817e4Smiod 	;
7233d8817e4Smiod       for (name_end = name;
7243d8817e4Smiod 	   (! IS_WHITESPACE (* name_end))
7253d8817e4Smiod 	   && (! IS_LINE_TERMINATOR (* name_end));
7263d8817e4Smiod 	   name_end ++)
7273d8817e4Smiod 	;
7283d8817e4Smiod 
7293d8817e4Smiod       if (! IS_LINE_TERMINATOR (* name_end))
7303d8817e4Smiod 	{
7313d8817e4Smiod 	  char * extra;
7323d8817e4Smiod 
7333d8817e4Smiod 	  for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++)
7343d8817e4Smiod 	    ;
7353d8817e4Smiod 
7363d8817e4Smiod 	  if (! IS_LINE_TERMINATOR (* extra))
7373d8817e4Smiod 	    non_fatal (_("%s:%d: Ignoring rubbish found on this line"),
7383d8817e4Smiod 		       filename, line_count);
7393d8817e4Smiod 	}
7403d8817e4Smiod 
7413d8817e4Smiod       * name_end = '\0';
7423d8817e4Smiod 
7433d8817e4Smiod       if (name_end > name)
7443d8817e4Smiod 	add_specific_symbol (name, list);
7453d8817e4Smiod 
7463d8817e4Smiod       /* Advance line pointer to end of line.  The 'eol ++' in the for
7473d8817e4Smiod 	 loop above will then advance us to the start of the next line.  */
7483d8817e4Smiod       line = eol;
7493d8817e4Smiod       line_count ++;
7503d8817e4Smiod     }
7513d8817e4Smiod }
7523d8817e4Smiod 
7533d8817e4Smiod /* See whether a symbol should be stripped or kept based on
7543d8817e4Smiod    strip_specific_list and keep_symbols.  */
7553d8817e4Smiod 
7563d8817e4Smiod static bfd_boolean
is_specified_symbol(const char * name,struct symlist * list)7573d8817e4Smiod is_specified_symbol (const char *name, struct symlist *list)
7583d8817e4Smiod {
7593d8817e4Smiod   struct symlist *tmp_list;
7603d8817e4Smiod 
7613d8817e4Smiod   if (wildcard)
7623d8817e4Smiod     {
7633d8817e4Smiod       for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
7643d8817e4Smiod 	if (*(tmp_list->name) != '!')
7653d8817e4Smiod 	  {
7663d8817e4Smiod 	    if (!fnmatch (tmp_list->name, name, 0))
7673d8817e4Smiod 	      return TRUE;
7683d8817e4Smiod 	  }
7693d8817e4Smiod 	else
7703d8817e4Smiod 	  {
7713d8817e4Smiod 	    if (fnmatch (tmp_list->name + 1, name, 0))
7723d8817e4Smiod 	      return TRUE;
7733d8817e4Smiod 	  }
7743d8817e4Smiod     }
7753d8817e4Smiod   else
7763d8817e4Smiod     {
7773d8817e4Smiod       for (tmp_list = list; tmp_list; tmp_list = tmp_list->next)
7783d8817e4Smiod 	if (strcmp (name, tmp_list->name) == 0)
7793d8817e4Smiod 	  return TRUE;
7803d8817e4Smiod     }
7813d8817e4Smiod 
7823d8817e4Smiod   return FALSE;
7833d8817e4Smiod }
7843d8817e4Smiod 
7853d8817e4Smiod /* See if a section is being removed.  */
7863d8817e4Smiod 
7873d8817e4Smiod static bfd_boolean
is_strip_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)7883d8817e4Smiod is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
7893d8817e4Smiod {
7903d8817e4Smiod   if (sections_removed || sections_copied)
7913d8817e4Smiod     {
7923d8817e4Smiod       struct section_list *p;
7933d8817e4Smiod 
7943d8817e4Smiod       p = find_section_list (bfd_get_section_name (abfd, sec), FALSE);
7953d8817e4Smiod 
7963d8817e4Smiod       if (sections_removed && p != NULL && p->remove)
7973d8817e4Smiod 	return TRUE;
7983d8817e4Smiod       if (sections_copied && (p == NULL || ! p->copy))
7993d8817e4Smiod 	return TRUE;
8003d8817e4Smiod     }
8013d8817e4Smiod 
8023d8817e4Smiod   if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0)
8033d8817e4Smiod     {
8043d8817e4Smiod       if (strip_symbols == STRIP_DEBUG
8053d8817e4Smiod 	  || strip_symbols == STRIP_UNNEEDED
8063d8817e4Smiod 	  || strip_symbols == STRIP_ALL
8073d8817e4Smiod 	  || discard_locals == LOCALS_ALL
8083d8817e4Smiod 	  || convert_debugging)
8093d8817e4Smiod 	return TRUE;
8103d8817e4Smiod 
8113d8817e4Smiod       if (strip_symbols == STRIP_NONDEBUG)
8123d8817e4Smiod 	return FALSE;
8133d8817e4Smiod     }
8143d8817e4Smiod 
8153d8817e4Smiod   return FALSE;
8163d8817e4Smiod }
8173d8817e4Smiod 
818c065f989Skettenis /* Return true if SYM is a hidden symbol.  */
819c065f989Skettenis 
820c065f989Skettenis static bfd_boolean
is_hidden_symbol(asymbol * sym)821c065f989Skettenis is_hidden_symbol (asymbol *sym)
822c065f989Skettenis {
823c065f989Skettenis   elf_symbol_type *elf_sym;
824c065f989Skettenis 
825c065f989Skettenis   elf_sym = elf_symbol_from (sym->the_bfd, sym);
826c065f989Skettenis   if (elf_sym != NULL)
827c065f989Skettenis     switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
828c065f989Skettenis       {
829c065f989Skettenis       case STV_HIDDEN:
830c065f989Skettenis       case STV_INTERNAL:
831c065f989Skettenis        return TRUE;
832c065f989Skettenis       }
833c065f989Skettenis   return FALSE;
834c065f989Skettenis }
835c065f989Skettenis 
8363d8817e4Smiod /* Choose which symbol entries to copy; put the result in OSYMS.
8373d8817e4Smiod    We don't copy in place, because that confuses the relocs.
8383d8817e4Smiod    Return the number of symbols to print.  */
8393d8817e4Smiod 
8403d8817e4Smiod static unsigned int
filter_symbols(bfd * abfd,bfd * obfd,asymbol ** osyms,asymbol ** isyms,long symcount)8413d8817e4Smiod filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
8423d8817e4Smiod 		asymbol **isyms, long symcount)
8433d8817e4Smiod {
8443d8817e4Smiod   asymbol **from = isyms, **to = osyms;
8453d8817e4Smiod   long src_count = 0, dst_count = 0;
8463d8817e4Smiod   int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC))
8473d8817e4Smiod 		    == HAS_RELOC;
8483d8817e4Smiod 
8493d8817e4Smiod   for (; src_count < symcount; src_count++)
8503d8817e4Smiod     {
8513d8817e4Smiod       asymbol *sym = from[src_count];
8523d8817e4Smiod       flagword flags = sym->flags;
8533d8817e4Smiod       char *name = (char *) bfd_asymbol_name (sym);
8543d8817e4Smiod       int keep;
8553d8817e4Smiod       bfd_boolean undefined;
8563d8817e4Smiod       bfd_boolean rem_leading_char;
8573d8817e4Smiod       bfd_boolean add_leading_char;
8583d8817e4Smiod 
8593d8817e4Smiod       undefined = bfd_is_und_section (bfd_get_section (sym));
8603d8817e4Smiod 
8613d8817e4Smiod       if (redefine_sym_list)
8623d8817e4Smiod 	{
8633d8817e4Smiod 	  char *old_name, *new_name;
8643d8817e4Smiod 
8653d8817e4Smiod 	  old_name = (char *) bfd_asymbol_name (sym);
8663d8817e4Smiod 	  new_name = (char *) lookup_sym_redefinition (old_name);
8673d8817e4Smiod 	  bfd_asymbol_name (sym) = new_name;
8683d8817e4Smiod 	  name = new_name;
8693d8817e4Smiod 	}
8703d8817e4Smiod 
8713d8817e4Smiod       /* Check if we will remove the current leading character.  */
8723d8817e4Smiod       rem_leading_char =
8733d8817e4Smiod 	(name[0] == bfd_get_symbol_leading_char (abfd))
8743d8817e4Smiod 	&& (change_leading_char
8753d8817e4Smiod 	    || (remove_leading_char
8763d8817e4Smiod 		&& ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
8773d8817e4Smiod 		    || undefined
8783d8817e4Smiod 		    || bfd_is_com_section (bfd_get_section (sym)))));
8793d8817e4Smiod 
8803d8817e4Smiod       /* Check if we will add a new leading character.  */
8813d8817e4Smiod       add_leading_char =
8823d8817e4Smiod 	change_leading_char
8833d8817e4Smiod 	&& (bfd_get_symbol_leading_char (obfd) != '\0')
8843d8817e4Smiod 	&& (bfd_get_symbol_leading_char (abfd) == '\0'
8853d8817e4Smiod 	    || (name[0] == bfd_get_symbol_leading_char (abfd)));
8863d8817e4Smiod 
8873d8817e4Smiod       /* Short circuit for change_leading_char if we can do it in-place.  */
8883d8817e4Smiod       if (rem_leading_char && add_leading_char && !prefix_symbols_string)
8893d8817e4Smiod         {
8903d8817e4Smiod 	  name[0] = bfd_get_symbol_leading_char (obfd);
8913d8817e4Smiod 	  bfd_asymbol_name (sym) = name;
8923d8817e4Smiod 	  rem_leading_char = FALSE;
8933d8817e4Smiod 	  add_leading_char = FALSE;
8943d8817e4Smiod         }
8953d8817e4Smiod 
8963d8817e4Smiod       /* Remove leading char.  */
8973d8817e4Smiod       if (rem_leading_char)
8983d8817e4Smiod 	bfd_asymbol_name (sym) = ++name;
8993d8817e4Smiod 
9003d8817e4Smiod       /* Add new leading char and/or prefix.  */
9013d8817e4Smiod       if (add_leading_char || prefix_symbols_string)
9023d8817e4Smiod         {
9033d8817e4Smiod           char *n, *ptr;
9043d8817e4Smiod 
9053d8817e4Smiod           ptr = n = xmalloc (1 + strlen (prefix_symbols_string)
9063d8817e4Smiod 			     + strlen (name) + 1);
9073d8817e4Smiod           if (add_leading_char)
9083d8817e4Smiod 	    *ptr++ = bfd_get_symbol_leading_char (obfd);
9093d8817e4Smiod 
9103d8817e4Smiod           if (prefix_symbols_string)
9113d8817e4Smiod             {
9123d8817e4Smiod               strcpy (ptr, prefix_symbols_string);
9133d8817e4Smiod               ptr += strlen (prefix_symbols_string);
9143d8817e4Smiod            }
9153d8817e4Smiod 
9163d8817e4Smiod           strcpy (ptr, name);
9173d8817e4Smiod           bfd_asymbol_name (sym) = n;
9183d8817e4Smiod           name = n;
9193d8817e4Smiod 	}
9203d8817e4Smiod 
9213d8817e4Smiod       if (strip_symbols == STRIP_ALL)
9223d8817e4Smiod 	keep = 0;
9233d8817e4Smiod       else if ((flags & BSF_KEEP) != 0		/* Used in relocation.  */
9243d8817e4Smiod 	       || ((flags & BSF_SECTION_SYM) != 0
9253d8817e4Smiod 		   && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
9263d8817e4Smiod 		       & BSF_KEEP) != 0))
9273d8817e4Smiod 	keep = 1;
9283d8817e4Smiod       else if (relocatable			/* Relocatable file.  */
9293d8817e4Smiod 	       && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
9303d8817e4Smiod 	keep = 1;
9313d8817e4Smiod       else if (bfd_decode_symclass (sym) == 'I')
9323d8817e4Smiod 	/* Global symbols in $idata sections need to be retained
9333d8817e4Smiod 	   even if relocatable is FALSE.  External users of the
9343d8817e4Smiod 	   library containing the $idata section may reference these
9353d8817e4Smiod 	   symbols.  */
9363d8817e4Smiod 	keep = 1;
9373d8817e4Smiod       else if ((flags & BSF_GLOBAL) != 0	/* Global symbol.  */
9383d8817e4Smiod 	       || (flags & BSF_WEAK) != 0
9393d8817e4Smiod 	       || undefined
9403d8817e4Smiod 	       || bfd_is_com_section (bfd_get_section (sym)))
9413d8817e4Smiod 	keep = strip_symbols != STRIP_UNNEEDED;
9423d8817e4Smiod       else if ((flags & BSF_DEBUGGING) != 0)	/* Debugging symbol.  */
9433d8817e4Smiod 	keep = (strip_symbols != STRIP_DEBUG
9443d8817e4Smiod 		&& strip_symbols != STRIP_UNNEEDED
9453d8817e4Smiod 		&& ! convert_debugging);
9463d8817e4Smiod       else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
9473d8817e4Smiod 	/* COMDAT sections store special information in local
9483d8817e4Smiod 	   symbols, so we cannot risk stripping any of them.  */
9493d8817e4Smiod 	keep = 1;
9503d8817e4Smiod       else			/* Local symbol.  */
9513d8817e4Smiod 	keep = (strip_symbols != STRIP_UNNEEDED
9523d8817e4Smiod 		&& (discard_locals != LOCALS_ALL
9533d8817e4Smiod 		    && (discard_locals != LOCALS_START_L
9543d8817e4Smiod 			|| ! bfd_is_local_label (abfd, sym))));
9553d8817e4Smiod 
9563d8817e4Smiod       if (keep && is_specified_symbol (name, strip_specific_list))
9573d8817e4Smiod 	keep = 0;
9583d8817e4Smiod       if (keep
9593d8817e4Smiod 	  && !(flags & BSF_KEEP)
9603d8817e4Smiod 	  && is_specified_symbol (name, strip_unneeded_list))
9613d8817e4Smiod 	keep = 0;
9623d8817e4Smiod       if (!keep
9633d8817e4Smiod 	  && ((keep_file_symbols && (flags & BSF_FILE))
9643d8817e4Smiod 	      || is_specified_symbol (name, keep_specific_list)))
9653d8817e4Smiod 	keep = 1;
9663d8817e4Smiod       if (keep && is_strip_section (abfd, bfd_get_section (sym)))
9673d8817e4Smiod 	keep = 0;
9683d8817e4Smiod 
9693d8817e4Smiod       if (keep)
9703d8817e4Smiod 	{
9713d8817e4Smiod 	  if ((flags & BSF_GLOBAL) != 0
9723d8817e4Smiod 	      && (weaken || is_specified_symbol (name, weaken_specific_list)))
9733d8817e4Smiod 	    {
9743d8817e4Smiod 	      sym->flags &= ~ BSF_GLOBAL;
9753d8817e4Smiod 	      sym->flags |= BSF_WEAK;
9763d8817e4Smiod 	    }
9773d8817e4Smiod 
9783d8817e4Smiod 	  if (!undefined
9793d8817e4Smiod 	      && (flags & (BSF_GLOBAL | BSF_WEAK))
9803d8817e4Smiod 	      && (is_specified_symbol (name, localize_specific_list)
9813d8817e4Smiod 		  || (keepglobal_specific_list != NULL
982c065f989Skettenis 		      && ! is_specified_symbol (name, keepglobal_specific_list))
983c065f989Skettenis 		  || (localize_hidden && is_hidden_symbol (sym))))
9843d8817e4Smiod 	    {
9853d8817e4Smiod 	      sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
9863d8817e4Smiod 	      sym->flags |= BSF_LOCAL;
9873d8817e4Smiod 	    }
9883d8817e4Smiod 
9893d8817e4Smiod 	  if (!undefined
9903d8817e4Smiod 	      && (flags & BSF_LOCAL)
9913d8817e4Smiod 	      && is_specified_symbol (name, globalize_specific_list))
9923d8817e4Smiod 	    {
9933d8817e4Smiod 	      sym->flags &= ~ BSF_LOCAL;
9943d8817e4Smiod 	      sym->flags |= BSF_GLOBAL;
9953d8817e4Smiod 	    }
9963d8817e4Smiod 
9973d8817e4Smiod 	  to[dst_count++] = sym;
9983d8817e4Smiod 	}
9993d8817e4Smiod     }
10003d8817e4Smiod 
10013d8817e4Smiod   to[dst_count] = NULL;
10023d8817e4Smiod 
10033d8817e4Smiod   return dst_count;
10043d8817e4Smiod }
10053d8817e4Smiod 
10063d8817e4Smiod /* Find the redefined name of symbol SOURCE.  */
10073d8817e4Smiod 
10083d8817e4Smiod static const char *
lookup_sym_redefinition(const char * source)10093d8817e4Smiod lookup_sym_redefinition (const char *source)
10103d8817e4Smiod {
10113d8817e4Smiod   struct redefine_node *list;
10123d8817e4Smiod 
10133d8817e4Smiod   for (list = redefine_sym_list; list != NULL; list = list->next)
10143d8817e4Smiod     if (strcmp (source, list->source) == 0)
10153d8817e4Smiod       return list->target;
10163d8817e4Smiod 
10173d8817e4Smiod   return source;
10183d8817e4Smiod }
10193d8817e4Smiod 
10203d8817e4Smiod /* Add a node to a symbol redefine list.  */
10213d8817e4Smiod 
10223d8817e4Smiod static void
redefine_list_append(const char * cause,const char * source,const char * target)10233d8817e4Smiod redefine_list_append (const char *cause, const char *source, const char *target)
10243d8817e4Smiod {
10253d8817e4Smiod   struct redefine_node **p;
10263d8817e4Smiod   struct redefine_node *list;
10273d8817e4Smiod   struct redefine_node *new_node;
10283d8817e4Smiod 
10293d8817e4Smiod   for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
10303d8817e4Smiod     {
10313d8817e4Smiod       if (strcmp (source, list->source) == 0)
10323d8817e4Smiod 	fatal (_("%s: Multiple redefinition of symbol \"%s\""),
10333d8817e4Smiod 	       cause, source);
10343d8817e4Smiod 
10353d8817e4Smiod       if (strcmp (target, list->target) == 0)
10363d8817e4Smiod 	fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
10373d8817e4Smiod 	       cause, target);
10383d8817e4Smiod     }
10393d8817e4Smiod 
10403d8817e4Smiod   new_node = xmalloc (sizeof (struct redefine_node));
10413d8817e4Smiod 
10423d8817e4Smiod   new_node->source = strdup (source);
10433d8817e4Smiod   new_node->target = strdup (target);
10443d8817e4Smiod   new_node->next = NULL;
10453d8817e4Smiod 
10463d8817e4Smiod   *p = new_node;
10473d8817e4Smiod }
10483d8817e4Smiod 
10493d8817e4Smiod /* Handle the --redefine-syms option.  Read lines containing "old new"
10503d8817e4Smiod    from the file, and add them to the symbol redefine list.  */
10513d8817e4Smiod 
10523d8817e4Smiod static void
add_redefine_syms_file(const char * filename)10533d8817e4Smiod add_redefine_syms_file (const char *filename)
10543d8817e4Smiod {
10553d8817e4Smiod   FILE *file;
10563d8817e4Smiod   char *buf;
10573d8817e4Smiod   size_t bufsize;
10583d8817e4Smiod   size_t len;
10593d8817e4Smiod   size_t outsym_off;
10603d8817e4Smiod   int c, lineno;
10613d8817e4Smiod 
10623d8817e4Smiod   file = fopen (filename, "r");
10633d8817e4Smiod   if (file == NULL)
10643d8817e4Smiod     fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
10653d8817e4Smiod 	   filename, strerror (errno));
10663d8817e4Smiod 
10673d8817e4Smiod   bufsize = 100;
10683d8817e4Smiod   buf = xmalloc (bufsize);
10693d8817e4Smiod 
10703d8817e4Smiod   lineno = 1;
10713d8817e4Smiod   c = getc (file);
10723d8817e4Smiod   len = 0;
10733d8817e4Smiod   outsym_off = 0;
10743d8817e4Smiod   while (c != EOF)
10753d8817e4Smiod     {
10763d8817e4Smiod       /* Collect the input symbol name.  */
10773d8817e4Smiod       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
10783d8817e4Smiod 	{
10793d8817e4Smiod 	  if (c == '#')
10803d8817e4Smiod 	    goto comment;
10813d8817e4Smiod 	  buf[len++] = c;
10823d8817e4Smiod 	  if (len >= bufsize)
10833d8817e4Smiod 	    {
10843d8817e4Smiod 	      bufsize *= 2;
10853d8817e4Smiod 	      buf = xrealloc (buf, bufsize);
10863d8817e4Smiod 	    }
10873d8817e4Smiod 	  c = getc (file);
10883d8817e4Smiod 	}
10893d8817e4Smiod       buf[len++] = '\0';
10903d8817e4Smiod       if (c == EOF)
10913d8817e4Smiod 	break;
10923d8817e4Smiod 
10933d8817e4Smiod       /* Eat white space between the symbol names.  */
10943d8817e4Smiod       while (IS_WHITESPACE (c))
10953d8817e4Smiod 	c = getc (file);
10963d8817e4Smiod       if (c == '#' || IS_LINE_TERMINATOR (c))
10973d8817e4Smiod 	goto comment;
10983d8817e4Smiod       if (c == EOF)
10993d8817e4Smiod 	break;
11003d8817e4Smiod 
11013d8817e4Smiod       /* Collect the output symbol name.  */
11023d8817e4Smiod       outsym_off = len;
11033d8817e4Smiod       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
11043d8817e4Smiod 	{
11053d8817e4Smiod 	  if (c == '#')
11063d8817e4Smiod 	    goto comment;
11073d8817e4Smiod 	  buf[len++] = c;
11083d8817e4Smiod 	  if (len >= bufsize)
11093d8817e4Smiod 	    {
11103d8817e4Smiod 	      bufsize *= 2;
11113d8817e4Smiod 	      buf = xrealloc (buf, bufsize);
11123d8817e4Smiod 	    }
11133d8817e4Smiod 	  c = getc (file);
11143d8817e4Smiod 	}
11153d8817e4Smiod       buf[len++] = '\0';
11163d8817e4Smiod       if (c == EOF)
11173d8817e4Smiod 	break;
11183d8817e4Smiod 
11193d8817e4Smiod       /* Eat white space at end of line.  */
11203d8817e4Smiod       while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c))
11213d8817e4Smiod 	c = getc (file);
11223d8817e4Smiod       if (c == '#')
11233d8817e4Smiod 	goto comment;
11243d8817e4Smiod       /* Handle \r\n.  */
11253d8817e4Smiod       if ((c == '\r' && (c = getc (file)) == '\n')
11263d8817e4Smiod 	  || c == '\n' || c == EOF)
11273d8817e4Smiod 	{
11283d8817e4Smiod  end_of_line:
11293d8817e4Smiod 	  /* Append the redefinition to the list.  */
11303d8817e4Smiod 	  if (buf[0] != '\0')
11313d8817e4Smiod 	    redefine_list_append (filename, &buf[0], &buf[outsym_off]);
11323d8817e4Smiod 
11333d8817e4Smiod 	  lineno++;
11343d8817e4Smiod 	  len = 0;
11353d8817e4Smiod 	  outsym_off = 0;
11363d8817e4Smiod 	  if (c == EOF)
11373d8817e4Smiod 	    break;
11383d8817e4Smiod 	  c = getc (file);
11393d8817e4Smiod 	  continue;
11403d8817e4Smiod 	}
11413d8817e4Smiod       else
11423d8817e4Smiod 	fatal (_("%s:%d: garbage found at end of line"), filename, lineno);
11433d8817e4Smiod  comment:
11443d8817e4Smiod       if (len != 0 && (outsym_off == 0 || outsym_off == len))
11453d8817e4Smiod 	fatal (_("%s:%d: missing new symbol name"), filename, lineno);
11463d8817e4Smiod       buf[len++] = '\0';
11473d8817e4Smiod 
11483d8817e4Smiod       /* Eat the rest of the line and finish it.  */
11493d8817e4Smiod       while (c != '\n' && c != EOF)
11503d8817e4Smiod 	c = getc (file);
11513d8817e4Smiod       goto end_of_line;
11523d8817e4Smiod     }
11533d8817e4Smiod 
11543d8817e4Smiod   if (len != 0)
11553d8817e4Smiod     fatal (_("%s:%d: premature end of file"), filename, lineno);
11563d8817e4Smiod 
11573d8817e4Smiod   free (buf);
11583d8817e4Smiod }
11593d8817e4Smiod 
11603d8817e4Smiod /* Copy unkown object file IBFD onto OBFD.
11613d8817e4Smiod    Returns TRUE upon success, FALSE otherwise.  */
11623d8817e4Smiod 
11633d8817e4Smiod static bfd_boolean
copy_unknown_object(bfd * ibfd,bfd * obfd)11643d8817e4Smiod copy_unknown_object (bfd *ibfd, bfd *obfd)
11653d8817e4Smiod {
11663d8817e4Smiod   char *cbuf;
11673d8817e4Smiod   int tocopy;
11683d8817e4Smiod   long ncopied;
11693d8817e4Smiod   long size;
11703d8817e4Smiod   struct stat buf;
11713d8817e4Smiod 
11723d8817e4Smiod   if (bfd_stat_arch_elt (ibfd, &buf) != 0)
11733d8817e4Smiod     {
11743d8817e4Smiod       bfd_nonfatal (bfd_get_archive_filename (ibfd));
11753d8817e4Smiod       return FALSE;
11763d8817e4Smiod     }
11773d8817e4Smiod 
11783d8817e4Smiod   size = buf.st_size;
11793d8817e4Smiod   if (size < 0)
11803d8817e4Smiod     {
11813d8817e4Smiod       non_fatal (_("stat returns negative size for `%s'"),
11823d8817e4Smiod 		 bfd_get_archive_filename (ibfd));
11833d8817e4Smiod       return FALSE;
11843d8817e4Smiod     }
11853d8817e4Smiod 
11863d8817e4Smiod   if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0)
11873d8817e4Smiod     {
11883d8817e4Smiod       bfd_nonfatal (bfd_get_archive_filename (ibfd));
11893d8817e4Smiod       return FALSE;
11903d8817e4Smiod     }
11913d8817e4Smiod 
11923d8817e4Smiod   if (verbose)
11933d8817e4Smiod     printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
11943d8817e4Smiod 	    bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
11953d8817e4Smiod 
11963d8817e4Smiod   cbuf = xmalloc (BUFSIZE);
11973d8817e4Smiod   ncopied = 0;
11983d8817e4Smiod   while (ncopied < size)
11993d8817e4Smiod     {
12003d8817e4Smiod       tocopy = size - ncopied;
12013d8817e4Smiod       if (tocopy > BUFSIZE)
12023d8817e4Smiod 	tocopy = BUFSIZE;
12033d8817e4Smiod 
12043d8817e4Smiod       if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
12053d8817e4Smiod 	  != (bfd_size_type) tocopy)
12063d8817e4Smiod 	{
12073d8817e4Smiod 	  bfd_nonfatal (bfd_get_archive_filename (ibfd));
12083d8817e4Smiod 	  free (cbuf);
12093d8817e4Smiod 	  return FALSE;
12103d8817e4Smiod 	}
12113d8817e4Smiod 
12123d8817e4Smiod       if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
12133d8817e4Smiod 	  != (bfd_size_type) tocopy)
12143d8817e4Smiod 	{
12153d8817e4Smiod 	  bfd_nonfatal (bfd_get_filename (obfd));
12163d8817e4Smiod 	  free (cbuf);
12173d8817e4Smiod 	  return FALSE;
12183d8817e4Smiod 	}
12193d8817e4Smiod 
12203d8817e4Smiod       ncopied += tocopy;
12213d8817e4Smiod     }
12223d8817e4Smiod 
12230153a938Sderaadt   chmod (bfd_get_filename (obfd), buf.st_mode & 0777);
12243d8817e4Smiod   free (cbuf);
12253d8817e4Smiod   return TRUE;
12263d8817e4Smiod }
12273d8817e4Smiod 
12283d8817e4Smiod /* Copy object file IBFD onto OBFD.
12293d8817e4Smiod    Returns TRUE upon success, FALSE otherwise.  */
12303d8817e4Smiod 
12313d8817e4Smiod static bfd_boolean
copy_object(bfd * ibfd,bfd * obfd)12323d8817e4Smiod copy_object (bfd *ibfd, bfd *obfd)
12333d8817e4Smiod {
12343d8817e4Smiod   bfd_vma start;
12353d8817e4Smiod   long symcount;
12363d8817e4Smiod   asection **osections = NULL;
12373d8817e4Smiod   asection *gnu_debuglink_section = NULL;
12383d8817e4Smiod   bfd_size_type *gaps = NULL;
12393d8817e4Smiod   bfd_size_type max_gap = 0;
12403d8817e4Smiod   long symsize;
12413d8817e4Smiod   void *dhandle;
12423d8817e4Smiod   enum bfd_architecture iarch;
12433d8817e4Smiod   unsigned int imach;
12443d8817e4Smiod 
12453d8817e4Smiod   if (ibfd->xvec->byteorder != obfd->xvec->byteorder
12463d8817e4Smiod       && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
12473d8817e4Smiod       && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
12483d8817e4Smiod     fatal (_("Unable to change endianness of input file(s)"));
12493d8817e4Smiod 
12503d8817e4Smiod   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
12513d8817e4Smiod     {
12523d8817e4Smiod       bfd_nonfatal (bfd_get_filename (obfd));
12533d8817e4Smiod       return FALSE;
12543d8817e4Smiod     }
12553d8817e4Smiod 
12563d8817e4Smiod   if (verbose)
12573d8817e4Smiod     printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
12583d8817e4Smiod 	    bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
12593d8817e4Smiod 	    bfd_get_filename (obfd), bfd_get_target (obfd));
12603d8817e4Smiod 
12613d8817e4Smiod   if (set_start_set)
12623d8817e4Smiod     start = set_start;
12633d8817e4Smiod   else
12643d8817e4Smiod     start = bfd_get_start_address (ibfd);
12653d8817e4Smiod   start += change_start;
12663d8817e4Smiod 
12673d8817e4Smiod   /* Neither the start address nor the flags
12683d8817e4Smiod      need to be set for a core file.  */
12693d8817e4Smiod   if (bfd_get_format (obfd) != bfd_core)
12703d8817e4Smiod     {
12713d8817e4Smiod       flagword flags;
12723d8817e4Smiod 
12733d8817e4Smiod       flags = bfd_get_file_flags (ibfd);
12743d8817e4Smiod       flags |= bfd_flags_to_set;
12753d8817e4Smiod       flags &= ~bfd_flags_to_clear;
12763d8817e4Smiod       flags &= bfd_applicable_file_flags (obfd);
12773d8817e4Smiod 
12783d8817e4Smiod       if (!bfd_set_start_address (obfd, start)
12793d8817e4Smiod 	  || !bfd_set_file_flags (obfd, flags))
12803d8817e4Smiod 	{
12813d8817e4Smiod 	  bfd_nonfatal (bfd_get_archive_filename (ibfd));
12823d8817e4Smiod 	  return FALSE;
12833d8817e4Smiod 	}
12843d8817e4Smiod     }
12853d8817e4Smiod 
12863d8817e4Smiod   /* Copy architecture of input file to output file.  */
12873d8817e4Smiod   iarch = bfd_get_arch (ibfd);
12883d8817e4Smiod   imach = bfd_get_mach (ibfd);
12893d8817e4Smiod   if (!bfd_set_arch_mach (obfd, iarch, imach)
12903d8817e4Smiod       && (ibfd->target_defaulted
12913d8817e4Smiod 	  || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
12923d8817e4Smiod     {
12933d8817e4Smiod       if (bfd_get_arch (ibfd) == bfd_arch_unknown)
12943d8817e4Smiod 	non_fatal (_("Unable to recognise the format of the input file `%s'"),
12953d8817e4Smiod 		   bfd_get_archive_filename (ibfd));
12963d8817e4Smiod       else
12973d8817e4Smiod 	non_fatal (_("Warning: Output file cannot represent architecture `%s'"),
12983d8817e4Smiod 		   bfd_printable_arch_mach (bfd_get_arch (ibfd),
12993d8817e4Smiod 					    bfd_get_mach (ibfd)));
13003d8817e4Smiod       return FALSE;
13013d8817e4Smiod     }
13023d8817e4Smiod 
13033d8817e4Smiod   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
13043d8817e4Smiod     {
13053d8817e4Smiod       bfd_nonfatal (bfd_get_archive_filename (ibfd));
13063d8817e4Smiod       return FALSE;
13073d8817e4Smiod     }
13083d8817e4Smiod 
13093d8817e4Smiod   if (isympp)
13103d8817e4Smiod     free (isympp);
13113d8817e4Smiod 
13123d8817e4Smiod   if (osympp != isympp)
13133d8817e4Smiod     free (osympp);
13143d8817e4Smiod 
13153d8817e4Smiod   isympp = NULL;
13163d8817e4Smiod   osympp = NULL;
13173d8817e4Smiod 
13183d8817e4Smiod   /* BFD mandates that all output sections be created and sizes set before
13193d8817e4Smiod      any output is done.  Thus, we traverse all sections multiple times.  */
13203d8817e4Smiod   bfd_map_over_sections (ibfd, setup_section, obfd);
13213d8817e4Smiod 
13223d8817e4Smiod   setup_bfd_headers (ibfd, obfd);
13233d8817e4Smiod 
13243d8817e4Smiod   if (add_sections != NULL)
13253d8817e4Smiod     {
13263d8817e4Smiod       struct section_add *padd;
13273d8817e4Smiod       struct section_list *pset;
13283d8817e4Smiod 
13293d8817e4Smiod       for (padd = add_sections; padd != NULL; padd = padd->next)
13303d8817e4Smiod 	{
13313d8817e4Smiod 	  flagword flags;
13323d8817e4Smiod 
13333d8817e4Smiod 	  pset = find_section_list (padd->name, FALSE);
13343d8817e4Smiod 	  if (pset != NULL)
13353d8817e4Smiod 	    pset->used = TRUE;
13363d8817e4Smiod 
13373d8817e4Smiod 	  flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
13383d8817e4Smiod 	  if (pset != NULL && pset->set_flags)
13393d8817e4Smiod 	    flags = pset->flags | SEC_HAS_CONTENTS;
13403d8817e4Smiod 
13413d8817e4Smiod 	  /* bfd_make_section_with_flags() does not return very helpful
13423d8817e4Smiod 	     error codes, so check for the most likely user error first.  */
13433d8817e4Smiod 	  if (bfd_get_section_by_name (obfd, padd->name))
13443d8817e4Smiod 	    {
13453d8817e4Smiod 	      non_fatal (_("can't add section '%s' - it already exists!"), padd->name);
13463d8817e4Smiod 	      return FALSE;
13473d8817e4Smiod 	    }
13483d8817e4Smiod 	  else
13493d8817e4Smiod 	    {
13503d8817e4Smiod 	      padd->section = bfd_make_section_with_flags (obfd, padd->name, flags);
13513d8817e4Smiod 	      if (padd->section == NULL)
13523d8817e4Smiod 		{
13533d8817e4Smiod 		  non_fatal (_("can't create section `%s': %s"),
13543d8817e4Smiod 			     padd->name, bfd_errmsg (bfd_get_error ()));
13553d8817e4Smiod 		  return FALSE;
13563d8817e4Smiod 		}
13573d8817e4Smiod 	    }
13583d8817e4Smiod 
13593d8817e4Smiod 	  if (! bfd_set_section_size (obfd, padd->section, padd->size))
13603d8817e4Smiod 	    {
13613d8817e4Smiod 	      bfd_nonfatal (bfd_get_filename (obfd));
13623d8817e4Smiod 	      return FALSE;
13633d8817e4Smiod 	    }
13643d8817e4Smiod 
13653d8817e4Smiod 	  if (pset != NULL)
13663d8817e4Smiod 	    {
13673d8817e4Smiod 	      if (pset->change_vma != CHANGE_IGNORE)
13683d8817e4Smiod 		if (! bfd_set_section_vma (obfd, padd->section,
13693d8817e4Smiod 					   pset->vma_val))
13703d8817e4Smiod 		  {
13713d8817e4Smiod 		    bfd_nonfatal (bfd_get_filename (obfd));
13723d8817e4Smiod 		    return FALSE;
13733d8817e4Smiod 		  }
13743d8817e4Smiod 
13753d8817e4Smiod 	      if (pset->change_lma != CHANGE_IGNORE)
13763d8817e4Smiod 		{
13773d8817e4Smiod 		  padd->section->lma = pset->lma_val;
13783d8817e4Smiod 
13793d8817e4Smiod 		  if (! bfd_set_section_alignment
13803d8817e4Smiod 		      (obfd, padd->section,
13813d8817e4Smiod 		       bfd_section_alignment (obfd, padd->section)))
13823d8817e4Smiod 		    {
13833d8817e4Smiod 		      bfd_nonfatal (bfd_get_filename (obfd));
13843d8817e4Smiod 		      return FALSE;
13853d8817e4Smiod 		    }
13863d8817e4Smiod 		}
13873d8817e4Smiod 	    }
13883d8817e4Smiod 	}
13893d8817e4Smiod     }
13903d8817e4Smiod 
13913d8817e4Smiod   if (gnu_debuglink_filename != NULL)
13923d8817e4Smiod     {
13933d8817e4Smiod       gnu_debuglink_section = bfd_create_gnu_debuglink_section
13943d8817e4Smiod 	(obfd, gnu_debuglink_filename);
13953d8817e4Smiod 
13963d8817e4Smiod       if (gnu_debuglink_section == NULL)
13973d8817e4Smiod 	{
13983d8817e4Smiod 	  bfd_nonfatal (gnu_debuglink_filename);
13993d8817e4Smiod 	  return FALSE;
14003d8817e4Smiod 	}
14013d8817e4Smiod 
14023d8817e4Smiod       /* Special processing for PE format files.  We
14033d8817e4Smiod 	 have no way to distinguish PE from COFF here.  */
14043d8817e4Smiod       if (bfd_get_flavour (obfd) == bfd_target_coff_flavour)
14053d8817e4Smiod 	{
14063d8817e4Smiod 	  bfd_vma debuglink_vma;
14073d8817e4Smiod 	  asection * highest_section;
14083d8817e4Smiod 	  asection * sec;
14093d8817e4Smiod 
14103d8817e4Smiod 	  /* The PE spec requires that all sections be adjacent and sorted
14113d8817e4Smiod 	     in ascending order of VMA.  It also specifies that debug
14123d8817e4Smiod 	     sections should be last.  This is despite the fact that debug
14133d8817e4Smiod 	     sections are not loaded into memory and so in theory have no
14143d8817e4Smiod 	     use for a VMA.
14153d8817e4Smiod 
14163d8817e4Smiod 	     This means that the debuglink section must be given a non-zero
14173d8817e4Smiod 	     VMA which makes it contiguous with other debug sections.  So
14183d8817e4Smiod 	     walk the current section list, find the section with the
14193d8817e4Smiod 	     highest VMA and start the debuglink section after that one.  */
14203d8817e4Smiod 	  for (sec = obfd->sections, highest_section = NULL;
14213d8817e4Smiod 	       sec != NULL;
14223d8817e4Smiod 	       sec = sec->next)
14233d8817e4Smiod 	    if (sec->vma > 0
14243d8817e4Smiod 		&& (highest_section == NULL
14253d8817e4Smiod 		    || sec->vma > highest_section->vma))
14263d8817e4Smiod 	      highest_section = sec;
14273d8817e4Smiod 
14283d8817e4Smiod 	  if (highest_section)
14293d8817e4Smiod 	    debuglink_vma = BFD_ALIGN (highest_section->vma
14303d8817e4Smiod 				       + highest_section->size,
14313d8817e4Smiod 				       /* FIXME: We ought to be using
14323d8817e4Smiod 					  COFF_PAGE_SIZE here or maybe
14333d8817e4Smiod 					  bfd_get_section_alignment() (if it
14343d8817e4Smiod 					  was set) but since this is for PE
14353d8817e4Smiod 					  and we know the required alignment
14363d8817e4Smiod 					  it is easier just to hard code it.  */
14373d8817e4Smiod 				       0x1000);
14383d8817e4Smiod 	  else
14393d8817e4Smiod 	    /* Umm, not sure what to do in this case.  */
14403d8817e4Smiod 	    debuglink_vma = 0x1000;
14413d8817e4Smiod 
14423d8817e4Smiod 	  bfd_set_section_vma (obfd, gnu_debuglink_section, debuglink_vma);
14433d8817e4Smiod 	}
14443d8817e4Smiod     }
14453d8817e4Smiod 
14463d8817e4Smiod   if (bfd_count_sections (obfd) == 0)
14473d8817e4Smiod     {
14483d8817e4Smiod       non_fatal (_("there are no sections to be copied!"));
14493d8817e4Smiod       return FALSE;
14503d8817e4Smiod     }
14513d8817e4Smiod 
14523d8817e4Smiod   if (gap_fill_set || pad_to_set)
14533d8817e4Smiod     {
14543d8817e4Smiod       asection **set;
14553d8817e4Smiod       unsigned int c, i;
14563d8817e4Smiod 
14573d8817e4Smiod       /* We must fill in gaps between the sections and/or we must pad
14583d8817e4Smiod 	 the last section to a specified address.  We do this by
14593d8817e4Smiod 	 grabbing a list of the sections, sorting them by VMA, and
14603d8817e4Smiod 	 increasing the section sizes as required to fill the gaps.
14613d8817e4Smiod 	 We write out the gap contents below.  */
14623d8817e4Smiod 
14633d8817e4Smiod       c = bfd_count_sections (obfd);
14643d8817e4Smiod       osections = xmalloc (c * sizeof (asection *));
14653d8817e4Smiod       set = osections;
14663d8817e4Smiod       bfd_map_over_sections (obfd, get_sections, &set);
14673d8817e4Smiod 
14683d8817e4Smiod       qsort (osections, c, sizeof (asection *), compare_section_lma);
14693d8817e4Smiod 
14703d8817e4Smiod       gaps = xmalloc (c * sizeof (bfd_size_type));
14713d8817e4Smiod       memset (gaps, 0, c * sizeof (bfd_size_type));
14723d8817e4Smiod 
14733d8817e4Smiod       if (gap_fill_set)
14743d8817e4Smiod 	{
14753d8817e4Smiod 	  for (i = 0; i < c - 1; i++)
14763d8817e4Smiod 	    {
14773d8817e4Smiod 	      flagword flags;
14783d8817e4Smiod 	      bfd_size_type size;
14793d8817e4Smiod 	      bfd_vma gap_start, gap_stop;
14803d8817e4Smiod 
14813d8817e4Smiod 	      flags = bfd_get_section_flags (obfd, osections[i]);
14823d8817e4Smiod 	      if ((flags & SEC_HAS_CONTENTS) == 0
14833d8817e4Smiod 		  || (flags & SEC_LOAD) == 0)
14843d8817e4Smiod 		continue;
14853d8817e4Smiod 
14863d8817e4Smiod 	      size = bfd_section_size (obfd, osections[i]);
14873d8817e4Smiod 	      gap_start = bfd_section_lma (obfd, osections[i]) + size;
14883d8817e4Smiod 	      gap_stop = bfd_section_lma (obfd, osections[i + 1]);
14893d8817e4Smiod 	      if (gap_start < gap_stop)
14903d8817e4Smiod 		{
14913d8817e4Smiod 		  if (! bfd_set_section_size (obfd, osections[i],
14923d8817e4Smiod 					      size + (gap_stop - gap_start)))
14933d8817e4Smiod 		    {
14943d8817e4Smiod 		      non_fatal (_("Can't fill gap after %s: %s"),
14953d8817e4Smiod 				 bfd_get_section_name (obfd, osections[i]),
14963d8817e4Smiod 				 bfd_errmsg (bfd_get_error ()));
14973d8817e4Smiod 		      status = 1;
14983d8817e4Smiod 		      break;
14993d8817e4Smiod 		    }
15003d8817e4Smiod 		  gaps[i] = gap_stop - gap_start;
15013d8817e4Smiod 		  if (max_gap < gap_stop - gap_start)
15023d8817e4Smiod 		    max_gap = gap_stop - gap_start;
15033d8817e4Smiod 		}
15043d8817e4Smiod 	    }
15053d8817e4Smiod 	}
15063d8817e4Smiod 
15073d8817e4Smiod       if (pad_to_set)
15083d8817e4Smiod 	{
15093d8817e4Smiod 	  bfd_vma lma;
15103d8817e4Smiod 	  bfd_size_type size;
15113d8817e4Smiod 
15123d8817e4Smiod 	  lma = bfd_section_lma (obfd, osections[c - 1]);
15133d8817e4Smiod 	  size = bfd_section_size (obfd, osections[c - 1]);
15143d8817e4Smiod 	  if (lma + size < pad_to)
15153d8817e4Smiod 	    {
15163d8817e4Smiod 	      if (! bfd_set_section_size (obfd, osections[c - 1],
15173d8817e4Smiod 					  pad_to - lma))
15183d8817e4Smiod 		{
15193d8817e4Smiod 		  non_fatal (_("Can't add padding to %s: %s"),
15203d8817e4Smiod 			     bfd_get_section_name (obfd, osections[c - 1]),
15213d8817e4Smiod 			     bfd_errmsg (bfd_get_error ()));
15223d8817e4Smiod 		  status = 1;
15233d8817e4Smiod 		}
15243d8817e4Smiod 	      else
15253d8817e4Smiod 		{
15263d8817e4Smiod 		  gaps[c - 1] = pad_to - (lma + size);
15273d8817e4Smiod 		  if (max_gap < pad_to - (lma + size))
15283d8817e4Smiod 		    max_gap = pad_to - (lma + size);
15293d8817e4Smiod 		}
15303d8817e4Smiod 	    }
15313d8817e4Smiod 	}
15323d8817e4Smiod     }
15333d8817e4Smiod 
15343d8817e4Smiod   /* Symbol filtering must happen after the output sections
15353d8817e4Smiod      have been created, but before their contents are set.  */
15363d8817e4Smiod   dhandle = NULL;
15373d8817e4Smiod   symsize = bfd_get_symtab_upper_bound (ibfd);
15383d8817e4Smiod   if (symsize < 0)
15393d8817e4Smiod     {
15403d8817e4Smiod       bfd_nonfatal (bfd_get_archive_filename (ibfd));
15413d8817e4Smiod       return FALSE;
15423d8817e4Smiod     }
15433d8817e4Smiod 
15443d8817e4Smiod   osympp = isympp = xmalloc (symsize);
15453d8817e4Smiod   symcount = bfd_canonicalize_symtab (ibfd, isympp);
15463d8817e4Smiod   if (symcount < 0)
15473d8817e4Smiod     {
15483d8817e4Smiod       bfd_nonfatal (bfd_get_filename (ibfd));
15493d8817e4Smiod       return FALSE;
15503d8817e4Smiod     }
15513d8817e4Smiod 
15523d8817e4Smiod   if (convert_debugging)
15533d8817e4Smiod     dhandle = read_debugging_info (ibfd, isympp, symcount);
15543d8817e4Smiod 
15553d8817e4Smiod   if (strip_symbols == STRIP_DEBUG
15563d8817e4Smiod       || strip_symbols == STRIP_ALL
15573d8817e4Smiod       || strip_symbols == STRIP_UNNEEDED
15583d8817e4Smiod       || strip_symbols == STRIP_NONDEBUG
15593d8817e4Smiod       || discard_locals != LOCALS_UNDEF
1560c065f989Skettenis       || localize_hidden
15613d8817e4Smiod       || strip_specific_list != NULL
15623d8817e4Smiod       || keep_specific_list != NULL
15633d8817e4Smiod       || localize_specific_list != NULL
15643d8817e4Smiod       || globalize_specific_list != NULL
15653d8817e4Smiod       || keepglobal_specific_list != NULL
15663d8817e4Smiod       || weaken_specific_list != NULL
15673d8817e4Smiod       || prefix_symbols_string
15683d8817e4Smiod       || sections_removed
15693d8817e4Smiod       || sections_copied
15703d8817e4Smiod       || convert_debugging
15713d8817e4Smiod       || change_leading_char
15723d8817e4Smiod       || remove_leading_char
15733d8817e4Smiod       || redefine_sym_list
15743d8817e4Smiod       || weaken)
15753d8817e4Smiod     {
15763d8817e4Smiod       /* Mark symbols used in output relocations so that they
15773d8817e4Smiod 	 are kept, even if they are local labels or static symbols.
15783d8817e4Smiod 
15793d8817e4Smiod 	 Note we iterate over the input sections examining their
15803d8817e4Smiod 	 relocations since the relocations for the output sections
15813d8817e4Smiod 	 haven't been set yet.  mark_symbols_used_in_relocations will
15823d8817e4Smiod 	 ignore input sections which have no corresponding output
15833d8817e4Smiod 	 section.  */
15843d8817e4Smiod       if (strip_symbols != STRIP_ALL)
15853d8817e4Smiod 	bfd_map_over_sections (ibfd,
15863d8817e4Smiod 			       mark_symbols_used_in_relocations,
15873d8817e4Smiod 			       isympp);
15883d8817e4Smiod       osympp = xmalloc ((symcount + 1) * sizeof (asymbol *));
15893d8817e4Smiod       symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
15903d8817e4Smiod     }
15913d8817e4Smiod 
15923d8817e4Smiod   if (convert_debugging && dhandle != NULL)
15933d8817e4Smiod     {
15943d8817e4Smiod       if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
15953d8817e4Smiod 	{
15963d8817e4Smiod 	  status = 1;
15973d8817e4Smiod 	  return FALSE;
15983d8817e4Smiod 	}
15993d8817e4Smiod     }
16003d8817e4Smiod 
16013d8817e4Smiod   bfd_set_symtab (obfd, osympp, symcount);
16023d8817e4Smiod 
16033d8817e4Smiod   /* This has to happen after the symbol table has been set.  */
16043d8817e4Smiod   bfd_map_over_sections (ibfd, copy_section, obfd);
16053d8817e4Smiod 
16063d8817e4Smiod   if (add_sections != NULL)
16073d8817e4Smiod     {
16083d8817e4Smiod       struct section_add *padd;
16093d8817e4Smiod 
16103d8817e4Smiod       for (padd = add_sections; padd != NULL; padd = padd->next)
16113d8817e4Smiod 	{
16123d8817e4Smiod 	  if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
16133d8817e4Smiod 					  0, padd->size))
16143d8817e4Smiod 	    {
16153d8817e4Smiod 	      bfd_nonfatal (bfd_get_filename (obfd));
16163d8817e4Smiod 	      return FALSE;
16173d8817e4Smiod 	    }
16183d8817e4Smiod 	}
16193d8817e4Smiod     }
16203d8817e4Smiod 
16213d8817e4Smiod   if (gnu_debuglink_filename != NULL)
16223d8817e4Smiod     {
16233d8817e4Smiod       if (! bfd_fill_in_gnu_debuglink_section
16243d8817e4Smiod 	  (obfd, gnu_debuglink_section, gnu_debuglink_filename))
16253d8817e4Smiod 	{
16263d8817e4Smiod 	  bfd_nonfatal (gnu_debuglink_filename);
16273d8817e4Smiod 	  return FALSE;
16283d8817e4Smiod 	}
16293d8817e4Smiod     }
16303d8817e4Smiod 
16313d8817e4Smiod   if (gap_fill_set || pad_to_set)
16323d8817e4Smiod     {
16333d8817e4Smiod       bfd_byte *buf;
16343d8817e4Smiod       int c, i;
16353d8817e4Smiod 
16363d8817e4Smiod       /* Fill in the gaps.  */
16373d8817e4Smiod       if (max_gap > 8192)
16383d8817e4Smiod 	max_gap = 8192;
16393d8817e4Smiod       buf = xmalloc (max_gap);
16403d8817e4Smiod       memset (buf, gap_fill, max_gap);
16413d8817e4Smiod 
16423d8817e4Smiod       c = bfd_count_sections (obfd);
16433d8817e4Smiod       for (i = 0; i < c; i++)
16443d8817e4Smiod 	{
16453d8817e4Smiod 	  if (gaps[i] != 0)
16463d8817e4Smiod 	    {
16473d8817e4Smiod 	      bfd_size_type left;
16483d8817e4Smiod 	      file_ptr off;
16493d8817e4Smiod 
16503d8817e4Smiod 	      left = gaps[i];
16513d8817e4Smiod 	      off = bfd_section_size (obfd, osections[i]) - left;
16523d8817e4Smiod 
16533d8817e4Smiod 	      while (left > 0)
16543d8817e4Smiod 		{
16553d8817e4Smiod 		  bfd_size_type now;
16563d8817e4Smiod 
16573d8817e4Smiod 		  if (left > 8192)
16583d8817e4Smiod 		    now = 8192;
16593d8817e4Smiod 		  else
16603d8817e4Smiod 		    now = left;
16613d8817e4Smiod 
16623d8817e4Smiod 		  if (! bfd_set_section_contents (obfd, osections[i], buf,
16633d8817e4Smiod 						  off, now))
16643d8817e4Smiod 		    {
16653d8817e4Smiod 		      bfd_nonfatal (bfd_get_filename (obfd));
16663d8817e4Smiod 		      return FALSE;
16673d8817e4Smiod 		    }
16683d8817e4Smiod 
16693d8817e4Smiod 		  left -= now;
16703d8817e4Smiod 		  off += now;
16713d8817e4Smiod 		}
16723d8817e4Smiod 	    }
16733d8817e4Smiod 	}
16743d8817e4Smiod     }
16753d8817e4Smiod 
16763d8817e4Smiod   /* Allow the BFD backend to copy any private data it understands
16773d8817e4Smiod      from the input BFD to the output BFD.  This is done last to
16783d8817e4Smiod      permit the routine to look at the filtered symbol table, which is
16793d8817e4Smiod      important for the ECOFF code at least.  */
16803d8817e4Smiod   if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
16813d8817e4Smiod       && strip_symbols == STRIP_NONDEBUG)
16823d8817e4Smiod     /* Do not copy the private data when creating an ELF format
16833d8817e4Smiod        debug info file.  We do not want the program headers.  */
16843d8817e4Smiod     ;
16853d8817e4Smiod   else if (! bfd_copy_private_bfd_data (ibfd, obfd))
16863d8817e4Smiod     {
16873d8817e4Smiod       non_fatal (_("%s: error copying private BFD data: %s"),
16883d8817e4Smiod 		 bfd_get_filename (obfd),
16893d8817e4Smiod 		 bfd_errmsg (bfd_get_error ()));
16903d8817e4Smiod       return FALSE;
16913d8817e4Smiod     }
16923d8817e4Smiod 
16933d8817e4Smiod   /* Switch to the alternate machine code.  We have to do this at the
16943d8817e4Smiod      very end, because we only initialize the header when we create
16953d8817e4Smiod      the first section.  */
16963d8817e4Smiod   if (use_alt_mach_code != 0)
16973d8817e4Smiod     {
16983d8817e4Smiod       if (! bfd_alt_mach_code (obfd, use_alt_mach_code))
16993d8817e4Smiod 	{
17003d8817e4Smiod 	  non_fatal (_("this target does not support %lu alternative machine codes"),
17013d8817e4Smiod 		     use_alt_mach_code);
17023d8817e4Smiod 	  if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
17033d8817e4Smiod 	    {
17043d8817e4Smiod 	      non_fatal (_("treating that number as an absolute e_machine value instead"));
17053d8817e4Smiod 	      elf_elfheader (obfd)->e_machine = use_alt_mach_code;
17063d8817e4Smiod 	    }
17073d8817e4Smiod 	  else
17083d8817e4Smiod 	    non_fatal (_("ignoring the alternative value"));
17093d8817e4Smiod 	}
17103d8817e4Smiod     }
17113d8817e4Smiod 
17123d8817e4Smiod   return TRUE;
17133d8817e4Smiod }
17143d8817e4Smiod 
17153d8817e4Smiod /* Read each archive element in turn from IBFD, copy the
17163d8817e4Smiod    contents to temp file, and keep the temp file handle.  */
17173d8817e4Smiod 
17183d8817e4Smiod static void
copy_archive(bfd * ibfd,bfd * obfd,const char * output_target)17193d8817e4Smiod copy_archive (bfd *ibfd, bfd *obfd, const char *output_target)
17203d8817e4Smiod {
17213d8817e4Smiod   struct name_list
17223d8817e4Smiod     {
17233d8817e4Smiod       struct name_list *next;
17243d8817e4Smiod       const char *name;
17253d8817e4Smiod       bfd *obfd;
17263d8817e4Smiod     } *list, *l;
17273d8817e4Smiod   bfd **ptr = &obfd->archive_head;
17283d8817e4Smiod   bfd *this_element;
1729d2386abeSmiod   char *dir = make_tempname (bfd_get_filename (obfd), 1);
17303d8817e4Smiod 
17313d8817e4Smiod   /* Make a temp directory to hold the contents.  */
1732d2386abeSmiod   if (dir == (char *) NULL)
1733d2386abeSmiod     fatal (_("cannot make temp directory for archive copying (error: %s)"),
1734d2386abeSmiod 	   strerror (errno));
17353d8817e4Smiod 
17363d8817e4Smiod   obfd->has_armap = ibfd->has_armap;
17373d8817e4Smiod 
17383d8817e4Smiod   list = NULL;
17393d8817e4Smiod 
17403d8817e4Smiod   this_element = bfd_openr_next_archived_file (ibfd, NULL);
17413d8817e4Smiod 
17423d8817e4Smiod   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
17433d8817e4Smiod     RETURN_NONFATAL (bfd_get_filename (obfd));
17443d8817e4Smiod 
17453d8817e4Smiod   while (!status && this_element != NULL)
17463d8817e4Smiod     {
17473d8817e4Smiod       char *output_name;
17483d8817e4Smiod       bfd *output_bfd;
17493d8817e4Smiod       bfd *last_element;
17503d8817e4Smiod       struct stat buf;
17513d8817e4Smiod       int stat_status = 0;
17523d8817e4Smiod       bfd_boolean delete = TRUE;
17533d8817e4Smiod 
17543d8817e4Smiod       /* Create an output file for this member.  */
17553d8817e4Smiod       output_name = concat (dir, "/",
17563d8817e4Smiod 			    bfd_get_filename (this_element), (char *) 0);
17573d8817e4Smiod 
17583d8817e4Smiod       /* If the file already exists, make another temp dir.  */
17593d8817e4Smiod       if (stat (output_name, &buf) >= 0)
17603d8817e4Smiod 	{
1761d2386abeSmiod 	  output_name = make_tempname (output_name, 1);
1762d2386abeSmiod 	  if (output_name == (char *) NULL)
1763d2386abeSmiod 	    fatal (_("cannot make temp directory for archive copying (error: %s)"),
1764d2386abeSmiod 		   strerror (errno));
17653d8817e4Smiod 
17663d8817e4Smiod 	  l = xmalloc (sizeof (struct name_list));
17673d8817e4Smiod 	  l->name = output_name;
17683d8817e4Smiod 	  l->next = list;
17693d8817e4Smiod 	  l->obfd = NULL;
17703d8817e4Smiod 	  list = l;
17713d8817e4Smiod 	  output_name = concat (output_name, "/",
17723d8817e4Smiod 				bfd_get_filename (this_element), (char *) 0);
17733d8817e4Smiod 	}
17743d8817e4Smiod 
17753d8817e4Smiod       output_bfd = bfd_openw (output_name, output_target);
17763d8817e4Smiod       if (preserve_dates)
17773d8817e4Smiod 	{
17783d8817e4Smiod 	  stat_status = bfd_stat_arch_elt (this_element, &buf);
17793d8817e4Smiod 
17803d8817e4Smiod 	  if (stat_status != 0)
17813d8817e4Smiod 	    non_fatal (_("internal stat error on %s"),
17823d8817e4Smiod 		       bfd_get_filename (this_element));
17833d8817e4Smiod 	}
17843d8817e4Smiod 
17853d8817e4Smiod       l = xmalloc (sizeof (struct name_list));
17863d8817e4Smiod       l->name = output_name;
17873d8817e4Smiod       l->next = list;
17883d8817e4Smiod       l->obfd = NULL;
17893d8817e4Smiod       list = l;
17903d8817e4Smiod 
17913d8817e4Smiod       if (output_bfd == NULL)
17923d8817e4Smiod 	RETURN_NONFATAL (output_name);
17933d8817e4Smiod 
17943d8817e4Smiod       if (bfd_check_format (this_element, bfd_object))
17953d8817e4Smiod 	{
17963d8817e4Smiod 	  delete = ! copy_object (this_element, output_bfd);
17973d8817e4Smiod 
17983d8817e4Smiod 	  if (! delete
17993d8817e4Smiod 	      || bfd_get_arch (this_element) != bfd_arch_unknown)
18003d8817e4Smiod 	    {
18013d8817e4Smiod 	      if (!bfd_close (output_bfd))
18023d8817e4Smiod 		{
18033d8817e4Smiod 		  bfd_nonfatal (bfd_get_filename (output_bfd));
18043d8817e4Smiod 		  /* Error in new object file. Don't change archive.  */
18053d8817e4Smiod 		  status = 1;
18063d8817e4Smiod 		}
18073d8817e4Smiod 	    }
18083d8817e4Smiod 	  else
18093d8817e4Smiod 	    goto copy_unknown_element;
18103d8817e4Smiod 	}
18113d8817e4Smiod       else
18123d8817e4Smiod 	{
18133d8817e4Smiod 	  non_fatal (_("Unable to recognise the format of the input file `%s'"),
18143d8817e4Smiod 		     bfd_get_archive_filename (this_element));
18153d8817e4Smiod 
18163d8817e4Smiod copy_unknown_element:
18173d8817e4Smiod 	  delete = !copy_unknown_object (this_element, output_bfd);
18183d8817e4Smiod 	  if (!bfd_close_all_done (output_bfd))
18193d8817e4Smiod 	    {
18203d8817e4Smiod 	      bfd_nonfatal (bfd_get_filename (output_bfd));
18213d8817e4Smiod 	      /* Error in new object file. Don't change archive.  */
18223d8817e4Smiod 	      status = 1;
18233d8817e4Smiod 	    }
18243d8817e4Smiod 	}
18253d8817e4Smiod 
18263d8817e4Smiod       if (delete)
18273d8817e4Smiod 	{
18283d8817e4Smiod 	  unlink (output_name);
18293d8817e4Smiod 	  status = 1;
18303d8817e4Smiod 	}
18313d8817e4Smiod       else
18323d8817e4Smiod 	{
18333d8817e4Smiod 	  if (preserve_dates && stat_status == 0)
18343d8817e4Smiod 	    set_times (output_name, &buf);
18353d8817e4Smiod 
18363d8817e4Smiod 	  /* Open the newly output file and attach to our list.  */
18373d8817e4Smiod 	  output_bfd = bfd_openr (output_name, output_target);
18383d8817e4Smiod 
18393d8817e4Smiod 	  l->obfd = output_bfd;
18403d8817e4Smiod 
18413d8817e4Smiod 	  *ptr = output_bfd;
18423d8817e4Smiod 	  ptr = &output_bfd->next;
18433d8817e4Smiod 
18443d8817e4Smiod 	  last_element = this_element;
18453d8817e4Smiod 
18463d8817e4Smiod 	  this_element = bfd_openr_next_archived_file (ibfd, last_element);
18473d8817e4Smiod 
18483d8817e4Smiod 	  bfd_close (last_element);
18493d8817e4Smiod 	}
18503d8817e4Smiod     }
18513d8817e4Smiod   *ptr = NULL;
18523d8817e4Smiod 
18533d8817e4Smiod   if (!bfd_close (obfd))
18543d8817e4Smiod     RETURN_NONFATAL (bfd_get_filename (obfd));
18553d8817e4Smiod 
18563d8817e4Smiod   if (!bfd_close (ibfd))
18573d8817e4Smiod     RETURN_NONFATAL (bfd_get_filename (ibfd));
18583d8817e4Smiod 
18593d8817e4Smiod   /* Delete all the files that we opened.  */
18603d8817e4Smiod   for (l = list; l != NULL; l = l->next)
18613d8817e4Smiod     {
18623d8817e4Smiod       if (l->obfd == NULL)
18633d8817e4Smiod 	rmdir (l->name);
18643d8817e4Smiod       else
18653d8817e4Smiod 	{
18663d8817e4Smiod 	  bfd_close (l->obfd);
18673d8817e4Smiod 	  unlink (l->name);
18683d8817e4Smiod 	}
18693d8817e4Smiod     }
18703d8817e4Smiod   rmdir (dir);
18713d8817e4Smiod }
18723d8817e4Smiod 
18733d8817e4Smiod /* The top-level control.  */
18743d8817e4Smiod 
18753d8817e4Smiod static void
copy_file(const char * input_filename,const char * output_filename,const char * input_target,const char * output_target)18763d8817e4Smiod copy_file (const char *input_filename, const char *output_filename,
18773d8817e4Smiod 	   const char *input_target,   const char *output_target)
18783d8817e4Smiod {
18793d8817e4Smiod   bfd *ibfd;
18803d8817e4Smiod   char **obj_matching;
18813d8817e4Smiod   char **core_matching;
18823d8817e4Smiod 
18833d8817e4Smiod   if (get_file_size (input_filename) < 1)
18843d8817e4Smiod     {
18853d8817e4Smiod       non_fatal (_("error: the input file '%s' is empty"), input_filename);
18863d8817e4Smiod       status = 1;
18873d8817e4Smiod       return;
18883d8817e4Smiod     }
18893d8817e4Smiod 
18903d8817e4Smiod   /* To allow us to do "strip *" without dying on the first
18913d8817e4Smiod      non-object file, failures are nonfatal.  */
18923d8817e4Smiod   ibfd = bfd_openr (input_filename, input_target);
18933d8817e4Smiod   if (ibfd == NULL)
18943d8817e4Smiod     RETURN_NONFATAL (input_filename);
18953d8817e4Smiod 
18963d8817e4Smiod   if (bfd_check_format (ibfd, bfd_archive))
18973d8817e4Smiod     {
18983d8817e4Smiod       bfd *obfd;
18993d8817e4Smiod 
19003d8817e4Smiod       /* bfd_get_target does not return the correct value until
19013d8817e4Smiod          bfd_check_format succeeds.  */
19023d8817e4Smiod       if (output_target == NULL)
19033d8817e4Smiod 	output_target = bfd_get_target (ibfd);
19043d8817e4Smiod 
19053d8817e4Smiod       obfd = bfd_openw (output_filename, output_target);
19063d8817e4Smiod       if (obfd == NULL)
19073d8817e4Smiod 	RETURN_NONFATAL (output_filename);
19083d8817e4Smiod 
19093d8817e4Smiod       copy_archive (ibfd, obfd, output_target);
19103d8817e4Smiod     }
19113d8817e4Smiod   else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
19123d8817e4Smiod     {
19133d8817e4Smiod       bfd *obfd;
19143d8817e4Smiod     do_copy:
19153d8817e4Smiod 
19163d8817e4Smiod       /* bfd_get_target does not return the correct value until
19173d8817e4Smiod          bfd_check_format succeeds.  */
19183d8817e4Smiod       if (output_target == NULL)
19193d8817e4Smiod 	output_target = bfd_get_target (ibfd);
19203d8817e4Smiod 
19213d8817e4Smiod       obfd = bfd_openw (output_filename, output_target);
19223d8817e4Smiod       if (obfd == NULL)
19233d8817e4Smiod 	RETURN_NONFATAL (output_filename);
19243d8817e4Smiod 
19253d8817e4Smiod       if (! copy_object (ibfd, obfd))
19263d8817e4Smiod 	status = 1;
19273d8817e4Smiod 
19283d8817e4Smiod       if (!bfd_close (obfd))
19293d8817e4Smiod 	RETURN_NONFATAL (output_filename);
19303d8817e4Smiod 
19313d8817e4Smiod       if (!bfd_close (ibfd))
19323d8817e4Smiod 	RETURN_NONFATAL (input_filename);
19333d8817e4Smiod 
19343d8817e4Smiod     }
19353d8817e4Smiod   else
19363d8817e4Smiod     {
19373d8817e4Smiod       bfd_error_type obj_error = bfd_get_error ();
19383d8817e4Smiod       bfd_error_type core_error;
19393d8817e4Smiod 
19403d8817e4Smiod       if (bfd_check_format_matches (ibfd, bfd_core, &core_matching))
19413d8817e4Smiod 	{
19423d8817e4Smiod 	  /* This probably can't happen..  */
19433d8817e4Smiod 	  if (obj_error == bfd_error_file_ambiguously_recognized)
19443d8817e4Smiod 	    free (obj_matching);
19453d8817e4Smiod 	  goto do_copy;
19463d8817e4Smiod 	}
19473d8817e4Smiod 
19483d8817e4Smiod       core_error = bfd_get_error ();
19493d8817e4Smiod       /* Report the object error in preference to the core error.  */
19503d8817e4Smiod       if (obj_error != core_error)
19513d8817e4Smiod 	bfd_set_error (obj_error);
19523d8817e4Smiod 
19533d8817e4Smiod       bfd_nonfatal (input_filename);
19543d8817e4Smiod 
19553d8817e4Smiod       if (obj_error == bfd_error_file_ambiguously_recognized)
19563d8817e4Smiod 	{
19573d8817e4Smiod 	  list_matching_formats (obj_matching);
19583d8817e4Smiod 	  free (obj_matching);
19593d8817e4Smiod 	}
19603d8817e4Smiod       if (core_error == bfd_error_file_ambiguously_recognized)
19613d8817e4Smiod 	{
19623d8817e4Smiod 	  list_matching_formats (core_matching);
19633d8817e4Smiod 	  free (core_matching);
19643d8817e4Smiod 	}
19653d8817e4Smiod 
19663d8817e4Smiod       status = 1;
19673d8817e4Smiod     }
19683d8817e4Smiod }
19693d8817e4Smiod 
19703d8817e4Smiod /* Add a name to the section renaming list.  */
19713d8817e4Smiod 
19723d8817e4Smiod static void
add_section_rename(const char * old_name,const char * new_name,flagword flags)19733d8817e4Smiod add_section_rename (const char * old_name, const char * new_name,
19743d8817e4Smiod 		    flagword flags)
19753d8817e4Smiod {
19763d8817e4Smiod   section_rename * rename;
19773d8817e4Smiod 
19783d8817e4Smiod   /* Check for conflicts first.  */
19793d8817e4Smiod   for (rename = section_rename_list; rename != NULL; rename = rename->next)
19803d8817e4Smiod     if (strcmp (rename->old_name, old_name) == 0)
19813d8817e4Smiod       {
19823d8817e4Smiod 	/* Silently ignore duplicate definitions.  */
19833d8817e4Smiod 	if (strcmp (rename->new_name, new_name) == 0
19843d8817e4Smiod 	    && rename->flags == flags)
19853d8817e4Smiod 	  return;
19863d8817e4Smiod 
19873d8817e4Smiod 	fatal (_("Multiple renames of section %s"), old_name);
19883d8817e4Smiod       }
19893d8817e4Smiod 
19903d8817e4Smiod   rename = xmalloc (sizeof (* rename));
19913d8817e4Smiod 
19923d8817e4Smiod   rename->old_name = old_name;
19933d8817e4Smiod   rename->new_name = new_name;
19943d8817e4Smiod   rename->flags    = flags;
19953d8817e4Smiod   rename->next     = section_rename_list;
19963d8817e4Smiod 
19973d8817e4Smiod   section_rename_list = rename;
19983d8817e4Smiod }
19993d8817e4Smiod 
20003d8817e4Smiod /* Check the section rename list for a new name of the input section
20013d8817e4Smiod    ISECTION.  Return the new name if one is found.
20023d8817e4Smiod    Also set RETURNED_FLAGS to the flags to be used for this section.  */
20033d8817e4Smiod 
20043d8817e4Smiod static const char *
find_section_rename(bfd * ibfd ATTRIBUTE_UNUSED,sec_ptr isection,flagword * returned_flags)20053d8817e4Smiod find_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection,
20063d8817e4Smiod 		     flagword * returned_flags)
20073d8817e4Smiod {
20083d8817e4Smiod   const char * old_name = bfd_section_name (ibfd, isection);
20093d8817e4Smiod   section_rename * rename;
20103d8817e4Smiod 
20113d8817e4Smiod   /* Default to using the flags of the input section.  */
20123d8817e4Smiod   * returned_flags = bfd_get_section_flags (ibfd, isection);
20133d8817e4Smiod 
20143d8817e4Smiod   for (rename = section_rename_list; rename != NULL; rename = rename->next)
20153d8817e4Smiod     if (strcmp (rename->old_name, old_name) == 0)
20163d8817e4Smiod       {
20173d8817e4Smiod 	if (rename->flags != (flagword) -1)
20183d8817e4Smiod 	  * returned_flags = rename->flags;
20193d8817e4Smiod 
20203d8817e4Smiod 	return rename->new_name;
20213d8817e4Smiod       }
20223d8817e4Smiod 
20233d8817e4Smiod   return old_name;
20243d8817e4Smiod }
20253d8817e4Smiod 
20263d8817e4Smiod /* Once each of the sections is copied, we may still need to do some
20273d8817e4Smiod    finalization work for private section headers.  Do that here.  */
20283d8817e4Smiod 
20293d8817e4Smiod static void
setup_bfd_headers(bfd * ibfd,bfd * obfd)20303d8817e4Smiod setup_bfd_headers (bfd *ibfd, bfd *obfd)
20313d8817e4Smiod {
20323d8817e4Smiod   const char *err;
20333d8817e4Smiod 
20343d8817e4Smiod   /* Allow the BFD backend to copy any private data it understands
20353d8817e4Smiod      from the input section to the output section.  */
20363d8817e4Smiod   if (! bfd_copy_private_header_data (ibfd, obfd))
20373d8817e4Smiod     {
20383d8817e4Smiod       err = _("private header data");
20393d8817e4Smiod       goto loser;
20403d8817e4Smiod     }
20413d8817e4Smiod 
20423d8817e4Smiod   /* All went well.  */
20433d8817e4Smiod   return;
20443d8817e4Smiod 
20453d8817e4Smiod loser:
20463d8817e4Smiod   non_fatal (_("%s: error in %s: %s"),
20473d8817e4Smiod 	     bfd_get_filename (ibfd),
20483d8817e4Smiod 	     err, bfd_errmsg (bfd_get_error ()));
20493d8817e4Smiod   status = 1;
20503d8817e4Smiod }
20513d8817e4Smiod 
20523d8817e4Smiod /* Create a section in OBFD with the same
20533d8817e4Smiod    name and attributes as ISECTION in IBFD.  */
20543d8817e4Smiod 
20553d8817e4Smiod static void
setup_section(bfd * ibfd,sec_ptr isection,void * obfdarg)20563d8817e4Smiod setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
20573d8817e4Smiod {
20583d8817e4Smiod   bfd *obfd = obfdarg;
20593d8817e4Smiod   struct section_list *p;
20603d8817e4Smiod   sec_ptr osection;
20613d8817e4Smiod   bfd_size_type size;
20623d8817e4Smiod   bfd_vma vma;
20633d8817e4Smiod   bfd_vma lma;
20643d8817e4Smiod   flagword flags;
20653d8817e4Smiod   const char *err;
20663d8817e4Smiod   const char * name;
20673d8817e4Smiod   char *prefix = NULL;
20683d8817e4Smiod 
20693d8817e4Smiod   if (is_strip_section (ibfd, isection))
20703d8817e4Smiod     return;
20713d8817e4Smiod 
20723d8817e4Smiod   p = find_section_list (bfd_section_name (ibfd, isection), FALSE);
20733d8817e4Smiod   if (p != NULL)
20743d8817e4Smiod     p->used = TRUE;
20753d8817e4Smiod 
20763d8817e4Smiod   /* Get the, possibly new, name of the output section.  */
20773d8817e4Smiod   name = find_section_rename (ibfd, isection, & flags);
20783d8817e4Smiod 
20793d8817e4Smiod   /* Prefix sections.  */
20803d8817e4Smiod   if ((prefix_alloc_sections_string)
20813d8817e4Smiod       && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
20823d8817e4Smiod     prefix = prefix_alloc_sections_string;
20833d8817e4Smiod   else if (prefix_sections_string)
20843d8817e4Smiod     prefix = prefix_sections_string;
20853d8817e4Smiod 
20863d8817e4Smiod   if (prefix)
20873d8817e4Smiod     {
20883d8817e4Smiod       char *n;
20893d8817e4Smiod 
20903d8817e4Smiod       n = xmalloc (strlen (prefix) + strlen (name) + 1);
20913d8817e4Smiod       strcpy (n, prefix);
20923d8817e4Smiod       strcat (n, name);
20933d8817e4Smiod       name = n;
20943d8817e4Smiod     }
20953d8817e4Smiod 
20963d8817e4Smiod   if (p != NULL && p->set_flags)
20973d8817e4Smiod     flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
20983d8817e4Smiod   else if (strip_symbols == STRIP_NONDEBUG && (flags & SEC_ALLOC) != 0)
20993d8817e4Smiod     flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD);
21003d8817e4Smiod 
21013d8817e4Smiod   osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
21023d8817e4Smiod 
21033d8817e4Smiod   if (osection == NULL)
21043d8817e4Smiod     {
21053d8817e4Smiod       err = _("making");
21063d8817e4Smiod       goto loser;
21073d8817e4Smiod     }
21083d8817e4Smiod 
21093d8817e4Smiod   if (strip_symbols == STRIP_NONDEBUG
21103d8817e4Smiod       && obfd->xvec->flavour == bfd_target_elf_flavour
21113d8817e4Smiod       && (flags & SEC_ALLOC) != 0
21123d8817e4Smiod       && (p == NULL || !p->set_flags))
21133d8817e4Smiod     elf_section_type (osection) = SHT_NOBITS;
21143d8817e4Smiod 
21153d8817e4Smiod   size = bfd_section_size (ibfd, isection);
21163d8817e4Smiod   if (copy_byte >= 0)
21173d8817e4Smiod     size = (size + interleave - 1) / interleave;
21183d8817e4Smiod   if (! bfd_set_section_size (obfd, osection, size))
21193d8817e4Smiod     {
21203d8817e4Smiod       err = _("size");
21213d8817e4Smiod       goto loser;
21223d8817e4Smiod     }
21233d8817e4Smiod 
21243d8817e4Smiod   vma = bfd_section_vma (ibfd, isection);
21253d8817e4Smiod   if (p != NULL && p->change_vma == CHANGE_MODIFY)
21263d8817e4Smiod     vma += p->vma_val;
21273d8817e4Smiod   else if (p != NULL && p->change_vma == CHANGE_SET)
21283d8817e4Smiod     vma = p->vma_val;
21293d8817e4Smiod   else
21303d8817e4Smiod     vma += change_section_address;
21313d8817e4Smiod 
21323d8817e4Smiod   if (! bfd_set_section_vma (obfd, osection, vma))
21333d8817e4Smiod     {
21343d8817e4Smiod       err = _("vma");
21353d8817e4Smiod       goto loser;
21363d8817e4Smiod     }
21373d8817e4Smiod 
21383d8817e4Smiod   lma = isection->lma;
21393d8817e4Smiod   if ((p != NULL) && p->change_lma != CHANGE_IGNORE)
21403d8817e4Smiod     {
21413d8817e4Smiod       if (p->change_lma == CHANGE_MODIFY)
21423d8817e4Smiod 	lma += p->lma_val;
21433d8817e4Smiod       else if (p->change_lma == CHANGE_SET)
21443d8817e4Smiod 	lma = p->lma_val;
21453d8817e4Smiod       else
21463d8817e4Smiod 	abort ();
21473d8817e4Smiod     }
21483d8817e4Smiod   else
21493d8817e4Smiod     lma += change_section_address;
21503d8817e4Smiod 
21513d8817e4Smiod   osection->lma = lma;
21523d8817e4Smiod 
21533d8817e4Smiod   /* FIXME: This is probably not enough.  If we change the LMA we
21543d8817e4Smiod      may have to recompute the header for the file as well.  */
21553d8817e4Smiod   if (!bfd_set_section_alignment (obfd,
21563d8817e4Smiod 				  osection,
21573d8817e4Smiod 				  bfd_section_alignment (ibfd, isection)))
21583d8817e4Smiod     {
21593d8817e4Smiod       err = _("alignment");
21603d8817e4Smiod       goto loser;
21613d8817e4Smiod     }
21623d8817e4Smiod 
21633d8817e4Smiod   /* Copy merge entity size.  */
21643d8817e4Smiod   osection->entsize = isection->entsize;
21653d8817e4Smiod 
21663d8817e4Smiod   /* This used to be mangle_section; we do here to avoid using
21673d8817e4Smiod      bfd_get_section_by_name since some formats allow multiple
21683d8817e4Smiod      sections with the same name.  */
21693d8817e4Smiod   isection->output_section = osection;
21703d8817e4Smiod   isection->output_offset = 0;
21713d8817e4Smiod 
21723d8817e4Smiod   /* Allow the BFD backend to copy any private data it understands
21733d8817e4Smiod      from the input section to the output section.  */
21743d8817e4Smiod   if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
21753d8817e4Smiod       && strip_symbols == STRIP_NONDEBUG)
21763d8817e4Smiod     /* Do not copy the private data when creating an ELF format
21773d8817e4Smiod        debug info file.  We do not want the program headers.  */
21783d8817e4Smiod     ;
21793d8817e4Smiod   else if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
21803d8817e4Smiod     {
21813d8817e4Smiod       err = _("private data");
21823d8817e4Smiod       goto loser;
21833d8817e4Smiod     }
21843d8817e4Smiod 
21853d8817e4Smiod   /* All went well.  */
21863d8817e4Smiod   return;
21873d8817e4Smiod 
21883d8817e4Smiod loser:
21893d8817e4Smiod   non_fatal (_("%s: section `%s': error in %s: %s"),
21903d8817e4Smiod 	     bfd_get_filename (ibfd),
21913d8817e4Smiod 	     bfd_section_name (ibfd, isection),
21923d8817e4Smiod 	     err, bfd_errmsg (bfd_get_error ()));
21933d8817e4Smiod   status = 1;
21943d8817e4Smiod }
21953d8817e4Smiod 
21963d8817e4Smiod /* Copy the data of input section ISECTION of IBFD
21973d8817e4Smiod    to an output section with the same name in OBFD.
21983d8817e4Smiod    If stripping then don't copy any relocation info.  */
21993d8817e4Smiod 
22003d8817e4Smiod static void
copy_section(bfd * ibfd,sec_ptr isection,void * obfdarg)22013d8817e4Smiod copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
22023d8817e4Smiod {
22033d8817e4Smiod   bfd *obfd = obfdarg;
22043d8817e4Smiod   struct section_list *p;
22053d8817e4Smiod   arelent **relpp;
22063d8817e4Smiod   long relcount;
22073d8817e4Smiod   sec_ptr osection;
22083d8817e4Smiod   bfd_size_type size;
22093d8817e4Smiod   long relsize;
22103d8817e4Smiod   flagword flags;
22113d8817e4Smiod 
22123d8817e4Smiod   /* If we have already failed earlier on,
22133d8817e4Smiod      do not keep on generating complaints now.  */
22143d8817e4Smiod   if (status != 0)
22153d8817e4Smiod     return;
22163d8817e4Smiod 
22173d8817e4Smiod   if (is_strip_section (ibfd, isection))
22183d8817e4Smiod     return;
22193d8817e4Smiod 
22203d8817e4Smiod   flags = bfd_get_section_flags (ibfd, isection);
22213d8817e4Smiod   if ((flags & SEC_GROUP) != 0)
22223d8817e4Smiod     return;
22233d8817e4Smiod 
22243d8817e4Smiod   osection = isection->output_section;
22253d8817e4Smiod   size = bfd_get_section_size (isection);
22263d8817e4Smiod 
22273d8817e4Smiod   if (size == 0 || osection == 0)
22283d8817e4Smiod     return;
22293d8817e4Smiod 
22303d8817e4Smiod   p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE);
22313d8817e4Smiod 
22323d8817e4Smiod   /* Core files do not need to be relocated.  */
22333d8817e4Smiod   if (bfd_get_format (obfd) == bfd_core)
22343d8817e4Smiod     relsize = 0;
22353d8817e4Smiod   else
22363d8817e4Smiod     {
22373d8817e4Smiod       relsize = bfd_get_reloc_upper_bound (ibfd, isection);
22383d8817e4Smiod 
22393d8817e4Smiod       if (relsize < 0)
22403d8817e4Smiod 	{
22413d8817e4Smiod 	  /* Do not complain if the target does not support relocations.  */
22423d8817e4Smiod 	  if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
22433d8817e4Smiod 	    relsize = 0;
22443d8817e4Smiod 	  else
22453d8817e4Smiod 	    RETURN_NONFATAL (bfd_get_filename (ibfd));
22463d8817e4Smiod 	}
22473d8817e4Smiod     }
22483d8817e4Smiod 
22493d8817e4Smiod   if (relsize == 0)
22503d8817e4Smiod     bfd_set_reloc (obfd, osection, NULL, 0);
22513d8817e4Smiod   else
22523d8817e4Smiod     {
22533d8817e4Smiod       relpp = xmalloc (relsize);
22543d8817e4Smiod       relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
22553d8817e4Smiod       if (relcount < 0)
22563d8817e4Smiod 	RETURN_NONFATAL (bfd_get_filename (ibfd));
22573d8817e4Smiod 
22583d8817e4Smiod       if (strip_symbols == STRIP_ALL)
22593d8817e4Smiod 	{
22603d8817e4Smiod 	  /* Remove relocations which are not in
22613d8817e4Smiod 	     keep_strip_specific_list.  */
22623d8817e4Smiod 	  arelent **temp_relpp;
22633d8817e4Smiod 	  long temp_relcount = 0;
22643d8817e4Smiod 	  long i;
22653d8817e4Smiod 
22663d8817e4Smiod 	  temp_relpp = xmalloc (relsize);
22673d8817e4Smiod 	  for (i = 0; i < relcount; i++)
22683d8817e4Smiod 	    if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
22693d8817e4Smiod 				     keep_specific_list))
22703d8817e4Smiod 	      temp_relpp [temp_relcount++] = relpp [i];
22713d8817e4Smiod 	  relcount = temp_relcount;
22723d8817e4Smiod 	  free (relpp);
22733d8817e4Smiod 	  relpp = temp_relpp;
22743d8817e4Smiod 	}
22753d8817e4Smiod 
22763d8817e4Smiod       bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
22773d8817e4Smiod       if (relcount == 0)
22783d8817e4Smiod 	free (relpp);
22793d8817e4Smiod     }
22803d8817e4Smiod 
22813d8817e4Smiod   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
22823d8817e4Smiod       && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
22833d8817e4Smiod     {
22843d8817e4Smiod       void *memhunk = xmalloc (size);
22853d8817e4Smiod 
22863d8817e4Smiod       if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
22873d8817e4Smiod 	RETURN_NONFATAL (bfd_get_filename (ibfd));
22883d8817e4Smiod 
22893d8817e4Smiod       if (copy_byte >= 0)
22903d8817e4Smiod 	{
22913d8817e4Smiod 	  /* Keep only every `copy_byte'th byte in MEMHUNK.  */
22923d8817e4Smiod 	  char *from = (char *) memhunk + copy_byte;
22933d8817e4Smiod 	  char *to = memhunk;
22943d8817e4Smiod 	  char *end = (char *) memhunk + size;
22953d8817e4Smiod 
22963d8817e4Smiod 	  for (; from < end; from += interleave)
22973d8817e4Smiod 	    *to++ = *from;
22983d8817e4Smiod 
22993d8817e4Smiod 	  size = (size + interleave - 1 - copy_byte) / interleave;
23003d8817e4Smiod 	  osection->lma /= interleave;
23013d8817e4Smiod 	}
23023d8817e4Smiod 
23033d8817e4Smiod       if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
23043d8817e4Smiod 	RETURN_NONFATAL (bfd_get_filename (obfd));
23053d8817e4Smiod 
23063d8817e4Smiod       free (memhunk);
23073d8817e4Smiod     }
23083d8817e4Smiod   else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0)
23093d8817e4Smiod     {
23103d8817e4Smiod       void *memhunk = xmalloc (size);
23113d8817e4Smiod 
23123d8817e4Smiod       /* We don't permit the user to turn off the SEC_HAS_CONTENTS
23133d8817e4Smiod 	 flag--they can just remove the section entirely and add it
23143d8817e4Smiod 	 back again.  However, we do permit them to turn on the
23153d8817e4Smiod 	 SEC_HAS_CONTENTS flag, and take it to mean that the section
23163d8817e4Smiod 	 contents should be zeroed out.  */
23173d8817e4Smiod 
23183d8817e4Smiod       memset (memhunk, 0, size);
23193d8817e4Smiod       if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
23203d8817e4Smiod 	RETURN_NONFATAL (bfd_get_filename (obfd));
23213d8817e4Smiod       free (memhunk);
23223d8817e4Smiod     }
23233d8817e4Smiod }
23243d8817e4Smiod 
23253d8817e4Smiod /* Get all the sections.  This is used when --gap-fill or --pad-to is
23263d8817e4Smiod    used.  */
23273d8817e4Smiod 
23283d8817e4Smiod static void
get_sections(bfd * obfd ATTRIBUTE_UNUSED,asection * osection,void * secppparg)23293d8817e4Smiod get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
23303d8817e4Smiod {
23313d8817e4Smiod   asection ***secppp = secppparg;
23323d8817e4Smiod 
23333d8817e4Smiod   **secppp = osection;
23343d8817e4Smiod   ++(*secppp);
23353d8817e4Smiod }
23363d8817e4Smiod 
23373d8817e4Smiod /* Sort sections by VMA.  This is called via qsort, and is used when
23383d8817e4Smiod    --gap-fill or --pad-to is used.  We force non loadable or empty
23393d8817e4Smiod    sections to the front, where they are easier to ignore.  */
23403d8817e4Smiod 
23413d8817e4Smiod static int
compare_section_lma(const void * arg1,const void * arg2)23423d8817e4Smiod compare_section_lma (const void *arg1, const void *arg2)
23433d8817e4Smiod {
23443d8817e4Smiod   const asection *const *sec1 = arg1;
23453d8817e4Smiod   const asection *const *sec2 = arg2;
23463d8817e4Smiod   flagword flags1, flags2;
23473d8817e4Smiod 
23483d8817e4Smiod   /* Sort non loadable sections to the front.  */
23493d8817e4Smiod   flags1 = (*sec1)->flags;
23503d8817e4Smiod   flags2 = (*sec2)->flags;
23513d8817e4Smiod   if ((flags1 & SEC_HAS_CONTENTS) == 0
23523d8817e4Smiod       || (flags1 & SEC_LOAD) == 0)
23533d8817e4Smiod     {
23543d8817e4Smiod       if ((flags2 & SEC_HAS_CONTENTS) != 0
23553d8817e4Smiod 	  && (flags2 & SEC_LOAD) != 0)
23563d8817e4Smiod 	return -1;
23573d8817e4Smiod     }
23583d8817e4Smiod   else
23593d8817e4Smiod     {
23603d8817e4Smiod       if ((flags2 & SEC_HAS_CONTENTS) == 0
23613d8817e4Smiod 	  || (flags2 & SEC_LOAD) == 0)
23623d8817e4Smiod 	return 1;
23633d8817e4Smiod     }
23643d8817e4Smiod 
23653d8817e4Smiod   /* Sort sections by LMA.  */
23663d8817e4Smiod   if ((*sec1)->lma > (*sec2)->lma)
23673d8817e4Smiod     return 1;
23683d8817e4Smiod   else if ((*sec1)->lma < (*sec2)->lma)
23693d8817e4Smiod     return -1;
23703d8817e4Smiod 
23713d8817e4Smiod   /* Sort sections with the same LMA by size.  */
23723d8817e4Smiod   if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2))
23733d8817e4Smiod     return 1;
23743d8817e4Smiod   else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2))
23753d8817e4Smiod     return -1;
23763d8817e4Smiod 
23773d8817e4Smiod   return 0;
23783d8817e4Smiod }
23793d8817e4Smiod 
23803d8817e4Smiod /* Mark all the symbols which will be used in output relocations with
23813d8817e4Smiod    the BSF_KEEP flag so that those symbols will not be stripped.
23823d8817e4Smiod 
23833d8817e4Smiod    Ignore relocations which will not appear in the output file.  */
23843d8817e4Smiod 
23853d8817e4Smiod static void
mark_symbols_used_in_relocations(bfd * ibfd,sec_ptr isection,void * symbolsarg)23863d8817e4Smiod mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
23873d8817e4Smiod {
23883d8817e4Smiod   asymbol **symbols = symbolsarg;
23893d8817e4Smiod   long relsize;
23903d8817e4Smiod   arelent **relpp;
23913d8817e4Smiod   long relcount, i;
23923d8817e4Smiod 
23933d8817e4Smiod   /* Ignore an input section with no corresponding output section.  */
23943d8817e4Smiod   if (isection->output_section == NULL)
23953d8817e4Smiod     return;
23963d8817e4Smiod 
23973d8817e4Smiod   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
23983d8817e4Smiod   if (relsize < 0)
23993d8817e4Smiod     {
24003d8817e4Smiod       /* Do not complain if the target does not support relocations.  */
24013d8817e4Smiod       if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
24023d8817e4Smiod 	return;
24033d8817e4Smiod       bfd_fatal (bfd_get_filename (ibfd));
24043d8817e4Smiod     }
24053d8817e4Smiod 
24063d8817e4Smiod   if (relsize == 0)
24073d8817e4Smiod     return;
24083d8817e4Smiod 
24093d8817e4Smiod   relpp = xmalloc (relsize);
24103d8817e4Smiod   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
24113d8817e4Smiod   if (relcount < 0)
24123d8817e4Smiod     bfd_fatal (bfd_get_filename (ibfd));
24133d8817e4Smiod 
24143d8817e4Smiod   /* Examine each symbol used in a relocation.  If it's not one of the
24153d8817e4Smiod      special bfd section symbols, then mark it with BSF_KEEP.  */
24163d8817e4Smiod   for (i = 0; i < relcount; i++)
24173d8817e4Smiod     {
24183d8817e4Smiod       if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
24193d8817e4Smiod 	  && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
24203d8817e4Smiod 	  && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
24213d8817e4Smiod 	(*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
24223d8817e4Smiod     }
24233d8817e4Smiod 
24243d8817e4Smiod   if (relpp != NULL)
24253d8817e4Smiod     free (relpp);
24263d8817e4Smiod }
24273d8817e4Smiod 
24283d8817e4Smiod /* Write out debugging information.  */
24293d8817e4Smiod 
24303d8817e4Smiod static bfd_boolean
write_debugging_info(bfd * obfd,void * dhandle,long * symcountp ATTRIBUTE_UNUSED,asymbol *** symppp ATTRIBUTE_UNUSED)24313d8817e4Smiod write_debugging_info (bfd *obfd, void *dhandle,
24323d8817e4Smiod 		      long *symcountp ATTRIBUTE_UNUSED,
24333d8817e4Smiod 		      asymbol ***symppp ATTRIBUTE_UNUSED)
24343d8817e4Smiod {
24353d8817e4Smiod   if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
24363d8817e4Smiod     return write_ieee_debugging_info (obfd, dhandle);
24373d8817e4Smiod 
24383d8817e4Smiod   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
24393d8817e4Smiod       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
24403d8817e4Smiod     {
24413d8817e4Smiod       bfd_byte *syms, *strings;
24423d8817e4Smiod       bfd_size_type symsize, stringsize;
24433d8817e4Smiod       asection *stabsec, *stabstrsec;
24443d8817e4Smiod       flagword flags;
24453d8817e4Smiod 
24463d8817e4Smiod       if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
24473d8817e4Smiod 						    &symsize, &strings,
24483d8817e4Smiod 						    &stringsize))
24493d8817e4Smiod 	return FALSE;
24503d8817e4Smiod 
24513d8817e4Smiod       flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
24523d8817e4Smiod       stabsec = bfd_make_section_with_flags (obfd, ".stab", flags);
24533d8817e4Smiod       stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags);
24543d8817e4Smiod       if (stabsec == NULL
24553d8817e4Smiod 	  || stabstrsec == NULL
24563d8817e4Smiod 	  || ! bfd_set_section_size (obfd, stabsec, symsize)
24573d8817e4Smiod 	  || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
24583d8817e4Smiod 	  || ! bfd_set_section_alignment (obfd, stabsec, 2)
24593d8817e4Smiod 	  || ! bfd_set_section_alignment (obfd, stabstrsec, 0))
24603d8817e4Smiod 	{
24613d8817e4Smiod 	  non_fatal (_("%s: can't create debugging section: %s"),
24623d8817e4Smiod 		     bfd_get_filename (obfd),
24633d8817e4Smiod 		     bfd_errmsg (bfd_get_error ()));
24643d8817e4Smiod 	  return FALSE;
24653d8817e4Smiod 	}
24663d8817e4Smiod 
24673d8817e4Smiod       /* We can get away with setting the section contents now because
24683d8817e4Smiod          the next thing the caller is going to do is copy over the
24693d8817e4Smiod          real sections.  We may someday have to split the contents
24703d8817e4Smiod          setting out of this function.  */
24713d8817e4Smiod       if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
24723d8817e4Smiod 	  || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
24733d8817e4Smiod 					 stringsize))
24743d8817e4Smiod 	{
24753d8817e4Smiod 	  non_fatal (_("%s: can't set debugging section contents: %s"),
24763d8817e4Smiod 		     bfd_get_filename (obfd),
24773d8817e4Smiod 		     bfd_errmsg (bfd_get_error ()));
24783d8817e4Smiod 	  return FALSE;
24793d8817e4Smiod 	}
24803d8817e4Smiod 
24813d8817e4Smiod       return TRUE;
24823d8817e4Smiod     }
24833d8817e4Smiod 
24843d8817e4Smiod   non_fatal (_("%s: don't know how to write debugging information for %s"),
24853d8817e4Smiod 	     bfd_get_filename (obfd), bfd_get_target (obfd));
24863d8817e4Smiod   return FALSE;
24873d8817e4Smiod }
24883d8817e4Smiod 
24893d8817e4Smiod static int
strip_main(int argc,char * argv[])24903d8817e4Smiod strip_main (int argc, char *argv[])
24913d8817e4Smiod {
24923d8817e4Smiod   char *input_target = NULL;
24933d8817e4Smiod   char *output_target = NULL;
24943d8817e4Smiod   bfd_boolean show_version = FALSE;
24953d8817e4Smiod   bfd_boolean formats_info = FALSE;
24963d8817e4Smiod   int c;
24973d8817e4Smiod   int i;
24983d8817e4Smiod   struct section_list *p;
24993d8817e4Smiod   char *output_file = NULL;
25003d8817e4Smiod 
25013d8817e4Smiod   while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw",
25023d8817e4Smiod 			   strip_options, (int *) 0)) != EOF)
25033d8817e4Smiod     {
25043d8817e4Smiod       switch (c)
25053d8817e4Smiod 	{
25063d8817e4Smiod 	case 'I':
25073d8817e4Smiod 	  input_target = optarg;
25083d8817e4Smiod 	  break;
25093d8817e4Smiod 	case 'O':
25103d8817e4Smiod 	  output_target = optarg;
25113d8817e4Smiod 	  break;
25123d8817e4Smiod 	case 'F':
25133d8817e4Smiod 	  input_target = output_target = optarg;
25143d8817e4Smiod 	  break;
25153d8817e4Smiod 	case 'R':
25163d8817e4Smiod 	  p = find_section_list (optarg, TRUE);
25173d8817e4Smiod 	  p->remove = TRUE;
25183d8817e4Smiod 	  sections_removed = TRUE;
25193d8817e4Smiod 	  break;
25203d8817e4Smiod 	case 's':
25213d8817e4Smiod 	  strip_symbols = STRIP_ALL;
25223d8817e4Smiod 	  break;
25233d8817e4Smiod 	case 'S':
25243d8817e4Smiod 	case 'g':
25253d8817e4Smiod 	case 'd':	/* Historic BSD alias for -g.  Used by early NetBSD.  */
25263d8817e4Smiod 	  strip_symbols = STRIP_DEBUG;
25273d8817e4Smiod 	  break;
25283d8817e4Smiod 	case OPTION_STRIP_UNNEEDED:
25293d8817e4Smiod 	  strip_symbols = STRIP_UNNEEDED;
25303d8817e4Smiod 	  break;
25313d8817e4Smiod 	case 'K':
25323d8817e4Smiod 	  add_specific_symbol (optarg, &keep_specific_list);
25333d8817e4Smiod 	  break;
25343d8817e4Smiod 	case 'N':
25353d8817e4Smiod 	  add_specific_symbol (optarg, &strip_specific_list);
25363d8817e4Smiod 	  break;
25373d8817e4Smiod 	case 'o':
25383d8817e4Smiod 	  output_file = optarg;
25393d8817e4Smiod 	  break;
25403d8817e4Smiod 	case 'p':
25413d8817e4Smiod 	  preserve_dates = TRUE;
25423d8817e4Smiod 	  break;
25433d8817e4Smiod 	case 'x':
25443d8817e4Smiod 	  discard_locals = LOCALS_ALL;
25453d8817e4Smiod 	  break;
25463d8817e4Smiod 	case 'X':
25473d8817e4Smiod 	  discard_locals = LOCALS_START_L;
25483d8817e4Smiod 	  break;
25493d8817e4Smiod 	case 'v':
25503d8817e4Smiod 	  verbose = TRUE;
25513d8817e4Smiod 	  break;
25523d8817e4Smiod 	case 'V':
25533d8817e4Smiod 	  show_version = TRUE;
25543d8817e4Smiod 	  break;
25553d8817e4Smiod 	case OPTION_FORMATS_INFO:
25563d8817e4Smiod 	  formats_info = TRUE;
25573d8817e4Smiod 	  break;
25583d8817e4Smiod 	case OPTION_ONLY_KEEP_DEBUG:
25593d8817e4Smiod 	  strip_symbols = STRIP_NONDEBUG;
25603d8817e4Smiod 	  break;
25613d8817e4Smiod 	case OPTION_KEEP_FILE_SYMBOLS:
25623d8817e4Smiod 	  keep_file_symbols = 1;
25633d8817e4Smiod 	  break;
25643d8817e4Smiod 	case 0:
25653d8817e4Smiod 	  /* We've been given a long option.  */
25663d8817e4Smiod 	  break;
25673d8817e4Smiod 	case 'w':
25683d8817e4Smiod 	  wildcard = TRUE;
25693d8817e4Smiod 	  break;
25703d8817e4Smiod 	case 'H':
25713d8817e4Smiod 	case 'h':
25723d8817e4Smiod 	  strip_usage (stdout, 0);
25733d8817e4Smiod 	default:
25743d8817e4Smiod 	  strip_usage (stderr, 1);
25753d8817e4Smiod 	}
25763d8817e4Smiod     }
25773d8817e4Smiod 
25783d8817e4Smiod   if (formats_info)
25793d8817e4Smiod     {
25803d8817e4Smiod       display_info ();
25813d8817e4Smiod       return 0;
25823d8817e4Smiod     }
25833d8817e4Smiod 
25843d8817e4Smiod   if (show_version)
25853d8817e4Smiod     print_version ("strip");
25863d8817e4Smiod 
25873d8817e4Smiod   /* Default is to strip all symbols.  */
25883d8817e4Smiod   if (strip_symbols == STRIP_UNDEF
25893d8817e4Smiod       && discard_locals == LOCALS_UNDEF
25903d8817e4Smiod       && strip_specific_list == NULL)
25913d8817e4Smiod     strip_symbols = STRIP_ALL;
25923d8817e4Smiod 
25933d8817e4Smiod   if (output_target == NULL)
25943d8817e4Smiod     output_target = input_target;
25953d8817e4Smiod 
25963d8817e4Smiod   i = optind;
25973d8817e4Smiod   if (i == argc
25983d8817e4Smiod       || (output_file != NULL && (i + 1) < argc))
25993d8817e4Smiod     strip_usage (stderr, 1);
26003d8817e4Smiod 
26013d8817e4Smiod   for (; i < argc; i++)
26023d8817e4Smiod     {
26033d8817e4Smiod       int hold_status = status;
26043d8817e4Smiod       struct stat statbuf;
26053d8817e4Smiod       char *tmpname;
26063d8817e4Smiod 
26073d8817e4Smiod       if (get_file_size (argv[i]) < 1)
2608d2386abeSmiod 	{
2609d2386abeSmiod 	  status = 1;
26103d8817e4Smiod 	  continue;
2611d2386abeSmiod 	}
26123d8817e4Smiod 
26133d8817e4Smiod       if (preserve_dates)
26143d8817e4Smiod 	/* No need to check the return value of stat().
26153d8817e4Smiod 	   It has already been checked in get_file_size().  */
26163d8817e4Smiod 	stat (argv[i], &statbuf);
26173d8817e4Smiod 
26183d8817e4Smiod       if (output_file != NULL)
26193d8817e4Smiod 	tmpname = output_file;
26203d8817e4Smiod       else
2621d2386abeSmiod 	tmpname = make_tempname (argv[i], 0);
26223d8817e4Smiod       status = 0;
26233d8817e4Smiod 
26243d8817e4Smiod       copy_file (argv[i], tmpname, input_target, output_target);
26253d8817e4Smiod       if (status == 0)
26263d8817e4Smiod 	{
26273d8817e4Smiod 	  if (preserve_dates)
26283d8817e4Smiod 	    set_times (tmpname, &statbuf);
26293d8817e4Smiod 	  if (output_file == NULL)
2630*d983f9a7Sespie 	    {
2631*d983f9a7Sespie 		int ret = smart_rename (tmpname, argv[i], preserve_dates);
2632*d983f9a7Sespie 		if (ret != 0)
2633*d983f9a7Sespie 		    hold_status = ret;
2634*d983f9a7Sespie 	    }
26353d8817e4Smiod 	  status = hold_status;
26363d8817e4Smiod 	}
26373d8817e4Smiod       else
26383d8817e4Smiod 	unlink_if_ordinary (tmpname);
26393d8817e4Smiod       if (output_file == NULL)
26403d8817e4Smiod 	free (tmpname);
26413d8817e4Smiod     }
26423d8817e4Smiod 
26433d8817e4Smiod   return 0;
26443d8817e4Smiod }
26453d8817e4Smiod 
26463d8817e4Smiod static int
copy_main(int argc,char * argv[])26473d8817e4Smiod copy_main (int argc, char *argv[])
26483d8817e4Smiod {
26493d8817e4Smiod   char * binary_architecture = NULL;
26503d8817e4Smiod   char *input_filename = NULL;
26513d8817e4Smiod   char *output_filename = NULL;
26523d8817e4Smiod   char *input_target = NULL;
26533d8817e4Smiod   char *output_target = NULL;
26543d8817e4Smiod   bfd_boolean show_version = FALSE;
26553d8817e4Smiod   bfd_boolean change_warn = TRUE;
26563d8817e4Smiod   bfd_boolean formats_info = FALSE;
26573d8817e4Smiod   int c;
26583d8817e4Smiod   struct section_list *p;
26593d8817e4Smiod   struct stat statbuf;
26603d8817e4Smiod 
26613d8817e4Smiod   while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w",
26623d8817e4Smiod 			   copy_options, (int *) 0)) != EOF)
26633d8817e4Smiod     {
26643d8817e4Smiod       switch (c)
26653d8817e4Smiod 	{
26663d8817e4Smiod 	case 'b':
26673d8817e4Smiod 	  copy_byte = atoi (optarg);
26683d8817e4Smiod 	  if (copy_byte < 0)
26693d8817e4Smiod 	    fatal (_("byte number must be non-negative"));
26703d8817e4Smiod 	  break;
26713d8817e4Smiod 
26723d8817e4Smiod 	case 'B':
26733d8817e4Smiod 	  binary_architecture = optarg;
26743d8817e4Smiod 	  break;
26753d8817e4Smiod 
26763d8817e4Smiod 	case 'i':
26773d8817e4Smiod 	  interleave = atoi (optarg);
26783d8817e4Smiod 	  if (interleave < 1)
26793d8817e4Smiod 	    fatal (_("interleave must be positive"));
26803d8817e4Smiod 	  break;
26813d8817e4Smiod 
26823d8817e4Smiod 	case 'I':
26833d8817e4Smiod 	case 's':		/* "source" - 'I' is preferred */
26843d8817e4Smiod 	  input_target = optarg;
26853d8817e4Smiod 	  break;
26863d8817e4Smiod 
26873d8817e4Smiod 	case 'O':
26883d8817e4Smiod 	case 'd':		/* "destination" - 'O' is preferred */
26893d8817e4Smiod 	  output_target = optarg;
26903d8817e4Smiod 	  break;
26913d8817e4Smiod 
26923d8817e4Smiod 	case 'F':
26933d8817e4Smiod 	  input_target = output_target = optarg;
26943d8817e4Smiod 	  break;
26953d8817e4Smiod 
26963d8817e4Smiod 	case 'j':
26973d8817e4Smiod 	  p = find_section_list (optarg, TRUE);
26983d8817e4Smiod 	  if (p->remove)
26993d8817e4Smiod 	    fatal (_("%s both copied and removed"), optarg);
27003d8817e4Smiod 	  p->copy = TRUE;
27013d8817e4Smiod 	  sections_copied = TRUE;
27023d8817e4Smiod 	  break;
27033d8817e4Smiod 
27043d8817e4Smiod 	case 'R':
27053d8817e4Smiod 	  p = find_section_list (optarg, TRUE);
27063d8817e4Smiod 	  if (p->copy)
27073d8817e4Smiod 	    fatal (_("%s both copied and removed"), optarg);
27083d8817e4Smiod 	  p->remove = TRUE;
27093d8817e4Smiod 	  sections_removed = TRUE;
27103d8817e4Smiod 	  break;
27113d8817e4Smiod 
27123d8817e4Smiod 	case 'S':
27133d8817e4Smiod 	  strip_symbols = STRIP_ALL;
27143d8817e4Smiod 	  break;
27153d8817e4Smiod 
27163d8817e4Smiod 	case 'g':
27173d8817e4Smiod 	  strip_symbols = STRIP_DEBUG;
27183d8817e4Smiod 	  break;
27193d8817e4Smiod 
27203d8817e4Smiod 	case OPTION_STRIP_UNNEEDED:
27213d8817e4Smiod 	  strip_symbols = STRIP_UNNEEDED;
27223d8817e4Smiod 	  break;
27233d8817e4Smiod 
27243d8817e4Smiod 	case OPTION_ONLY_KEEP_DEBUG:
27253d8817e4Smiod 	  strip_symbols = STRIP_NONDEBUG;
27263d8817e4Smiod 	  break;
27273d8817e4Smiod 
27283d8817e4Smiod 	case OPTION_KEEP_FILE_SYMBOLS:
27293d8817e4Smiod 	  keep_file_symbols = 1;
27303d8817e4Smiod 	  break;
27313d8817e4Smiod 
27323d8817e4Smiod 	case OPTION_ADD_GNU_DEBUGLINK:
27333d8817e4Smiod 	  gnu_debuglink_filename = optarg;
27343d8817e4Smiod 	  break;
27353d8817e4Smiod 
27363d8817e4Smiod 	case 'K':
27373d8817e4Smiod 	  add_specific_symbol (optarg, &keep_specific_list);
27383d8817e4Smiod 	  break;
27393d8817e4Smiod 
27403d8817e4Smiod 	case 'N':
27413d8817e4Smiod 	  add_specific_symbol (optarg, &strip_specific_list);
27423d8817e4Smiod 	  break;
27433d8817e4Smiod 
27443d8817e4Smiod 	case OPTION_STRIP_UNNEEDED_SYMBOL:
27453d8817e4Smiod 	  add_specific_symbol (optarg, &strip_unneeded_list);
27463d8817e4Smiod 	  break;
27473d8817e4Smiod 
27483d8817e4Smiod 	case 'L':
27493d8817e4Smiod 	  add_specific_symbol (optarg, &localize_specific_list);
27503d8817e4Smiod 	  break;
27513d8817e4Smiod 
27523d8817e4Smiod 	case OPTION_GLOBALIZE_SYMBOL:
27533d8817e4Smiod 	  add_specific_symbol (optarg, &globalize_specific_list);
27543d8817e4Smiod 	  break;
27553d8817e4Smiod 
27563d8817e4Smiod 	case 'G':
27573d8817e4Smiod 	  add_specific_symbol (optarg, &keepglobal_specific_list);
27583d8817e4Smiod 	  break;
27593d8817e4Smiod 
27603d8817e4Smiod 	case 'W':
27613d8817e4Smiod 	  add_specific_symbol (optarg, &weaken_specific_list);
27623d8817e4Smiod 	  break;
27633d8817e4Smiod 
27643d8817e4Smiod 	case 'p':
27653d8817e4Smiod 	  preserve_dates = TRUE;
27663d8817e4Smiod 	  break;
27673d8817e4Smiod 
27683d8817e4Smiod 	case 'w':
27693d8817e4Smiod 	  wildcard = TRUE;
27703d8817e4Smiod 	  break;
27713d8817e4Smiod 
27723d8817e4Smiod 	case 'x':
27733d8817e4Smiod 	  discard_locals = LOCALS_ALL;
27743d8817e4Smiod 	  break;
27753d8817e4Smiod 
27763d8817e4Smiod 	case 'X':
27773d8817e4Smiod 	  discard_locals = LOCALS_START_L;
27783d8817e4Smiod 	  break;
27793d8817e4Smiod 
27803d8817e4Smiod 	case 'v':
27813d8817e4Smiod 	  verbose = TRUE;
27823d8817e4Smiod 	  break;
27833d8817e4Smiod 
27843d8817e4Smiod 	case 'V':
27853d8817e4Smiod 	  show_version = TRUE;
27863d8817e4Smiod 	  break;
27873d8817e4Smiod 
27883d8817e4Smiod 	case OPTION_FORMATS_INFO:
27893d8817e4Smiod 	  formats_info = TRUE;
27903d8817e4Smiod 	  break;
27913d8817e4Smiod 
27923d8817e4Smiod 	case OPTION_WEAKEN:
27933d8817e4Smiod 	  weaken = TRUE;
27943d8817e4Smiod 	  break;
27953d8817e4Smiod 
27963d8817e4Smiod 	case OPTION_ADD_SECTION:
27973d8817e4Smiod 	  {
27983d8817e4Smiod 	    const char *s;
27993d8817e4Smiod 	    off_t size;
28003d8817e4Smiod 	    struct section_add *pa;
28013d8817e4Smiod 	    int len;
28023d8817e4Smiod 	    char *name;
28033d8817e4Smiod 	    FILE *f;
28043d8817e4Smiod 
28053d8817e4Smiod 	    s = strchr (optarg, '=');
28063d8817e4Smiod 
28073d8817e4Smiod 	    if (s == NULL)
28083d8817e4Smiod 	      fatal (_("bad format for %s"), "--add-section");
28093d8817e4Smiod 
28103d8817e4Smiod 	    size = get_file_size (s + 1);
28113d8817e4Smiod 	    if (size < 1)
28123d8817e4Smiod 	      break;
28133d8817e4Smiod 
28143d8817e4Smiod 	    pa = xmalloc (sizeof (struct section_add));
28153d8817e4Smiod 
28163d8817e4Smiod 	    len = s - optarg;
28173d8817e4Smiod 	    name = xmalloc (len + 1);
28183d8817e4Smiod 	    strncpy (name, optarg, len);
28193d8817e4Smiod 	    name[len] = '\0';
28203d8817e4Smiod 	    pa->name = name;
28213d8817e4Smiod 
28223d8817e4Smiod 	    pa->filename = s + 1;
28233d8817e4Smiod 	    pa->size = size;
28243d8817e4Smiod 	    pa->contents = xmalloc (size);
28253d8817e4Smiod 
28263d8817e4Smiod 	    f = fopen (pa->filename, FOPEN_RB);
28273d8817e4Smiod 
28283d8817e4Smiod 	    if (f == NULL)
28293d8817e4Smiod 	      fatal (_("cannot open: %s: %s"),
28303d8817e4Smiod 		     pa->filename, strerror (errno));
28313d8817e4Smiod 
28323d8817e4Smiod 	    if (fread (pa->contents, 1, pa->size, f) == 0
28333d8817e4Smiod 		|| ferror (f))
28343d8817e4Smiod 	      fatal (_("%s: fread failed"), pa->filename);
28353d8817e4Smiod 
28363d8817e4Smiod 	    fclose (f);
28373d8817e4Smiod 
28383d8817e4Smiod 	    pa->next = add_sections;
28393d8817e4Smiod 	    add_sections = pa;
28403d8817e4Smiod 	  }
28413d8817e4Smiod 	  break;
28423d8817e4Smiod 
28433d8817e4Smiod 	case OPTION_CHANGE_START:
28443d8817e4Smiod 	  change_start = parse_vma (optarg, "--change-start");
28453d8817e4Smiod 	  break;
28463d8817e4Smiod 
28473d8817e4Smiod 	case OPTION_CHANGE_SECTION_ADDRESS:
28483d8817e4Smiod 	case OPTION_CHANGE_SECTION_LMA:
28493d8817e4Smiod 	case OPTION_CHANGE_SECTION_VMA:
28503d8817e4Smiod 	  {
28513d8817e4Smiod 	    const char *s;
28523d8817e4Smiod 	    int len;
28533d8817e4Smiod 	    char *name;
28543d8817e4Smiod 	    char *option = NULL;
28553d8817e4Smiod 	    bfd_vma val;
28563d8817e4Smiod 	    enum change_action what = CHANGE_IGNORE;
28573d8817e4Smiod 
28583d8817e4Smiod 	    switch (c)
28593d8817e4Smiod 	      {
28603d8817e4Smiod 	      case OPTION_CHANGE_SECTION_ADDRESS:
28613d8817e4Smiod 		option = "--change-section-address";
28623d8817e4Smiod 		break;
28633d8817e4Smiod 	      case OPTION_CHANGE_SECTION_LMA:
28643d8817e4Smiod 		option = "--change-section-lma";
28653d8817e4Smiod 		break;
28663d8817e4Smiod 	      case OPTION_CHANGE_SECTION_VMA:
28673d8817e4Smiod 		option = "--change-section-vma";
28683d8817e4Smiod 		break;
28693d8817e4Smiod 	      }
28703d8817e4Smiod 
28713d8817e4Smiod 	    s = strchr (optarg, '=');
28723d8817e4Smiod 	    if (s == NULL)
28733d8817e4Smiod 	      {
28743d8817e4Smiod 		s = strchr (optarg, '+');
28753d8817e4Smiod 		if (s == NULL)
28763d8817e4Smiod 		  {
28773d8817e4Smiod 		    s = strchr (optarg, '-');
28783d8817e4Smiod 		    if (s == NULL)
28793d8817e4Smiod 		      fatal (_("bad format for %s"), option);
28803d8817e4Smiod 		  }
28813d8817e4Smiod 	      }
28823d8817e4Smiod 
28833d8817e4Smiod 	    len = s - optarg;
28843d8817e4Smiod 	    name = xmalloc (len + 1);
28853d8817e4Smiod 	    strncpy (name, optarg, len);
28863d8817e4Smiod 	    name[len] = '\0';
28873d8817e4Smiod 
28883d8817e4Smiod 	    p = find_section_list (name, TRUE);
28893d8817e4Smiod 
28903d8817e4Smiod 	    val = parse_vma (s + 1, option);
28913d8817e4Smiod 
28923d8817e4Smiod 	    switch (*s)
28933d8817e4Smiod 	      {
28943d8817e4Smiod 	      case '=': what = CHANGE_SET; break;
28953d8817e4Smiod 	      case '-': val  = - val; /* Drop through.  */
28963d8817e4Smiod 	      case '+': what = CHANGE_MODIFY; break;
28973d8817e4Smiod 	      }
28983d8817e4Smiod 
28993d8817e4Smiod 	    switch (c)
29003d8817e4Smiod 	      {
29013d8817e4Smiod 	      case OPTION_CHANGE_SECTION_ADDRESS:
29023d8817e4Smiod 		p->change_vma = what;
29033d8817e4Smiod 		p->vma_val    = val;
29043d8817e4Smiod 		/* Drop through.  */
29053d8817e4Smiod 
29063d8817e4Smiod 	      case OPTION_CHANGE_SECTION_LMA:
29073d8817e4Smiod 		p->change_lma = what;
29083d8817e4Smiod 		p->lma_val    = val;
29093d8817e4Smiod 		break;
29103d8817e4Smiod 
29113d8817e4Smiod 	      case OPTION_CHANGE_SECTION_VMA:
29123d8817e4Smiod 		p->change_vma = what;
29133d8817e4Smiod 		p->vma_val    = val;
29143d8817e4Smiod 		break;
29153d8817e4Smiod 	      }
29163d8817e4Smiod 	  }
29173d8817e4Smiod 	  break;
29183d8817e4Smiod 
29193d8817e4Smiod 	case OPTION_CHANGE_ADDRESSES:
29203d8817e4Smiod 	  change_section_address = parse_vma (optarg, "--change-addresses");
29213d8817e4Smiod 	  change_start = change_section_address;
29223d8817e4Smiod 	  break;
29233d8817e4Smiod 
29243d8817e4Smiod 	case OPTION_CHANGE_WARNINGS:
29253d8817e4Smiod 	  change_warn = TRUE;
29263d8817e4Smiod 	  break;
29273d8817e4Smiod 
29283d8817e4Smiod 	case OPTION_CHANGE_LEADING_CHAR:
29293d8817e4Smiod 	  change_leading_char = TRUE;
29303d8817e4Smiod 	  break;
29313d8817e4Smiod 
29323d8817e4Smiod 	case OPTION_DEBUGGING:
29333d8817e4Smiod 	  convert_debugging = TRUE;
29343d8817e4Smiod 	  break;
29353d8817e4Smiod 
29363d8817e4Smiod 	case OPTION_GAP_FILL:
29373d8817e4Smiod 	  {
29383d8817e4Smiod 	    bfd_vma gap_fill_vma;
29393d8817e4Smiod 
29403d8817e4Smiod 	    gap_fill_vma = parse_vma (optarg, "--gap-fill");
29413d8817e4Smiod 	    gap_fill = (bfd_byte) gap_fill_vma;
29423d8817e4Smiod 	    if ((bfd_vma) gap_fill != gap_fill_vma)
29433d8817e4Smiod 	      {
29443d8817e4Smiod 		char buff[20];
29453d8817e4Smiod 
29463d8817e4Smiod 		sprintf_vma (buff, gap_fill_vma);
29473d8817e4Smiod 
29483d8817e4Smiod 		non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
29493d8817e4Smiod 			   buff, gap_fill);
29503d8817e4Smiod 	      }
29513d8817e4Smiod 	    gap_fill_set = TRUE;
29523d8817e4Smiod 	  }
29533d8817e4Smiod 	  break;
29543d8817e4Smiod 
29553d8817e4Smiod 	case OPTION_NO_CHANGE_WARNINGS:
29563d8817e4Smiod 	  change_warn = FALSE;
29573d8817e4Smiod 	  break;
29583d8817e4Smiod 
29593d8817e4Smiod 	case OPTION_PAD_TO:
29603d8817e4Smiod 	  pad_to = parse_vma (optarg, "--pad-to");
29613d8817e4Smiod 	  pad_to_set = TRUE;
29623d8817e4Smiod 	  break;
29633d8817e4Smiod 
29643d8817e4Smiod 	case OPTION_REMOVE_LEADING_CHAR:
29653d8817e4Smiod 	  remove_leading_char = TRUE;
29663d8817e4Smiod 	  break;
29673d8817e4Smiod 
29683d8817e4Smiod 	case OPTION_REDEFINE_SYM:
29693d8817e4Smiod 	  {
29703d8817e4Smiod 	    /* Push this redefinition onto redefine_symbol_list.  */
29713d8817e4Smiod 
29723d8817e4Smiod 	    int len;
29733d8817e4Smiod 	    const char *s;
29743d8817e4Smiod 	    const char *nextarg;
29753d8817e4Smiod 	    char *source, *target;
29763d8817e4Smiod 
29773d8817e4Smiod 	    s = strchr (optarg, '=');
29783d8817e4Smiod 	    if (s == NULL)
29793d8817e4Smiod 	      fatal (_("bad format for %s"), "--redefine-sym");
29803d8817e4Smiod 
29813d8817e4Smiod 	    len = s - optarg;
29823d8817e4Smiod 	    source = xmalloc (len + 1);
29833d8817e4Smiod 	    strncpy (source, optarg, len);
29843d8817e4Smiod 	    source[len] = '\0';
29853d8817e4Smiod 
29863d8817e4Smiod 	    nextarg = s + 1;
29873d8817e4Smiod 	    len = strlen (nextarg);
29883d8817e4Smiod 	    target = xmalloc (len + 1);
29893d8817e4Smiod 	    strcpy (target, nextarg);
29903d8817e4Smiod 
29913d8817e4Smiod 	    redefine_list_append ("--redefine-sym", source, target);
29923d8817e4Smiod 
29933d8817e4Smiod 	    free (source);
29943d8817e4Smiod 	    free (target);
29953d8817e4Smiod 	  }
29963d8817e4Smiod 	  break;
29973d8817e4Smiod 
29983d8817e4Smiod 	case OPTION_REDEFINE_SYMS:
29993d8817e4Smiod 	  add_redefine_syms_file (optarg);
30003d8817e4Smiod 	  break;
30013d8817e4Smiod 
30023d8817e4Smiod 	case OPTION_SET_SECTION_FLAGS:
30033d8817e4Smiod 	  {
30043d8817e4Smiod 	    const char *s;
30053d8817e4Smiod 	    int len;
30063d8817e4Smiod 	    char *name;
30073d8817e4Smiod 
30083d8817e4Smiod 	    s = strchr (optarg, '=');
30093d8817e4Smiod 	    if (s == NULL)
30103d8817e4Smiod 	      fatal (_("bad format for %s"), "--set-section-flags");
30113d8817e4Smiod 
30123d8817e4Smiod 	    len = s - optarg;
30133d8817e4Smiod 	    name = xmalloc (len + 1);
30143d8817e4Smiod 	    strncpy (name, optarg, len);
30153d8817e4Smiod 	    name[len] = '\0';
30163d8817e4Smiod 
30173d8817e4Smiod 	    p = find_section_list (name, TRUE);
30183d8817e4Smiod 
30193d8817e4Smiod 	    p->set_flags = TRUE;
30203d8817e4Smiod 	    p->flags = parse_flags (s + 1);
30213d8817e4Smiod 	  }
30223d8817e4Smiod 	  break;
30233d8817e4Smiod 
30243d8817e4Smiod 	case OPTION_RENAME_SECTION:
30253d8817e4Smiod 	  {
30263d8817e4Smiod 	    flagword flags;
30273d8817e4Smiod 	    const char *eq, *fl;
30283d8817e4Smiod 	    char *old_name;
30293d8817e4Smiod 	    char *new_name;
30303d8817e4Smiod 	    unsigned int len;
30313d8817e4Smiod 
30323d8817e4Smiod 	    eq = strchr (optarg, '=');
30333d8817e4Smiod 	    if (eq == NULL)
30343d8817e4Smiod 	      fatal (_("bad format for %s"), "--rename-section");
30353d8817e4Smiod 
30363d8817e4Smiod 	    len = eq - optarg;
30373d8817e4Smiod 	    if (len == 0)
30383d8817e4Smiod 	      fatal (_("bad format for %s"), "--rename-section");
30393d8817e4Smiod 
30403d8817e4Smiod 	    old_name = xmalloc (len + 1);
30413d8817e4Smiod 	    strncpy (old_name, optarg, len);
30423d8817e4Smiod 	    old_name[len] = 0;
30433d8817e4Smiod 
30443d8817e4Smiod 	    eq++;
30453d8817e4Smiod 	    fl = strchr (eq, ',');
30463d8817e4Smiod 	    if (fl)
30473d8817e4Smiod 	      {
30483d8817e4Smiod 		flags = parse_flags (fl + 1);
30493d8817e4Smiod 		len = fl - eq;
30503d8817e4Smiod 	      }
30513d8817e4Smiod 	    else
30523d8817e4Smiod 	      {
30533d8817e4Smiod 		flags = -1;
30543d8817e4Smiod 		len = strlen (eq);
30553d8817e4Smiod 	      }
30563d8817e4Smiod 
30573d8817e4Smiod 	    if (len == 0)
30583d8817e4Smiod 	      fatal (_("bad format for %s"), "--rename-section");
30593d8817e4Smiod 
30603d8817e4Smiod 	    new_name = xmalloc (len + 1);
30613d8817e4Smiod 	    strncpy (new_name, eq, len);
30623d8817e4Smiod 	    new_name[len] = 0;
30633d8817e4Smiod 
30643d8817e4Smiod 	    add_section_rename (old_name, new_name, flags);
30653d8817e4Smiod 	  }
30663d8817e4Smiod 	  break;
30673d8817e4Smiod 
30683d8817e4Smiod 	case OPTION_SET_START:
30693d8817e4Smiod 	  set_start = parse_vma (optarg, "--set-start");
30703d8817e4Smiod 	  set_start_set = TRUE;
30713d8817e4Smiod 	  break;
30723d8817e4Smiod 
30733d8817e4Smiod 	case OPTION_SREC_LEN:
30743d8817e4Smiod 	  Chunk = parse_vma (optarg, "--srec-len");
30753d8817e4Smiod 	  break;
30763d8817e4Smiod 
30773d8817e4Smiod 	case OPTION_SREC_FORCES3:
30783d8817e4Smiod 	  S3Forced = TRUE;
30793d8817e4Smiod 	  break;
30803d8817e4Smiod 
30813d8817e4Smiod 	case OPTION_STRIP_SYMBOLS:
30823d8817e4Smiod 	  add_specific_symbols (optarg, &strip_specific_list);
30833d8817e4Smiod 	  break;
30843d8817e4Smiod 
30853d8817e4Smiod 	case OPTION_STRIP_UNNEEDED_SYMBOLS:
30863d8817e4Smiod 	  add_specific_symbols (optarg, &strip_unneeded_list);
30873d8817e4Smiod 	  break;
30883d8817e4Smiod 
30893d8817e4Smiod 	case OPTION_KEEP_SYMBOLS:
30903d8817e4Smiod 	  add_specific_symbols (optarg, &keep_specific_list);
30913d8817e4Smiod 	  break;
30923d8817e4Smiod 
3093c065f989Skettenis 	case OPTION_LOCALIZE_HIDDEN:
3094c065f989Skettenis 	  localize_hidden = TRUE;
3095c065f989Skettenis 	  break;
3096c065f989Skettenis 
30973d8817e4Smiod 	case OPTION_LOCALIZE_SYMBOLS:
30983d8817e4Smiod 	  add_specific_symbols (optarg, &localize_specific_list);
30993d8817e4Smiod 	  break;
31003d8817e4Smiod 
31013d8817e4Smiod 	case OPTION_GLOBALIZE_SYMBOLS:
31023d8817e4Smiod 	  add_specific_symbols (optarg, &globalize_specific_list);
31033d8817e4Smiod 	  break;
31043d8817e4Smiod 
31053d8817e4Smiod 	case OPTION_KEEPGLOBAL_SYMBOLS:
31063d8817e4Smiod 	  add_specific_symbols (optarg, &keepglobal_specific_list);
31073d8817e4Smiod 	  break;
31083d8817e4Smiod 
31093d8817e4Smiod 	case OPTION_WEAKEN_SYMBOLS:
31103d8817e4Smiod 	  add_specific_symbols (optarg, &weaken_specific_list);
31113d8817e4Smiod 	  break;
31123d8817e4Smiod 
31133d8817e4Smiod 	case OPTION_ALT_MACH_CODE:
31143d8817e4Smiod 	  use_alt_mach_code = strtoul (optarg, NULL, 0);
31153d8817e4Smiod 	  if (use_alt_mach_code == 0)
31163d8817e4Smiod 	    fatal (_("unable to parse alternative machine code"));
31173d8817e4Smiod 	  break;
31183d8817e4Smiod 
31193d8817e4Smiod 	case OPTION_PREFIX_SYMBOLS:
31203d8817e4Smiod 	  prefix_symbols_string = optarg;
31213d8817e4Smiod 	  break;
31223d8817e4Smiod 
31233d8817e4Smiod 	case OPTION_PREFIX_SECTIONS:
31243d8817e4Smiod 	  prefix_sections_string = optarg;
31253d8817e4Smiod 	  break;
31263d8817e4Smiod 
31273d8817e4Smiod 	case OPTION_PREFIX_ALLOC_SECTIONS:
31283d8817e4Smiod 	  prefix_alloc_sections_string = optarg;
31293d8817e4Smiod 	  break;
31303d8817e4Smiod 
31313d8817e4Smiod 	case OPTION_READONLY_TEXT:
31323d8817e4Smiod 	  bfd_flags_to_set |= WP_TEXT;
31333d8817e4Smiod 	  bfd_flags_to_clear &= ~WP_TEXT;
31343d8817e4Smiod 	  break;
31353d8817e4Smiod 
31363d8817e4Smiod 	case OPTION_WRITABLE_TEXT:
31373d8817e4Smiod 	  bfd_flags_to_clear |= WP_TEXT;
31383d8817e4Smiod 	  bfd_flags_to_set &= ~WP_TEXT;
31393d8817e4Smiod 	  break;
31403d8817e4Smiod 
31413d8817e4Smiod 	case OPTION_PURE:
31423d8817e4Smiod 	  bfd_flags_to_set |= D_PAGED;
31433d8817e4Smiod 	  bfd_flags_to_clear &= ~D_PAGED;
31443d8817e4Smiod 	  break;
31453d8817e4Smiod 
31463d8817e4Smiod 	case OPTION_IMPURE:
31473d8817e4Smiod 	  bfd_flags_to_clear |= D_PAGED;
31483d8817e4Smiod 	  bfd_flags_to_set &= ~D_PAGED;
31493d8817e4Smiod 	  break;
31503d8817e4Smiod 
31513d8817e4Smiod 	case 0:
31523d8817e4Smiod 	  /* We've been given a long option.  */
31533d8817e4Smiod 	  break;
31543d8817e4Smiod 
31553d8817e4Smiod 	case 'H':
31563d8817e4Smiod 	case 'h':
31573d8817e4Smiod 	  copy_usage (stdout, 0);
31583d8817e4Smiod 
31593d8817e4Smiod 	default:
31603d8817e4Smiod 	  copy_usage (stderr, 1);
31613d8817e4Smiod 	}
31623d8817e4Smiod     }
31633d8817e4Smiod 
31643d8817e4Smiod   if (formats_info)
31653d8817e4Smiod     {
31663d8817e4Smiod       display_info ();
31673d8817e4Smiod       return 0;
31683d8817e4Smiod     }
31693d8817e4Smiod 
31703d8817e4Smiod   if (show_version)
31713d8817e4Smiod     print_version ("objcopy");
31723d8817e4Smiod 
31733d8817e4Smiod   if (copy_byte >= interleave)
31743d8817e4Smiod     fatal (_("byte number must be less than interleave"));
31753d8817e4Smiod 
31763d8817e4Smiod   if (optind == argc || optind + 2 < argc)
31773d8817e4Smiod     copy_usage (stderr, 1);
31783d8817e4Smiod 
31793d8817e4Smiod   input_filename = argv[optind];
31803d8817e4Smiod   if (optind + 1 < argc)
31813d8817e4Smiod     output_filename = argv[optind + 1];
31823d8817e4Smiod 
31833d8817e4Smiod   /* Default is to strip no symbols.  */
31843d8817e4Smiod   if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
31853d8817e4Smiod     strip_symbols = STRIP_NONE;
31863d8817e4Smiod 
31873d8817e4Smiod   if (output_target == NULL)
31883d8817e4Smiod     output_target = input_target;
31893d8817e4Smiod 
31903d8817e4Smiod   if (binary_architecture != NULL)
31913d8817e4Smiod     {
31923d8817e4Smiod       if (input_target && strcmp (input_target, "binary") == 0)
31933d8817e4Smiod 	{
31943d8817e4Smiod 	  const bfd_arch_info_type * temp_arch_info;
31953d8817e4Smiod 
31963d8817e4Smiod 	  temp_arch_info = bfd_scan_arch (binary_architecture);
31973d8817e4Smiod 
31983d8817e4Smiod 	  if (temp_arch_info != NULL)
31993d8817e4Smiod 	    {
32003d8817e4Smiod 	      bfd_external_binary_architecture = temp_arch_info->arch;
32013d8817e4Smiod 	      bfd_external_machine             = temp_arch_info->mach;
32023d8817e4Smiod 	    }
32033d8817e4Smiod 	  else
32043d8817e4Smiod 	    fatal (_("architecture %s unknown"), binary_architecture);
32053d8817e4Smiod 	}
32063d8817e4Smiod       else
32073d8817e4Smiod 	{
32083d8817e4Smiod 	  non_fatal (_("Warning: input target 'binary' required for binary architecture parameter."));
32093d8817e4Smiod 	  non_fatal (_(" Argument %s ignored"), binary_architecture);
32103d8817e4Smiod 	}
32113d8817e4Smiod     }
32123d8817e4Smiod 
32133d8817e4Smiod   if (preserve_dates)
32143d8817e4Smiod     if (stat (input_filename, & statbuf) < 0)
32153d8817e4Smiod       fatal (_("warning: could not locate '%s'.  System error message: %s"),
32163d8817e4Smiod 	     input_filename, strerror (errno));
32173d8817e4Smiod 
32183d8817e4Smiod   /* If there is no destination file, or the source and destination files
32193d8817e4Smiod      are the same, then create a temp and rename the result into the input.  */
32203d8817e4Smiod   if (output_filename == NULL || strcmp (input_filename, output_filename) == 0)
32213d8817e4Smiod     {
3222d2386abeSmiod       char *tmpname = make_tempname (input_filename, 0);
32233d8817e4Smiod 
32243d8817e4Smiod       copy_file (input_filename, tmpname, input_target, output_target);
32253d8817e4Smiod       if (status == 0)
32263d8817e4Smiod 	{
32273d8817e4Smiod 	  if (preserve_dates)
32283d8817e4Smiod 	    set_times (tmpname, &statbuf);
32293d8817e4Smiod 	  smart_rename (tmpname, input_filename, preserve_dates);
32303d8817e4Smiod 	}
32313d8817e4Smiod       else
32323d8817e4Smiod 	unlink (tmpname);
32333d8817e4Smiod     }
32343d8817e4Smiod   else
32353d8817e4Smiod     {
32363d8817e4Smiod       copy_file (input_filename, output_filename, input_target, output_target);
32373d8817e4Smiod 
32383d8817e4Smiod       if (status == 0 && preserve_dates)
32393d8817e4Smiod 	set_times (output_filename, &statbuf);
32403d8817e4Smiod       else if (status != 0)
32413d8817e4Smiod 	unlink_if_ordinary (output_filename);
32423d8817e4Smiod     }
32433d8817e4Smiod 
32443d8817e4Smiod   if (change_warn)
32453d8817e4Smiod     {
32463d8817e4Smiod       for (p = change_sections; p != NULL; p = p->next)
32473d8817e4Smiod 	{
32483d8817e4Smiod 	  if (! p->used)
32493d8817e4Smiod 	    {
32503d8817e4Smiod 	      if (p->change_vma != CHANGE_IGNORE)
32513d8817e4Smiod 		{
32523d8817e4Smiod 		  char buff [20];
32533d8817e4Smiod 
32543d8817e4Smiod 		  sprintf_vma (buff, p->vma_val);
32553d8817e4Smiod 
32563d8817e4Smiod 		  /* xgettext:c-format */
32573d8817e4Smiod 		  non_fatal (_("%s %s%c0x%s never used"),
32583d8817e4Smiod 			     "--change-section-vma",
32593d8817e4Smiod 			     p->name,
32603d8817e4Smiod 			     p->change_vma == CHANGE_SET ? '=' : '+',
32613d8817e4Smiod 			     buff);
32623d8817e4Smiod 		}
32633d8817e4Smiod 
32643d8817e4Smiod 	      if (p->change_lma != CHANGE_IGNORE)
32653d8817e4Smiod 		{
32663d8817e4Smiod 		  char buff [20];
32673d8817e4Smiod 
32683d8817e4Smiod 		  sprintf_vma (buff, p->lma_val);
32693d8817e4Smiod 
32703d8817e4Smiod 		  /* xgettext:c-format */
32713d8817e4Smiod 		  non_fatal (_("%s %s%c0x%s never used"),
32723d8817e4Smiod 			     "--change-section-lma",
32733d8817e4Smiod 			     p->name,
32743d8817e4Smiod 			     p->change_lma == CHANGE_SET ? '=' : '+',
32753d8817e4Smiod 			     buff);
32763d8817e4Smiod 		}
32773d8817e4Smiod 	    }
32783d8817e4Smiod 	}
32793d8817e4Smiod     }
32803d8817e4Smiod 
32813d8817e4Smiod   return 0;
32823d8817e4Smiod }
32833d8817e4Smiod 
32843d8817e4Smiod int
main(int argc,char * argv[])32853d8817e4Smiod main (int argc, char *argv[])
32863d8817e4Smiod {
32873d8817e4Smiod #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
32883d8817e4Smiod   setlocale (LC_MESSAGES, "");
32893d8817e4Smiod #endif
32903d8817e4Smiod #if defined (HAVE_SETLOCALE)
32913d8817e4Smiod   setlocale (LC_CTYPE, "");
32923d8817e4Smiod #endif
32933d8817e4Smiod   bindtextdomain (PACKAGE, LOCALEDIR);
32943d8817e4Smiod   textdomain (PACKAGE);
32953d8817e4Smiod 
32963d8817e4Smiod   program_name = argv[0];
32973d8817e4Smiod   xmalloc_set_program_name (program_name);
32983d8817e4Smiod 
32993d8817e4Smiod   START_PROGRESS (program_name, 0);
33003d8817e4Smiod 
3301f9a4b902Sderaadt   if (pledge ("stdio rpath wpath cpath fattr", NULL) == -1)
3302f9a4b902Sderaadt     fatal (_("pledge: %s"), strerror (errno));
3303f9a4b902Sderaadt 
33043d8817e4Smiod   expandargv (&argc, &argv);
33053d8817e4Smiod 
33063d8817e4Smiod   strip_symbols = STRIP_UNDEF;
33073d8817e4Smiod   discard_locals = LOCALS_UNDEF;
33083d8817e4Smiod 
33093d8817e4Smiod   bfd_init ();
33103d8817e4Smiod   set_default_bfd_target ();
33113d8817e4Smiod 
33123d8817e4Smiod   if (is_strip < 0)
33133d8817e4Smiod     {
33143d8817e4Smiod       int i = strlen (program_name);
33153d8817e4Smiod #ifdef HAVE_DOS_BASED_FILE_SYSTEM
33163d8817e4Smiod       /* Drop the .exe suffix, if any.  */
33173d8817e4Smiod       if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0)
33183d8817e4Smiod 	{
33193d8817e4Smiod 	  i -= 4;
33203d8817e4Smiod 	  program_name[i] = '\0';
33213d8817e4Smiod 	}
33223d8817e4Smiod #endif
33233d8817e4Smiod       is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
33243d8817e4Smiod     }
33253d8817e4Smiod 
33263d8817e4Smiod   if (is_strip)
33273d8817e4Smiod     strip_main (argc, argv);
33283d8817e4Smiod   else
33293d8817e4Smiod     copy_main (argc, argv);
33303d8817e4Smiod 
33313d8817e4Smiod   END_PROGRESS (program_name);
33323d8817e4Smiod 
33333d8817e4Smiod   return status;
33343d8817e4Smiod }
3335