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