133965Sjdp/* objcopy.c -- copy object file from input to output, optionally massaging it. 278828Sobrien Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3218822Sdim 2001, 2002, 2003, 2004, 2005, 2006, 2007 438889Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GNU Binutils. 733965Sjdp 833965Sjdp This program is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2 of the License, or 1133965Sjdp (at your option) any later version. 1233965Sjdp 1333965Sjdp This program is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 23218822Sdim#include "sysdep.h" 2433965Sjdp#include "bfd.h" 2533965Sjdp#include "progress.h" 2633965Sjdp#include "getopt.h" 2733965Sjdp#include "libiberty.h" 28218822Sdim#include "bucomm.h" 2933965Sjdp#include "budbg.h" 3061843Sobrien#include "filenames.h" 31130561Sobrien#include "fnmatch.h" 32130561Sobrien#include "elf-bfd.h" 3333965Sjdp#include <sys/stat.h> 34218822Sdim#include "libbfd.h" 3533965Sjdp 3638889Sjdp/* A list of symbols to explicitly strip out, or to keep. A linked 3738889Sjdp list is good enough for a small number from the command line, but 3838889Sjdp this will slow things down a lot if many symbols are being 39104834Sobrien deleted. */ 4038889Sjdp 4138889Sjdpstruct symlist 4238889Sjdp{ 4338889Sjdp const char *name; 4438889Sjdp struct symlist *next; 4538889Sjdp}; 4638889Sjdp 4760484Sobrien/* A list to support redefine_sym. */ 4860484Sobrienstruct redefine_node 4960484Sobrien{ 5060484Sobrien char *source; 5160484Sobrien char *target; 5260484Sobrien struct redefine_node *next; 5360484Sobrien}; 5460484Sobrien 5589857Sobrientypedef struct section_rename 5689857Sobrien{ 5789857Sobrien const char * old_name; 5889857Sobrien const char * new_name; 5989857Sobrien flagword flags; 6089857Sobrien struct section_rename * next; 6189857Sobrien} 6289857Sobriensection_rename; 6389857Sobrien 6489857Sobrien/* List of sections to be renamed. */ 65130561Sobrienstatic section_rename *section_rename_list; 6689857Sobrien 6760484Sobrien#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;} 6833965Sjdp 69130561Sobrienstatic asymbol **isympp = NULL; /* Input symbols. */ 70130561Sobrienstatic asymbol **osympp = NULL; /* Output symbols that survive stripping. */ 7133965Sjdp 7233965Sjdp/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */ 7333965Sjdpstatic int copy_byte = -1; 7433965Sjdpstatic int interleave = 4; 7533965Sjdp 76130561Sobrienstatic bfd_boolean verbose; /* Print file and target names. */ 77130561Sobrienstatic bfd_boolean preserve_dates; /* Preserve input file timestamp. */ 7833965Sjdpstatic int status = 0; /* Exit status. */ 7933965Sjdp 8033965Sjdpenum strip_action 8133965Sjdp { 8260484Sobrien STRIP_UNDEF, 83130561Sobrien STRIP_NONE, /* Don't strip. */ 84130561Sobrien STRIP_DEBUG, /* Strip all debugger symbols. */ 85130561Sobrien STRIP_UNNEEDED, /* Strip unnecessary symbols. */ 86130561Sobrien STRIP_NONDEBUG, /* Strip everything but debug info. */ 87130561Sobrien STRIP_ALL /* Strip all symbols. */ 8833965Sjdp }; 8933965Sjdp 90104834Sobrien/* Which symbols to remove. */ 9133965Sjdpstatic enum strip_action strip_symbols; 9233965Sjdp 9333965Sjdpenum locals_action 9433965Sjdp { 9560484Sobrien LOCALS_UNDEF, 96130561Sobrien LOCALS_START_L, /* Discard locals starting with L. */ 97130561Sobrien LOCALS_ALL /* Discard all locals. */ 9833965Sjdp }; 9933965Sjdp 10060484Sobrien/* Which local symbols to remove. Overrides STRIP_ALL. */ 10133965Sjdpstatic enum locals_action discard_locals; 10233965Sjdp 10360484Sobrien/* What kind of change to perform. */ 10460484Sobrienenum change_action 10560484Sobrien{ 10660484Sobrien CHANGE_IGNORE, 10760484Sobrien CHANGE_MODIFY, 10860484Sobrien CHANGE_SET 10960484Sobrien}; 11060484Sobrien 11133965Sjdp/* Structure used to hold lists of sections and actions to take. */ 11233965Sjdpstruct section_list 11333965Sjdp{ 114130561Sobrien struct section_list * next; /* Next section to change. */ 115130561Sobrien const char * name; /* Section name. */ 116130561Sobrien bfd_boolean used; /* Whether this entry was used. */ 117130561Sobrien bfd_boolean remove; /* Whether to remove this section. */ 118130561Sobrien bfd_boolean copy; /* Whether to copy this section. */ 119130561Sobrien enum change_action change_vma;/* Whether to change or set VMA. */ 120130561Sobrien bfd_vma vma_val; /* Amount to change by or set to. */ 121130561Sobrien enum change_action change_lma;/* Whether to change or set LMA. */ 122130561Sobrien bfd_vma lma_val; /* Amount to change by or set to. */ 123130561Sobrien bfd_boolean set_flags; /* Whether to set the section flags. */ 124130561Sobrien flagword flags; /* What to set the section flags to. */ 12533965Sjdp}; 12633965Sjdp 12760484Sobrienstatic struct section_list *change_sections; 12889857Sobrien 129130561Sobrien/* TRUE if some sections are to be removed. */ 130130561Sobrienstatic bfd_boolean sections_removed; 13189857Sobrien 132130561Sobrien/* TRUE if only some sections are to be copied. */ 133130561Sobrienstatic bfd_boolean sections_copied; 13433965Sjdp 13560484Sobrien/* Changes to the start address. */ 13660484Sobrienstatic bfd_vma change_start = 0; 137130561Sobrienstatic bfd_boolean set_start_set = FALSE; 13833965Sjdpstatic bfd_vma set_start; 13933965Sjdp 14060484Sobrien/* Changes to section addresses. */ 14160484Sobrienstatic bfd_vma change_section_address = 0; 14233965Sjdp 14333965Sjdp/* Filling gaps between sections. */ 144130561Sobrienstatic bfd_boolean gap_fill_set = FALSE; 14533965Sjdpstatic bfd_byte gap_fill = 0; 14633965Sjdp 14733965Sjdp/* Pad to a given address. */ 148130561Sobrienstatic bfd_boolean pad_to_set = FALSE; 14933965Sjdpstatic bfd_vma pad_to; 15033965Sjdp 151218822Sdim/* Use alternative machine code? */ 152218822Sdimstatic unsigned long use_alt_mach_code = 0; 15389857Sobrien 154130561Sobrien/* Output BFD flags user wants to set or clear */ 155130561Sobrienstatic flagword bfd_flags_to_set; 156130561Sobrienstatic flagword bfd_flags_to_clear; 157130561Sobrien 15833965Sjdp/* List of sections to add. */ 15933965Sjdpstruct section_add 16033965Sjdp{ 16133965Sjdp /* Next section to add. */ 16233965Sjdp struct section_add *next; 16333965Sjdp /* Name of section to add. */ 16433965Sjdp const char *name; 16533965Sjdp /* Name of file holding section contents. */ 16633965Sjdp const char *filename; 16733965Sjdp /* Size of file. */ 16833965Sjdp size_t size; 16933965Sjdp /* Contents of file. */ 17033965Sjdp bfd_byte *contents; 17133965Sjdp /* BFD section, after it has been added. */ 17233965Sjdp asection *section; 17333965Sjdp}; 17433965Sjdp 17589857Sobrien/* List of sections to add to the output BFD. */ 17633965Sjdpstatic struct section_add *add_sections; 17733965Sjdp 178130561Sobrien/* If non-NULL the argument to --add-gnu-debuglink. 179130561Sobrien This should be the filename to store in the .gnu_debuglink section. */ 180130561Sobrienstatic const char * gnu_debuglink_filename = NULL; 181130561Sobrien 18233965Sjdp/* Whether to convert debugging information. */ 183130561Sobrienstatic bfd_boolean convert_debugging = FALSE; 18433965Sjdp 18533965Sjdp/* Whether to change the leading character in symbol names. */ 186130561Sobrienstatic bfd_boolean change_leading_char = FALSE; 18733965Sjdp 18833965Sjdp/* Whether to remove the leading character from global symbol names. */ 189130561Sobrienstatic bfd_boolean remove_leading_char = FALSE; 19033965Sjdp 191130561Sobrien/* Whether to permit wildcard in symbol comparison. */ 192130561Sobrienstatic bfd_boolean wildcard = FALSE; 193130561Sobrien 194218822Sdim/* True if --localize-hidden is in effect. */ 195218822Sdimstatic bfd_boolean localize_hidden = FALSE; 196218822Sdim 19778828Sobrien/* List of symbols to strip, keep, localize, keep-global, weaken, 19878828Sobrien or redefine. */ 19938889Sjdpstatic struct symlist *strip_specific_list = NULL; 200218822Sdimstatic struct symlist *strip_unneeded_list = NULL; 20138889Sjdpstatic struct symlist *keep_specific_list = NULL; 20238889Sjdpstatic struct symlist *localize_specific_list = NULL; 203218822Sdimstatic struct symlist *globalize_specific_list = NULL; 20478828Sobrienstatic struct symlist *keepglobal_specific_list = NULL; 20538889Sjdpstatic struct symlist *weaken_specific_list = NULL; 20660484Sobrienstatic struct redefine_node *redefine_sym_list = NULL; 20738889Sjdp 208130561Sobrien/* If this is TRUE, we weaken global symbols (set BSF_WEAK). */ 209130561Sobrienstatic bfd_boolean weaken = FALSE; 21038889Sjdp 211218822Sdim/* If this is TRUE, we retain BSF_FILE symbols. */ 212218822Sdimstatic bfd_boolean keep_file_symbols = FALSE; 213218822Sdim 214130561Sobrien/* Prefix symbols/sections. */ 215130561Sobrienstatic char *prefix_symbols_string = 0; 216130561Sobrienstatic char *prefix_sections_string = 0; 217130561Sobrienstatic char *prefix_alloc_sections_string = 0; 218130561Sobrien 219218822Sdim/* True if --extract-symbol was passed on the command line. */ 220218822Sdimstatic bfd_boolean extract_symbol = FALSE; 221218822Sdim 222218822Sdim/* If `reverse_bytes' is nonzero, then reverse the order of every chunk 223218822Sdim of <reverse_bytes> bytes within each output section. */ 224218822Sdimstatic int reverse_bytes = 0; 225218822Sdim 226218822Sdim 22733965Sjdp/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ 228130561Sobrienenum command_line_switch 229130561Sobrien { 230130561Sobrien OPTION_ADD_SECTION=150, 231130561Sobrien OPTION_CHANGE_ADDRESSES, 232130561Sobrien OPTION_CHANGE_LEADING_CHAR, 233130561Sobrien OPTION_CHANGE_START, 234130561Sobrien OPTION_CHANGE_SECTION_ADDRESS, 235130561Sobrien OPTION_CHANGE_SECTION_LMA, 236130561Sobrien OPTION_CHANGE_SECTION_VMA, 237130561Sobrien OPTION_CHANGE_WARNINGS, 238130561Sobrien OPTION_DEBUGGING, 239130561Sobrien OPTION_GAP_FILL, 240130561Sobrien OPTION_NO_CHANGE_WARNINGS, 241130561Sobrien OPTION_PAD_TO, 242130561Sobrien OPTION_REMOVE_LEADING_CHAR, 243130561Sobrien OPTION_SET_SECTION_FLAGS, 244130561Sobrien OPTION_SET_START, 245130561Sobrien OPTION_STRIP_UNNEEDED, 246130561Sobrien OPTION_WEAKEN, 247130561Sobrien OPTION_REDEFINE_SYM, 248130561Sobrien OPTION_REDEFINE_SYMS, 249130561Sobrien OPTION_SREC_LEN, 250130561Sobrien OPTION_SREC_FORCES3, 251130561Sobrien OPTION_STRIP_SYMBOLS, 252218822Sdim OPTION_STRIP_UNNEEDED_SYMBOL, 253218822Sdim OPTION_STRIP_UNNEEDED_SYMBOLS, 254130561Sobrien OPTION_KEEP_SYMBOLS, 255218822Sdim OPTION_LOCALIZE_HIDDEN, 256130561Sobrien OPTION_LOCALIZE_SYMBOLS, 257218822Sdim OPTION_GLOBALIZE_SYMBOL, 258218822Sdim OPTION_GLOBALIZE_SYMBOLS, 259130561Sobrien OPTION_KEEPGLOBAL_SYMBOLS, 260130561Sobrien OPTION_WEAKEN_SYMBOLS, 261130561Sobrien OPTION_RENAME_SECTION, 262130561Sobrien OPTION_ALT_MACH_CODE, 263130561Sobrien OPTION_PREFIX_SYMBOLS, 264130561Sobrien OPTION_PREFIX_SECTIONS, 265130561Sobrien OPTION_PREFIX_ALLOC_SECTIONS, 266130561Sobrien OPTION_FORMATS_INFO, 267130561Sobrien OPTION_ADD_GNU_DEBUGLINK, 268130561Sobrien OPTION_ONLY_KEEP_DEBUG, 269218822Sdim OPTION_KEEP_FILE_SYMBOLS, 270130561Sobrien OPTION_READONLY_TEXT, 271130561Sobrien OPTION_WRITABLE_TEXT, 272130561Sobrien OPTION_PURE, 273218822Sdim OPTION_IMPURE, 274218822Sdim OPTION_EXTRACT_SYMBOL, 275218822Sdim OPTION_REVERSE_BYTES 276130561Sobrien }; 27733965Sjdp 27833965Sjdp/* Options to handle if running as "strip". */ 27933965Sjdp 28033965Sjdpstatic struct option strip_options[] = 28133965Sjdp{ 28233965Sjdp {"discard-all", no_argument, 0, 'x'}, 28333965Sjdp {"discard-locals", no_argument, 0, 'X'}, 28433965Sjdp {"format", required_argument, 0, 'F'}, /* Obsolete */ 28533965Sjdp {"help", no_argument, 0, 'h'}, 286130561Sobrien {"info", no_argument, 0, OPTION_FORMATS_INFO}, 28733965Sjdp {"input-format", required_argument, 0, 'I'}, /* Obsolete */ 28833965Sjdp {"input-target", required_argument, 0, 'I'}, 289218822Sdim {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, 29033965Sjdp {"keep-symbol", required_argument, 0, 'K'}, 291130561Sobrien {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG}, 29233965Sjdp {"output-format", required_argument, 0, 'O'}, /* Obsolete */ 29333965Sjdp {"output-target", required_argument, 0, 'O'}, 29480016Sobrien {"output-file", required_argument, 0, 'o'}, 29533965Sjdp {"preserve-dates", no_argument, 0, 'p'}, 29633965Sjdp {"remove-section", required_argument, 0, 'R'}, 29733965Sjdp {"strip-all", no_argument, 0, 's'}, 29833965Sjdp {"strip-debug", no_argument, 0, 'S'}, 29933965Sjdp {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, 30033965Sjdp {"strip-symbol", required_argument, 0, 'N'}, 30133965Sjdp {"target", required_argument, 0, 'F'}, 30233965Sjdp {"verbose", no_argument, 0, 'v'}, 30333965Sjdp {"version", no_argument, 0, 'V'}, 304130561Sobrien {"wildcard", no_argument, 0, 'w'}, 30533965Sjdp {0, no_argument, 0, 0} 30633965Sjdp}; 30733965Sjdp 30833965Sjdp/* Options to handle if running as "objcopy". */ 30933965Sjdp 31033965Sjdpstatic struct option copy_options[] = 31133965Sjdp{ 312130561Sobrien {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK}, 31333965Sjdp {"add-section", required_argument, 0, OPTION_ADD_SECTION}, 31460484Sobrien {"adjust-start", required_argument, 0, OPTION_CHANGE_START}, 31560484Sobrien {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES}, 31660484Sobrien {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS}, 31760484Sobrien {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS}, 318130561Sobrien {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE}, 31989857Sobrien {"binary-architecture", required_argument, 0, 'B'}, 32033965Sjdp {"byte", required_argument, 0, 'b'}, 32160484Sobrien {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES}, 32233965Sjdp {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR}, 32360484Sobrien {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS}, 32460484Sobrien {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA}, 32560484Sobrien {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA}, 32660484Sobrien {"change-start", required_argument, 0, OPTION_CHANGE_START}, 32760484Sobrien {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS}, 32833965Sjdp {"debugging", no_argument, 0, OPTION_DEBUGGING}, 32933965Sjdp {"discard-all", no_argument, 0, 'x'}, 33033965Sjdp {"discard-locals", no_argument, 0, 'X'}, 331218822Sdim {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL}, 33233965Sjdp {"format", required_argument, 0, 'F'}, /* Obsolete */ 33333965Sjdp {"gap-fill", required_argument, 0, OPTION_GAP_FILL}, 334218822Sdim {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL}, 335218822Sdim {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS}, 33633965Sjdp {"help", no_argument, 0, 'h'}, 337130561Sobrien {"impure", no_argument, 0, OPTION_IMPURE}, 338130561Sobrien {"info", no_argument, 0, OPTION_FORMATS_INFO}, 33933965Sjdp {"input-format", required_argument, 0, 'I'}, /* Obsolete */ 34033965Sjdp {"input-target", required_argument, 0, 'I'}, 34133965Sjdp {"interleave", required_argument, 0, 'i'}, 342218822Sdim {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS}, 343130561Sobrien {"keep-global-symbol", required_argument, 0, 'G'}, 344130561Sobrien {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS}, 34533965Sjdp {"keep-symbol", required_argument, 0, 'K'}, 346130561Sobrien {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS}, 347218822Sdim {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN}, 348130561Sobrien {"localize-symbol", required_argument, 0, 'L'}, 349130561Sobrien {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS}, 35060484Sobrien {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS}, 35160484Sobrien {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS}, 352130561Sobrien {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG}, 353130561Sobrien {"only-section", required_argument, 0, 'j'}, 35433965Sjdp {"output-format", required_argument, 0, 'O'}, /* Obsolete */ 35533965Sjdp {"output-target", required_argument, 0, 'O'}, 35633965Sjdp {"pad-to", required_argument, 0, OPTION_PAD_TO}, 357130561Sobrien {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS}, 358130561Sobrien {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS}, 359130561Sobrien {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS}, 36033965Sjdp {"preserve-dates", no_argument, 0, 'p'}, 361130561Sobrien {"pure", no_argument, 0, OPTION_PURE}, 362130561Sobrien {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT}, 363130561Sobrien {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM}, 364130561Sobrien {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS}, 36533965Sjdp {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR}, 36633965Sjdp {"remove-section", required_argument, 0, 'R'}, 36789857Sobrien {"rename-section", required_argument, 0, OPTION_RENAME_SECTION}, 368218822Sdim {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES}, 36933965Sjdp {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, 37033965Sjdp {"set-start", required_argument, 0, OPTION_SET_START}, 371130561Sobrien {"srec-len", required_argument, 0, OPTION_SREC_LEN}, 372130561Sobrien {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3}, 37333965Sjdp {"strip-all", no_argument, 0, 'S'}, 37433965Sjdp {"strip-debug", no_argument, 0, 'g'}, 37533965Sjdp {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED}, 376218822Sdim {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL}, 377218822Sdim {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS}, 37833965Sjdp {"strip-symbol", required_argument, 0, 'N'}, 379130561Sobrien {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS}, 38033965Sjdp {"target", required_argument, 0, 'F'}, 38133965Sjdp {"verbose", no_argument, 0, 'v'}, 38233965Sjdp {"version", no_argument, 0, 'V'}, 38333965Sjdp {"weaken", no_argument, 0, OPTION_WEAKEN}, 38438889Sjdp {"weaken-symbol", required_argument, 0, 'W'}, 38578828Sobrien {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS}, 386130561Sobrien {"wildcard", no_argument, 0, 'w'}, 387130561Sobrien {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT}, 38833965Sjdp {0, no_argument, 0, 0} 38933965Sjdp}; 39033965Sjdp 39133965Sjdp/* IMPORTS */ 39233965Sjdpextern char *program_name; 39333965Sjdp 39433965Sjdp/* This flag distinguishes between strip and objcopy: 39533965Sjdp 1 means this is 'strip'; 0 means this is 'objcopy'. 396104834Sobrien -1 means if we should use argv[0] to decide. */ 39733965Sjdpextern int is_strip; 39833965Sjdp 39977298Sobrien/* The maximum length of an S record. This variable is declared in srec.c 40077298Sobrien and can be modified by the --srec-len parameter. */ 40177298Sobrienextern unsigned int Chunk; 40233965Sjdp 40377298Sobrien/* Restrict the generation of Srecords to type S3 only. 40477298Sobrien This variable is declare in bfd/srec.c and can be toggled 40577298Sobrien on by the --srec-forceS3 command line switch. */ 406130561Sobrienextern bfd_boolean S3Forced; 40777298Sobrien 408130561Sobrien/* Defined in bfd/binary.c. Used to set architecture and machine of input 409130561Sobrien binary files. */ 410130561Sobrienextern enum bfd_architecture bfd_external_binary_architecture; 411130561Sobrienextern unsigned long bfd_external_machine; 41289857Sobrien 413130561Sobrien/* Forward declarations. */ 414130561Sobrienstatic void setup_section (bfd *, asection *, void *); 415218822Sdimstatic void setup_bfd_headers (bfd *, bfd *); 416130561Sobrienstatic void copy_section (bfd *, asection *, void *); 417130561Sobrienstatic void get_sections (bfd *, asection *, void *); 418130561Sobrienstatic int compare_section_lma (const void *, const void *); 419130561Sobrienstatic void mark_symbols_used_in_relocations (bfd *, asection *, void *); 420130561Sobrienstatic bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***); 421130561Sobrienstatic const char *lookup_sym_redefinition (const char *); 42289857Sobrien 42333965Sjdpstatic void 424130561Sobriencopy_usage (FILE *stream, int exit_status) 42533965Sjdp{ 42689857Sobrien fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name); 42789857Sobrien fprintf (stream, _(" Copies a binary file, possibly transforming it in the process\n")); 42889857Sobrien fprintf (stream, _(" The options are:\n")); 42960484Sobrien fprintf (stream, _("\ 43060484Sobrien -I --input-target <bfdname> Assume input file is in format <bfdname>\n\ 43160484Sobrien -O --output-target <bfdname> Create an output file in format <bfdname>\n\ 43289857Sobrien -B --binary-architecture <arch> Set arch of output file, when input is binary\n\ 43360484Sobrien -F --target <bfdname> Set both input and output format to <bfdname>\n\ 43460484Sobrien --debugging Convert debugging information, if possible\n\ 43560484Sobrien -p --preserve-dates Copy modified/access timestamps to the output\n\ 43660484Sobrien -j --only-section <name> Only copy section <name> into the output\n\ 437130561Sobrien --add-gnu-debuglink=<file> Add section .gnu_debuglink linking to <file>\n\ 43860484Sobrien -R --remove-section <name> Remove section <name> from the output\n\ 43960484Sobrien -S --strip-all Remove all symbol and relocation information\n\ 440130561Sobrien -g --strip-debug Remove all debugging symbols & sections\n\ 44160484Sobrien --strip-unneeded Remove all symbols not needed by relocations\n\ 44260484Sobrien -N --strip-symbol <name> Do not copy symbol <name>\n\ 443218822Sdim --strip-unneeded-symbol <name>\n\ 444218822Sdim Do not copy symbol <name> unless needed by\n\ 445218822Sdim relocations\n\ 446130561Sobrien --only-keep-debug Strip everything but the debug information\n\ 447218822Sdim --extract-symbol Remove section contents but keep symbols\n\ 448218822Sdim -K --keep-symbol <name> Do not strip symbol <name>\n\ 449218822Sdim --keep-file-symbols Do not strip file symbol(s)\n\ 450218822Sdim --localize-hidden Turn all ELF hidden symbols into locals\n\ 45160484Sobrien -L --localize-symbol <name> Force symbol <name> to be marked as a local\n\ 452218822Sdim --globalize-symbol <name> Force symbol <name> to be marked as a global\n\ 45378828Sobrien -G --keep-global-symbol <name> Localize all symbols except <name>\n\ 45460484Sobrien -W --weaken-symbol <name> Force symbol <name> to be marked as a weak\n\ 45560484Sobrien --weaken Force all global symbols to be marked as weak\n\ 456218822Sdim -w --wildcard Permit wildcard in symbol comparison\n\ 45760484Sobrien -x --discard-all Remove all non-global symbols\n\ 45860484Sobrien -X --discard-locals Remove any compiler-generated symbols\n\ 45960484Sobrien -i --interleave <number> Only copy one out of every <number> bytes\n\ 46060484Sobrien -b --byte <num> Select byte <num> in every interleaved block\n\ 46160484Sobrien --gap-fill <val> Fill gaps between sections with <val>\n\ 46260484Sobrien --pad-to <addr> Pad the last section up to address <addr>\n\ 46360484Sobrien --set-start <addr> Set the start address to <addr>\n\ 46460484Sobrien {--change-start|--adjust-start} <incr>\n\ 46560484Sobrien Add <incr> to the start address\n\ 46660484Sobrien {--change-addresses|--adjust-vma} <incr>\n\ 46760484Sobrien Add <incr> to LMA, VMA and start addresses\n\ 46860484Sobrien {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\ 46960484Sobrien Change LMA and VMA of section <name> by <val>\n\ 47060484Sobrien --change-section-lma <name>{=|+|-}<val>\n\ 47160484Sobrien Change the LMA of section <name> by <val>\n\ 47260484Sobrien --change-section-vma <name>{=|+|-}<val>\n\ 47360484Sobrien Change the VMA of section <name> by <val>\n\ 47460484Sobrien {--[no-]change-warnings|--[no-]adjust-warnings}\n\ 47560484Sobrien Warn if a named section does not exist\n\ 47660484Sobrien --set-section-flags <name>=<flags>\n\ 47760484Sobrien Set section <name>'s properties to <flags>\n\ 47860484Sobrien --add-section <name>=<file> Add section <name> found in <file> to output\n\ 47989857Sobrien --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\ 48060484Sobrien --change-leading-char Force output format's leading character style\n\ 48160484Sobrien --remove-leading-char Remove leading character from global symbols\n\ 482218822Sdim --reverse-bytes=<num> Reverse <num> bytes at a time, in output sections with content\n\ 48360484Sobrien --redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\ 484130561Sobrien --redefine-syms <file> --redefine-sym for all symbol pairs \n\ 485130561Sobrien listed in <file>\n\ 48677298Sobrien --srec-len <number> Restrict the length of generated Srecords\n\ 48777298Sobrien --srec-forceS3 Restrict the type of generated Srecords to S3\n\ 48878828Sobrien --strip-symbols <file> -N for all symbols listed in <file>\n\ 489218822Sdim --strip-unneeded-symbols <file>\n\ 490218822Sdim --strip-unneeded-symbol for all symbols listed\n\ 491218822Sdim in <file>\n\ 49278828Sobrien --keep-symbols <file> -K for all symbols listed in <file>\n\ 49378828Sobrien --localize-symbols <file> -L for all symbols listed in <file>\n\ 494218822Sdim --globalize-symbols <file> --globalize-symbol for all in <file>\n\ 49578828Sobrien --keep-global-symbols <file> -G for all symbols listed in <file>\n\ 49678828Sobrien --weaken-symbols <file> -W for all symbols listed in <file>\n\ 497218822Sdim --alt-machine-code <index> Use the target's <index>'th alternative machine\n\ 498130561Sobrien --writable-text Mark the output text as writable\n\ 499130561Sobrien --readonly-text Make the output text write protected\n\ 500130561Sobrien --pure Mark the output file as demand paged\n\ 501130561Sobrien --impure Mark the output file as impure\n\ 502130561Sobrien --prefix-symbols <prefix> Add <prefix> to start of every symbol name\n\ 503130561Sobrien --prefix-sections <prefix> Add <prefix> to start of every section name\n\ 504130561Sobrien --prefix-alloc-sections <prefix>\n\ 505130561Sobrien Add <prefix> to start of every allocatable\n\ 506130561Sobrien section name\n\ 50760484Sobrien -v --verbose List all object files modified\n\ 508218822Sdim @<file> Read options from <file>\n\ 50960484Sobrien -V --version Display this program's version number\n\ 51060484Sobrien -h --help Display this output\n\ 511130561Sobrien --info List object formats & architectures supported\n\ 51260484Sobrien")); 51333965Sjdp list_supported_targets (program_name, stream); 514218822Sdim if (REPORT_BUGS_TO[0] && exit_status == 0) 51560484Sobrien fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 51633965Sjdp exit (exit_status); 51733965Sjdp} 51833965Sjdp 51933965Sjdpstatic void 520130561Sobrienstrip_usage (FILE *stream, int exit_status) 52133965Sjdp{ 52289857Sobrien fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name); 52389857Sobrien fprintf (stream, _(" Removes symbols and sections from files\n")); 52489857Sobrien fprintf (stream, _(" The options are:\n")); 52560484Sobrien fprintf (stream, _("\ 52689857Sobrien -I --input-target=<bfdname> Assume input file is in format <bfdname>\n\ 52789857Sobrien -O --output-target=<bfdname> Create an output file in format <bfdname>\n\ 52889857Sobrien -F --target=<bfdname> Set both input and output format to <bfdname>\n\ 52960484Sobrien -p --preserve-dates Copy modified/access timestamps to the output\n\ 53089857Sobrien -R --remove-section=<name> Remove section <name> from the output\n\ 53160484Sobrien -s --strip-all Remove all symbol and relocation information\n\ 532130561Sobrien -g -S -d --strip-debug Remove all debugging symbols & sections\n\ 53360484Sobrien --strip-unneeded Remove all symbols not needed by relocations\n\ 534130561Sobrien --only-keep-debug Strip everything but the debug information\n\ 53589857Sobrien -N --strip-symbol=<name> Do not copy symbol <name>\n\ 536218822Sdim -K --keep-symbol=<name> Do not strip symbol <name>\n\ 537218822Sdim --keep-file-symbols Do not strip file symbol(s)\n\ 538218822Sdim -w --wildcard Permit wildcard in symbol comparison\n\ 53960484Sobrien -x --discard-all Remove all non-global symbols\n\ 54060484Sobrien -X --discard-locals Remove any compiler-generated symbols\n\ 54160484Sobrien -v --verbose List all object files modified\n\ 54260484Sobrien -V --version Display this program's version number\n\ 54360484Sobrien -h --help Display this output\n\ 544130561Sobrien --info List object formats & architectures supported\n\ 54560484Sobrien -o <file> Place stripped output into <file>\n\ 54660484Sobrien")); 54760484Sobrien 54833965Sjdp list_supported_targets (program_name, stream); 549218822Sdim if (REPORT_BUGS_TO[0] && exit_status == 0) 55060484Sobrien fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 55133965Sjdp exit (exit_status); 55233965Sjdp} 55333965Sjdp 55433965Sjdp/* Parse section flags into a flagword, with a fatal error if the 55533965Sjdp string can't be parsed. */ 55633965Sjdp 55733965Sjdpstatic flagword 558130561Sobrienparse_flags (const char *s) 55933965Sjdp{ 56033965Sjdp flagword ret; 56133965Sjdp const char *snext; 56233965Sjdp int len; 56333965Sjdp 56433965Sjdp ret = SEC_NO_FLAGS; 56533965Sjdp 56633965Sjdp do 56733965Sjdp { 56833965Sjdp snext = strchr (s, ','); 56933965Sjdp if (snext == NULL) 57033965Sjdp len = strlen (s); 57133965Sjdp else 57233965Sjdp { 57333965Sjdp len = snext - s; 57433965Sjdp ++snext; 57533965Sjdp } 57633965Sjdp 57738889Sjdp if (0) ; 57838889Sjdp#define PARSE_FLAG(fname,fval) \ 57938889Sjdp else if (strncasecmp (fname, s, len) == 0) ret |= fval 58033965Sjdp PARSE_FLAG ("alloc", SEC_ALLOC); 58133965Sjdp PARSE_FLAG ("load", SEC_LOAD); 58260484Sobrien PARSE_FLAG ("noload", SEC_NEVER_LOAD); 58333965Sjdp PARSE_FLAG ("readonly", SEC_READONLY); 58460484Sobrien PARSE_FLAG ("debug", SEC_DEBUGGING); 58533965Sjdp PARSE_FLAG ("code", SEC_CODE); 58633965Sjdp PARSE_FLAG ("data", SEC_DATA); 58733965Sjdp PARSE_FLAG ("rom", SEC_ROM); 588218822Sdim PARSE_FLAG ("share", SEC_COFF_SHARED); 58938889Sjdp PARSE_FLAG ("contents", SEC_HAS_CONTENTS); 59033965Sjdp#undef PARSE_FLAG 59138889Sjdp else 59238889Sjdp { 59338889Sjdp char *copy; 59433965Sjdp 59538889Sjdp copy = xmalloc (len + 1); 59638889Sjdp strncpy (copy, s, len); 59738889Sjdp copy[len] = '\0'; 59860484Sobrien non_fatal (_("unrecognized section flag `%s'"), copy); 59960484Sobrien fatal (_("supported flags: %s"), 60060484Sobrien "alloc, load, noload, readonly, debug, code, data, rom, share, contents"); 60138889Sjdp } 60238889Sjdp 60333965Sjdp s = snext; 60433965Sjdp } 60533965Sjdp while (s != NULL); 60633965Sjdp 60733965Sjdp return ret; 60833965Sjdp} 60933965Sjdp 61060484Sobrien/* Find and optionally add an entry in the change_sections list. */ 61133965Sjdp 61233965Sjdpstatic struct section_list * 613130561Sobrienfind_section_list (const char *name, bfd_boolean add) 61433965Sjdp{ 615130561Sobrien struct section_list *p; 61633965Sjdp 61760484Sobrien for (p = change_sections; p != NULL; p = p->next) 61833965Sjdp if (strcmp (p->name, name) == 0) 61933965Sjdp return p; 62033965Sjdp 62133965Sjdp if (! add) 62233965Sjdp return NULL; 62333965Sjdp 624130561Sobrien p = xmalloc (sizeof (struct section_list)); 62533965Sjdp p->name = name; 626130561Sobrien p->used = FALSE; 627130561Sobrien p->remove = FALSE; 628130561Sobrien p->copy = FALSE; 62960484Sobrien p->change_vma = CHANGE_IGNORE; 63060484Sobrien p->change_lma = CHANGE_IGNORE; 63160484Sobrien p->vma_val = 0; 63260484Sobrien p->lma_val = 0; 633130561Sobrien p->set_flags = FALSE; 63433965Sjdp p->flags = 0; 63533965Sjdp 63660484Sobrien p->next = change_sections; 63760484Sobrien change_sections = p; 63833965Sjdp 63933965Sjdp return p; 64033965Sjdp} 64133965Sjdp 64233965Sjdp/* Add a symbol to strip_specific_list. */ 64333965Sjdp 64460484Sobrienstatic void 645130561Sobrienadd_specific_symbol (const char *name, struct symlist **list) 64633965Sjdp{ 64733965Sjdp struct symlist *tmp_list; 64833965Sjdp 649130561Sobrien tmp_list = xmalloc (sizeof (struct symlist)); 65033965Sjdp tmp_list->name = name; 65138889Sjdp tmp_list->next = *list; 65238889Sjdp *list = tmp_list; 65333965Sjdp} 65433965Sjdp 655104834Sobrien/* Add symbols listed in `filename' to strip_specific_list. */ 65678828Sobrien 65778828Sobrien#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t') 65878828Sobrien#define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') 65978828Sobrien 66078828Sobrienstatic void 661130561Sobrienadd_specific_symbols (const char *filename, struct symlist **list) 66278828Sobrien{ 663130561Sobrien off_t size; 66478828Sobrien FILE * f; 66578828Sobrien char * line; 66678828Sobrien char * buffer; 66778828Sobrien unsigned int line_count; 668104834Sobrien 669130561Sobrien size = get_file_size (filename); 670130561Sobrien if (size == 0) 671218822Sdim { 672218822Sdim status = 1; 673218822Sdim return; 674218822Sdim } 67578828Sobrien 676130561Sobrien buffer = xmalloc (size + 2); 67778828Sobrien f = fopen (filename, FOPEN_RT); 67878828Sobrien if (f == NULL) 679130561Sobrien fatal (_("cannot open '%s': %s"), filename, strerror (errno)); 68078828Sobrien 681130561Sobrien if (fread (buffer, 1, size, f) == 0 || ferror (f)) 68278828Sobrien fatal (_("%s: fread failed"), filename); 68378828Sobrien 68478828Sobrien fclose (f); 685130561Sobrien buffer [size] = '\n'; 686130561Sobrien buffer [size + 1] = '\0'; 68778828Sobrien 68878828Sobrien line_count = 1; 689104834Sobrien 69078828Sobrien for (line = buffer; * line != '\0'; line ++) 69178828Sobrien { 69278828Sobrien char * eol; 69378828Sobrien char * name; 69478828Sobrien char * name_end; 695130561Sobrien int finished = FALSE; 69678828Sobrien 69778828Sobrien for (eol = line;; eol ++) 69878828Sobrien { 69978828Sobrien switch (* eol) 70078828Sobrien { 70178828Sobrien case '\n': 70278828Sobrien * eol = '\0'; 70378828Sobrien /* Cope with \n\r. */ 70478828Sobrien if (eol[1] == '\r') 70578828Sobrien ++ eol; 706130561Sobrien finished = TRUE; 70778828Sobrien break; 708104834Sobrien 70978828Sobrien case '\r': 71078828Sobrien * eol = '\0'; 71178828Sobrien /* Cope with \r\n. */ 71278828Sobrien if (eol[1] == '\n') 71378828Sobrien ++ eol; 714130561Sobrien finished = TRUE; 71578828Sobrien break; 716104834Sobrien 71778828Sobrien case 0: 718130561Sobrien finished = TRUE; 71978828Sobrien break; 720104834Sobrien 72178828Sobrien case '#': 72278828Sobrien /* Line comment, Terminate the line here, in case a 72378828Sobrien name is present and then allow the rest of the 72478828Sobrien loop to find the real end of the line. */ 72578828Sobrien * eol = '\0'; 72678828Sobrien break; 727104834Sobrien 72878828Sobrien default: 72978828Sobrien break; 73078828Sobrien } 73178828Sobrien 73278828Sobrien if (finished) 73378828Sobrien break; 73478828Sobrien } 73578828Sobrien 73678828Sobrien /* A name may now exist somewhere between 'line' and 'eol'. 73778828Sobrien Strip off leading whitespace and trailing whitespace, 73878828Sobrien then add it to the list. */ 73978828Sobrien for (name = line; IS_WHITESPACE (* name); name ++) 74078828Sobrien ; 74178828Sobrien for (name_end = name; 74278828Sobrien (! IS_WHITESPACE (* name_end)) 74378828Sobrien && (! IS_LINE_TERMINATOR (* name_end)); 744104834Sobrien name_end ++) 745104834Sobrien ; 74678828Sobrien 74778828Sobrien if (! IS_LINE_TERMINATOR (* name_end)) 74878828Sobrien { 74978828Sobrien char * extra; 75078828Sobrien 75178828Sobrien for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++) 75278828Sobrien ; 75378828Sobrien 75478828Sobrien if (! IS_LINE_TERMINATOR (* extra)) 755218822Sdim non_fatal (_("%s:%d: Ignoring rubbish found on this line"), 756218822Sdim filename, line_count); 75778828Sobrien } 758104834Sobrien 75978828Sobrien * name_end = '\0'; 76078828Sobrien 76178828Sobrien if (name_end > name) 76278828Sobrien add_specific_symbol (name, list); 76378828Sobrien 76478828Sobrien /* Advance line pointer to end of line. The 'eol ++' in the for 76578828Sobrien loop above will then advance us to the start of the next line. */ 76678828Sobrien line = eol; 76778828Sobrien line_count ++; 76878828Sobrien } 76978828Sobrien} 77078828Sobrien 77133965Sjdp/* See whether a symbol should be stripped or kept based on 77233965Sjdp strip_specific_list and keep_symbols. */ 77333965Sjdp 774130561Sobrienstatic bfd_boolean 775130561Sobrienis_specified_symbol (const char *name, struct symlist *list) 77633965Sjdp{ 77733965Sjdp struct symlist *tmp_list; 77833965Sjdp 779130561Sobrien if (wildcard) 780130561Sobrien { 781130561Sobrien for (tmp_list = list; tmp_list; tmp_list = tmp_list->next) 782130561Sobrien if (*(tmp_list->name) != '!') 783130561Sobrien { 784130561Sobrien if (!fnmatch (tmp_list->name, name, 0)) 785130561Sobrien return TRUE; 786130561Sobrien } 787130561Sobrien else 788130561Sobrien { 789130561Sobrien if (fnmatch (tmp_list->name + 1, name, 0)) 790130561Sobrien return TRUE; 791130561Sobrien } 792130561Sobrien } 793130561Sobrien else 794130561Sobrien { 795130561Sobrien for (tmp_list = list; tmp_list; tmp_list = tmp_list->next) 796130561Sobrien if (strcmp (name, tmp_list->name) == 0) 797130561Sobrien return TRUE; 798130561Sobrien } 79989857Sobrien 800130561Sobrien return FALSE; 80133965Sjdp} 80233965Sjdp 803218822Sdim/* Return a pointer to the symbol used as a signature for GROUP. */ 804218822Sdim 805218822Sdimstatic asymbol * 806218822Sdimgroup_signature (asection *group) 807218822Sdim{ 808218822Sdim bfd *abfd = group->owner; 809218822Sdim Elf_Internal_Shdr *ghdr; 810218822Sdim 811218822Sdim if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) 812218822Sdim return NULL; 813218822Sdim 814218822Sdim ghdr = &elf_section_data (group)->this_hdr; 815218822Sdim if (ghdr->sh_link < elf_numsections (abfd)) 816218822Sdim { 817218822Sdim const struct elf_backend_data *bed = get_elf_backend_data (abfd); 818218822Sdim Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link]; 819218822Sdim 820218822Sdim if (symhdr->sh_type == SHT_SYMTAB 821218822Sdim && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym) 822218822Sdim return isympp[ghdr->sh_info - 1]; 823218822Sdim } 824218822Sdim return NULL; 825218822Sdim} 826218822Sdim 82733965Sjdp/* See if a section is being removed. */ 82833965Sjdp 829130561Sobrienstatic bfd_boolean 830130561Sobrienis_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) 83133965Sjdp{ 832130561Sobrien if (sections_removed || sections_copied) 833130561Sobrien { 834130561Sobrien struct section_list *p; 83533965Sjdp 836130561Sobrien p = find_section_list (bfd_get_section_name (abfd, sec), FALSE); 837130561Sobrien 838130561Sobrien if (sections_removed && p != NULL && p->remove) 839130561Sobrien return TRUE; 840130561Sobrien if (sections_copied && (p == NULL || ! p->copy)) 841130561Sobrien return TRUE; 842130561Sobrien } 843130561Sobrien 844130561Sobrien if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0) 845130561Sobrien { 846130561Sobrien if (strip_symbols == STRIP_DEBUG 84760484Sobrien || strip_symbols == STRIP_UNNEEDED 84860484Sobrien || strip_symbols == STRIP_ALL 84960484Sobrien || discard_locals == LOCALS_ALL 850130561Sobrien || convert_debugging) 851130561Sobrien return TRUE; 85233965Sjdp 853130561Sobrien if (strip_symbols == STRIP_NONDEBUG) 854130561Sobrien return FALSE; 855130561Sobrien } 85660484Sobrien 857218822Sdim if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0) 858218822Sdim { 859218822Sdim asymbol *gsym; 860218822Sdim const char *gname; 861218822Sdim 862218822Sdim /* PR binutils/3166 863218822Sdim Group sections look like debugging sections but they are not. 864218822Sdim (They have a non-zero size but they are not ALLOCated). */ 865218822Sdim if (strip_symbols == STRIP_NONDEBUG) 866218822Sdim return TRUE; 867218822Sdim 868218822Sdim /* PR binutils/3181 869218822Sdim If we are going to strip the group signature symbol, then 870218822Sdim strip the group section too. */ 871218822Sdim gsym = group_signature (sec); 872218822Sdim if (gsym != NULL) 873218822Sdim gname = gsym->name; 874218822Sdim else 875218822Sdim gname = sec->name; 876218822Sdim if ((strip_symbols == STRIP_ALL 877218822Sdim && !is_specified_symbol (gname, keep_specific_list)) 878218822Sdim || is_specified_symbol (gname, strip_specific_list)) 879218822Sdim return TRUE; 880218822Sdim } 881218822Sdim 882130561Sobrien return FALSE; 88333965Sjdp} 88433965Sjdp 885218822Sdim/* Return true if SYM is a hidden symbol. */ 886218822Sdim 887218822Sdimstatic bfd_boolean 888218822Sdimis_hidden_symbol (asymbol *sym) 889218822Sdim{ 890218822Sdim elf_symbol_type *elf_sym; 891218822Sdim 892218822Sdim elf_sym = elf_symbol_from (sym->the_bfd, sym); 893218822Sdim if (elf_sym != NULL) 894218822Sdim switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other)) 895218822Sdim { 896218822Sdim case STV_HIDDEN: 897218822Sdim case STV_INTERNAL: 898218822Sdim return TRUE; 899218822Sdim } 900218822Sdim return FALSE; 901218822Sdim} 902218822Sdim 90333965Sjdp/* Choose which symbol entries to copy; put the result in OSYMS. 90433965Sjdp We don't copy in place, because that confuses the relocs. 90533965Sjdp Return the number of symbols to print. */ 90633965Sjdp 90733965Sjdpstatic unsigned int 908130561Sobrienfilter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, 909130561Sobrien asymbol **isyms, long symcount) 91033965Sjdp{ 911130561Sobrien asymbol **from = isyms, **to = osyms; 91233965Sjdp long src_count = 0, dst_count = 0; 913218822Sdim int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; 91433965Sjdp 91533965Sjdp for (; src_count < symcount; src_count++) 91633965Sjdp { 91733965Sjdp asymbol *sym = from[src_count]; 91833965Sjdp flagword flags = sym->flags; 919130561Sobrien char *name = (char *) bfd_asymbol_name (sym); 920218822Sdim bfd_boolean keep; 921218822Sdim bfd_boolean used_in_reloc = FALSE; 922130561Sobrien bfd_boolean undefined; 923130561Sobrien bfd_boolean rem_leading_char; 924130561Sobrien bfd_boolean add_leading_char; 92533965Sjdp 926130561Sobrien undefined = bfd_is_und_section (bfd_get_section (sym)); 927130561Sobrien 92860484Sobrien if (redefine_sym_list) 92960484Sobrien { 930130561Sobrien char *old_name, *new_name; 93160484Sobrien 932130561Sobrien old_name = (char *) bfd_asymbol_name (sym); 933130561Sobrien new_name = (char *) lookup_sym_redefinition (old_name); 934130561Sobrien bfd_asymbol_name (sym) = new_name; 935130561Sobrien name = new_name; 93660484Sobrien } 93760484Sobrien 938130561Sobrien /* Check if we will remove the current leading character. */ 939130561Sobrien rem_leading_char = 940130561Sobrien (name[0] == bfd_get_symbol_leading_char (abfd)) 941130561Sobrien && (change_leading_char 942130561Sobrien || (remove_leading_char 943130561Sobrien && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0 944130561Sobrien || undefined 945130561Sobrien || bfd_is_com_section (bfd_get_section (sym))))); 94633965Sjdp 947130561Sobrien /* Check if we will add a new leading character. */ 948130561Sobrien add_leading_char = 949130561Sobrien change_leading_char 950130561Sobrien && (bfd_get_symbol_leading_char (obfd) != '\0') 951130561Sobrien && (bfd_get_symbol_leading_char (abfd) == '\0' 952130561Sobrien || (name[0] == bfd_get_symbol_leading_char (abfd))); 95333965Sjdp 954130561Sobrien /* Short circuit for change_leading_char if we can do it in-place. */ 955130561Sobrien if (rem_leading_char && add_leading_char && !prefix_symbols_string) 956130561Sobrien { 957130561Sobrien name[0] = bfd_get_symbol_leading_char (obfd); 958130561Sobrien bfd_asymbol_name (sym) = name; 959130561Sobrien rem_leading_char = FALSE; 960130561Sobrien add_leading_char = FALSE; 961130561Sobrien } 96289857Sobrien 963130561Sobrien /* Remove leading char. */ 964130561Sobrien if (rem_leading_char) 965130561Sobrien bfd_asymbol_name (sym) = ++name; 96633965Sjdp 967130561Sobrien /* Add new leading char and/or prefix. */ 968130561Sobrien if (add_leading_char || prefix_symbols_string) 969130561Sobrien { 970130561Sobrien char *n, *ptr; 971130561Sobrien 972130561Sobrien ptr = n = xmalloc (1 + strlen (prefix_symbols_string) 973130561Sobrien + strlen (name) + 1); 974130561Sobrien if (add_leading_char) 975130561Sobrien *ptr++ = bfd_get_symbol_leading_char (obfd); 976130561Sobrien 977130561Sobrien if (prefix_symbols_string) 978130561Sobrien { 979130561Sobrien strcpy (ptr, prefix_symbols_string); 980130561Sobrien ptr += strlen (prefix_symbols_string); 981130561Sobrien } 982130561Sobrien 983130561Sobrien strcpy (ptr, name); 984130561Sobrien bfd_asymbol_name (sym) = n; 985130561Sobrien name = n; 986130561Sobrien } 987130561Sobrien 98860484Sobrien if (strip_symbols == STRIP_ALL) 989218822Sdim keep = FALSE; 99060484Sobrien else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */ 99160484Sobrien || ((flags & BSF_SECTION_SYM) != 0 99260484Sobrien && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags 99360484Sobrien & BSF_KEEP) != 0)) 994218822Sdim { 995218822Sdim keep = TRUE; 996218822Sdim used_in_reloc = TRUE; 997218822Sdim } 998104834Sobrien else if (relocatable /* Relocatable file. */ 99977298Sobrien && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0) 1000218822Sdim keep = TRUE; 100178828Sobrien else if (bfd_decode_symclass (sym) == 'I') 100278828Sobrien /* Global symbols in $idata sections need to be retained 1003130561Sobrien even if relocatable is FALSE. External users of the 100478828Sobrien library containing the $idata section may reference these 100578828Sobrien symbols. */ 1006218822Sdim keep = TRUE; 100733965Sjdp else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ 100833965Sjdp || (flags & BSF_WEAK) != 0 100989857Sobrien || undefined 101033965Sjdp || bfd_is_com_section (bfd_get_section (sym))) 101160484Sobrien keep = strip_symbols != STRIP_UNNEEDED; 101233965Sjdp else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */ 101360484Sobrien keep = (strip_symbols != STRIP_DEBUG 101460484Sobrien && strip_symbols != STRIP_UNNEEDED 101533965Sjdp && ! convert_debugging); 1016218822Sdim else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym))) 101780016Sobrien /* COMDAT sections store special information in local 101880016Sobrien symbols, so we cannot risk stripping any of them. */ 1019218822Sdim keep = TRUE; 102033965Sjdp else /* Local symbol. */ 102160484Sobrien keep = (strip_symbols != STRIP_UNNEEDED 102260484Sobrien && (discard_locals != LOCALS_ALL 102360484Sobrien && (discard_locals != LOCALS_START_L 102433965Sjdp || ! bfd_is_local_label (abfd, sym)))); 102533965Sjdp 102638889Sjdp if (keep && is_specified_symbol (name, strip_specific_list)) 1027218822Sdim { 1028218822Sdim /* There are multiple ways to set 'keep' above, but if it 1029218822Sdim was the relocatable symbol case, then that's an error. */ 1030218822Sdim if (used_in_reloc) 1031218822Sdim { 1032218822Sdim non_fatal (_("not stripping symbol `%s' because it is named in a relocation"), name); 1033218822Sdim status = 1; 1034218822Sdim } 1035218822Sdim else 1036218822Sdim keep = FALSE; 1037218822Sdim } 1038218822Sdim 1039218822Sdim if (keep 1040218822Sdim && !(flags & BSF_KEEP) 1041218822Sdim && is_specified_symbol (name, strip_unneeded_list)) 1042218822Sdim keep = FALSE; 1043218822Sdim 1044218822Sdim if (!keep 1045218822Sdim && ((keep_file_symbols && (flags & BSF_FILE)) 1046218822Sdim || is_specified_symbol (name, keep_specific_list))) 1047218822Sdim keep = TRUE; 1048218822Sdim 104933965Sjdp if (keep && is_strip_section (abfd, bfd_get_section (sym))) 1050218822Sdim keep = FALSE; 105133965Sjdp 1052218822Sdim if (keep) 105333965Sjdp { 1054218822Sdim if ((flags & BSF_GLOBAL) != 0 1055218822Sdim && (weaken || is_specified_symbol (name, weaken_specific_list))) 1056218822Sdim { 1057218822Sdim sym->flags &= ~ BSF_GLOBAL; 1058218822Sdim sym->flags |= BSF_WEAK; 1059218822Sdim } 1060218822Sdim 1061218822Sdim if (!undefined 1062218822Sdim && (flags & (BSF_GLOBAL | BSF_WEAK)) 1063218822Sdim && (is_specified_symbol (name, localize_specific_list) 1064218822Sdim || (keepglobal_specific_list != NULL 1065218822Sdim && ! is_specified_symbol (name, keepglobal_specific_list)) 1066218822Sdim || (localize_hidden && is_hidden_symbol (sym)))) 1067218822Sdim { 1068218822Sdim sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK); 1069218822Sdim sym->flags |= BSF_LOCAL; 1070218822Sdim } 1071218822Sdim 1072218822Sdim if (!undefined 1073218822Sdim && (flags & BSF_LOCAL) 1074218822Sdim && is_specified_symbol (name, globalize_specific_list)) 1075218822Sdim { 1076218822Sdim sym->flags &= ~ BSF_LOCAL; 1077218822Sdim sym->flags |= BSF_GLOBAL; 1078218822Sdim } 1079218822Sdim 1080218822Sdim to[dst_count++] = sym; 108133965Sjdp } 108233965Sjdp } 108333965Sjdp 108433965Sjdp to[dst_count] = NULL; 108533965Sjdp 108633965Sjdp return dst_count; 108733965Sjdp} 108833965Sjdp 108989857Sobrien/* Find the redefined name of symbol SOURCE. */ 109089857Sobrien 109160484Sobrienstatic const char * 1092130561Sobrienlookup_sym_redefinition (const char *source) 109360484Sobrien{ 109460484Sobrien struct redefine_node *list; 109560484Sobrien 109689857Sobrien for (list = redefine_sym_list; list != NULL; list = list->next) 109789857Sobrien if (strcmp (source, list->source) == 0) 109889857Sobrien return list->target; 109960484Sobrien 110089857Sobrien return source; 110160484Sobrien} 110260484Sobrien 110389857Sobrien/* Add a node to a symbol redefine list. */ 110460484Sobrien 110560484Sobrienstatic void 1106130561Sobrienredefine_list_append (const char *cause, const char *source, const char *target) 110760484Sobrien{ 110860484Sobrien struct redefine_node **p; 110960484Sobrien struct redefine_node *list; 111060484Sobrien struct redefine_node *new_node; 111160484Sobrien 111260484Sobrien for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next) 111360484Sobrien { 111460484Sobrien if (strcmp (source, list->source) == 0) 111589857Sobrien fatal (_("%s: Multiple redefinition of symbol \"%s\""), 1116130561Sobrien cause, source); 111760484Sobrien 111860484Sobrien if (strcmp (target, list->target) == 0) 111989857Sobrien fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"), 1120130561Sobrien cause, target); 112160484Sobrien } 112260484Sobrien 1123130561Sobrien new_node = xmalloc (sizeof (struct redefine_node)); 112460484Sobrien 112560484Sobrien new_node->source = strdup (source); 112660484Sobrien new_node->target = strdup (target); 112760484Sobrien new_node->next = NULL; 112860484Sobrien 112960484Sobrien *p = new_node; 113060484Sobrien} 113160484Sobrien 1132130561Sobrien/* Handle the --redefine-syms option. Read lines containing "old new" 1133130561Sobrien from the file, and add them to the symbol redefine list. */ 113433965Sjdp 113533965Sjdpstatic void 1136130561Sobrienadd_redefine_syms_file (const char *filename) 113733965Sjdp{ 1138130561Sobrien FILE *file; 1139130561Sobrien char *buf; 1140130561Sobrien size_t bufsize; 1141130561Sobrien size_t len; 1142130561Sobrien size_t outsym_off; 1143130561Sobrien int c, lineno; 114433965Sjdp 1145130561Sobrien file = fopen (filename, "r"); 1146130561Sobrien if (file == NULL) 1147130561Sobrien fatal (_("couldn't open symbol redefinition file %s (error: %s)"), 1148130561Sobrien filename, strerror (errno)); 114989857Sobrien 1150130561Sobrien bufsize = 100; 1151130561Sobrien buf = xmalloc (bufsize); 1152130561Sobrien 1153130561Sobrien lineno = 1; 1154130561Sobrien c = getc (file); 1155130561Sobrien len = 0; 1156130561Sobrien outsym_off = 0; 1157130561Sobrien while (c != EOF) 1158130561Sobrien { 1159130561Sobrien /* Collect the input symbol name. */ 1160130561Sobrien while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF) 1161130561Sobrien { 1162130561Sobrien if (c == '#') 1163130561Sobrien goto comment; 1164130561Sobrien buf[len++] = c; 1165130561Sobrien if (len >= bufsize) 1166130561Sobrien { 1167130561Sobrien bufsize *= 2; 1168130561Sobrien buf = xrealloc (buf, bufsize); 1169130561Sobrien } 1170130561Sobrien c = getc (file); 1171130561Sobrien } 1172130561Sobrien buf[len++] = '\0'; 1173130561Sobrien if (c == EOF) 1174130561Sobrien break; 1175130561Sobrien 1176130561Sobrien /* Eat white space between the symbol names. */ 1177130561Sobrien while (IS_WHITESPACE (c)) 1178130561Sobrien c = getc (file); 1179130561Sobrien if (c == '#' || IS_LINE_TERMINATOR (c)) 1180130561Sobrien goto comment; 1181130561Sobrien if (c == EOF) 1182130561Sobrien break; 1183130561Sobrien 1184130561Sobrien /* Collect the output symbol name. */ 1185130561Sobrien outsym_off = len; 1186130561Sobrien while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF) 1187130561Sobrien { 1188130561Sobrien if (c == '#') 1189130561Sobrien goto comment; 1190130561Sobrien buf[len++] = c; 1191130561Sobrien if (len >= bufsize) 1192130561Sobrien { 1193130561Sobrien bufsize *= 2; 1194130561Sobrien buf = xrealloc (buf, bufsize); 1195130561Sobrien } 1196130561Sobrien c = getc (file); 1197130561Sobrien } 1198130561Sobrien buf[len++] = '\0'; 1199130561Sobrien if (c == EOF) 1200130561Sobrien break; 1201130561Sobrien 1202130561Sobrien /* Eat white space at end of line. */ 1203130561Sobrien while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c)) 1204130561Sobrien c = getc (file); 1205130561Sobrien if (c == '#') 1206130561Sobrien goto comment; 1207130561Sobrien /* Handle \r\n. */ 1208130561Sobrien if ((c == '\r' && (c = getc (file)) == '\n') 1209130561Sobrien || c == '\n' || c == EOF) 1210130561Sobrien { 1211130561Sobrien end_of_line: 1212130561Sobrien /* Append the redefinition to the list. */ 1213130561Sobrien if (buf[0] != '\0') 1214130561Sobrien redefine_list_append (filename, &buf[0], &buf[outsym_off]); 1215130561Sobrien 1216218822Sdim lineno++; 1217130561Sobrien len = 0; 1218130561Sobrien outsym_off = 0; 1219130561Sobrien if (c == EOF) 1220130561Sobrien break; 1221130561Sobrien c = getc (file); 1222130561Sobrien continue; 1223130561Sobrien } 1224130561Sobrien else 1225218822Sdim fatal (_("%s:%d: garbage found at end of line"), filename, lineno); 1226130561Sobrien comment: 1227130561Sobrien if (len != 0 && (outsym_off == 0 || outsym_off == len)) 1228218822Sdim fatal (_("%s:%d: missing new symbol name"), filename, lineno); 1229130561Sobrien buf[len++] = '\0'; 1230130561Sobrien 1231130561Sobrien /* Eat the rest of the line and finish it. */ 1232130561Sobrien while (c != '\n' && c != EOF) 1233130561Sobrien c = getc (file); 1234130561Sobrien goto end_of_line; 1235130561Sobrien } 1236130561Sobrien 1237130561Sobrien if (len != 0) 1238218822Sdim fatal (_("%s:%d: premature end of file"), filename, lineno); 1239130561Sobrien 1240130561Sobrien free (buf); 124133965Sjdp} 124233965Sjdp 1243218822Sdim/* Copy unkown object file IBFD onto OBFD. 1244218822Sdim Returns TRUE upon success, FALSE otherwise. */ 1245218822Sdim 1246218822Sdimstatic bfd_boolean 1247218822Sdimcopy_unknown_object (bfd *ibfd, bfd *obfd) 1248218822Sdim{ 1249218822Sdim char *cbuf; 1250218822Sdim int tocopy; 1251218822Sdim long ncopied; 1252218822Sdim long size; 1253218822Sdim struct stat buf; 1254218822Sdim 1255218822Sdim if (bfd_stat_arch_elt (ibfd, &buf) != 0) 1256218822Sdim { 1257218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1258218822Sdim return FALSE; 1259218822Sdim } 1260218822Sdim 1261218822Sdim size = buf.st_size; 1262218822Sdim if (size < 0) 1263218822Sdim { 1264218822Sdim non_fatal (_("stat returns negative size for `%s'"), 1265218822Sdim bfd_get_archive_filename (ibfd)); 1266218822Sdim return FALSE; 1267218822Sdim } 1268218822Sdim 1269218822Sdim if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0) 1270218822Sdim { 1271218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1272218822Sdim return FALSE; 1273218822Sdim } 1274218822Sdim 1275218822Sdim if (verbose) 1276218822Sdim printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"), 1277218822Sdim bfd_get_archive_filename (ibfd), bfd_get_filename (obfd)); 1278218822Sdim 1279218822Sdim cbuf = xmalloc (BUFSIZE); 1280218822Sdim ncopied = 0; 1281218822Sdim while (ncopied < size) 1282218822Sdim { 1283218822Sdim tocopy = size - ncopied; 1284218822Sdim if (tocopy > BUFSIZE) 1285218822Sdim tocopy = BUFSIZE; 1286218822Sdim 1287218822Sdim if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd) 1288218822Sdim != (bfd_size_type) tocopy) 1289218822Sdim { 1290218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1291218822Sdim free (cbuf); 1292218822Sdim return FALSE; 1293218822Sdim } 1294218822Sdim 1295218822Sdim if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd) 1296218822Sdim != (bfd_size_type) tocopy) 1297218822Sdim { 1298218822Sdim bfd_nonfatal (bfd_get_filename (obfd)); 1299218822Sdim free (cbuf); 1300218822Sdim return FALSE; 1301218822Sdim } 1302218822Sdim 1303218822Sdim ncopied += tocopy; 1304218822Sdim } 1305218822Sdim 1306218822Sdim chmod (bfd_get_filename (obfd), buf.st_mode); 1307218822Sdim free (cbuf); 1308218822Sdim return TRUE; 1309218822Sdim} 1310218822Sdim 1311130561Sobrien/* Copy object file IBFD onto OBFD. 1312130561Sobrien Returns TRUE upon success, FALSE otherwise. */ 131333965Sjdp 1314130561Sobrienstatic bfd_boolean 1315130561Sobriencopy_object (bfd *ibfd, bfd *obfd) 131633965Sjdp{ 131733965Sjdp bfd_vma start; 131833965Sjdp long symcount; 131933965Sjdp asection **osections = NULL; 1320130561Sobrien asection *gnu_debuglink_section = NULL; 132133965Sjdp bfd_size_type *gaps = NULL; 132233965Sjdp bfd_size_type max_gap = 0; 132360484Sobrien long symsize; 1324130561Sobrien void *dhandle; 1325130561Sobrien enum bfd_architecture iarch; 1326130561Sobrien unsigned int imach; 132733965Sjdp 132877298Sobrien if (ibfd->xvec->byteorder != obfd->xvec->byteorder 132977298Sobrien && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN 133077298Sobrien && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) 1331130561Sobrien fatal (_("Unable to change endianness of input file(s)")); 1332130561Sobrien 1333130561Sobrien if (!bfd_set_format (obfd, bfd_get_format (ibfd))) 133477298Sobrien { 1335130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1336130561Sobrien return FALSE; 133777298Sobrien } 133860484Sobrien 133933965Sjdp if (verbose) 1340218822Sdim printf (_("copy from `%s' [%s] to `%s' [%s]\n"), 1341218822Sdim bfd_get_archive_filename (ibfd), bfd_get_target (ibfd), 134260484Sobrien bfd_get_filename (obfd), bfd_get_target (obfd)); 134333965Sjdp 1344218822Sdim if (extract_symbol) 1345218822Sdim start = 0; 134633965Sjdp else 1347218822Sdim { 1348218822Sdim if (set_start_set) 1349218822Sdim start = set_start; 1350218822Sdim else 1351218822Sdim start = bfd_get_start_address (ibfd); 1352218822Sdim start += change_start; 1353218822Sdim } 135433965Sjdp 1355104834Sobrien /* Neither the start address nor the flags 1356104834Sobrien need to be set for a core file. */ 135789857Sobrien if (bfd_get_format (obfd) != bfd_core) 135889857Sobrien { 1359130561Sobrien flagword flags; 1360130561Sobrien 1361130561Sobrien flags = bfd_get_file_flags (ibfd); 1362130561Sobrien flags |= bfd_flags_to_set; 1363130561Sobrien flags &= ~bfd_flags_to_clear; 1364130561Sobrien flags &= bfd_applicable_file_flags (obfd); 1365130561Sobrien 136689857Sobrien if (!bfd_set_start_address (obfd, start) 1367130561Sobrien || !bfd_set_file_flags (obfd, flags)) 1368130561Sobrien { 1369218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1370130561Sobrien return FALSE; 1371130561Sobrien } 137289857Sobrien } 137333965Sjdp 137489857Sobrien /* Copy architecture of input file to output file. */ 1375130561Sobrien iarch = bfd_get_arch (ibfd); 1376130561Sobrien imach = bfd_get_mach (ibfd); 1377130561Sobrien if (!bfd_set_arch_mach (obfd, iarch, imach) 1378130561Sobrien && (ibfd->target_defaulted 1379130561Sobrien || bfd_get_arch (ibfd) != bfd_get_arch (obfd))) 1380130561Sobrien { 1381130561Sobrien if (bfd_get_arch (ibfd) == bfd_arch_unknown) 1382218822Sdim non_fatal (_("Unable to recognise the format of the input file `%s'"), 1383218822Sdim bfd_get_archive_filename (ibfd)); 1384130561Sobrien else 1385218822Sdim non_fatal (_("Warning: Output file cannot represent architecture `%s'"), 1386218822Sdim bfd_printable_arch_mach (bfd_get_arch (ibfd), 1387218822Sdim bfd_get_mach (ibfd))); 1388218822Sdim return FALSE; 1389130561Sobrien } 139060484Sobrien 139133965Sjdp if (!bfd_set_format (obfd, bfd_get_format (ibfd))) 1392130561Sobrien { 1393218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1394130561Sobrien return FALSE; 1395130561Sobrien } 139633965Sjdp 139733965Sjdp if (isympp) 139833965Sjdp free (isympp); 139960484Sobrien 140033965Sjdp if (osympp != isympp) 140133965Sjdp free (osympp); 140233965Sjdp 1403218822Sdim isympp = NULL; 1404218822Sdim osympp = NULL; 1405218822Sdim 1406218822Sdim symsize = bfd_get_symtab_upper_bound (ibfd); 1407218822Sdim if (symsize < 0) 1408218822Sdim { 1409218822Sdim bfd_nonfatal (bfd_get_archive_filename (ibfd)); 1410218822Sdim return FALSE; 1411218822Sdim } 1412218822Sdim 1413218822Sdim osympp = isympp = xmalloc (symsize); 1414218822Sdim symcount = bfd_canonicalize_symtab (ibfd, isympp); 1415218822Sdim if (symcount < 0) 1416218822Sdim { 1417218822Sdim bfd_nonfatal (bfd_get_filename (ibfd)); 1418218822Sdim return FALSE; 1419218822Sdim } 1420218822Sdim 142160484Sobrien /* BFD mandates that all output sections be created and sizes set before 142233965Sjdp any output is done. Thus, we traverse all sections multiple times. */ 1423130561Sobrien bfd_map_over_sections (ibfd, setup_section, obfd); 142433965Sjdp 1425218822Sdim setup_bfd_headers (ibfd, obfd); 1426218822Sdim 142733965Sjdp if (add_sections != NULL) 142833965Sjdp { 142933965Sjdp struct section_add *padd; 143033965Sjdp struct section_list *pset; 143133965Sjdp 143233965Sjdp for (padd = add_sections; padd != NULL; padd = padd->next) 143333965Sjdp { 1434130561Sobrien flagword flags; 1435130561Sobrien 1436130561Sobrien pset = find_section_list (padd->name, FALSE); 1437130561Sobrien if (pset != NULL) 1438130561Sobrien pset->used = TRUE; 143933965Sjdp 1440218822Sdim flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; 1441130561Sobrien if (pset != NULL && pset->set_flags) 1442130561Sobrien flags = pset->flags | SEC_HAS_CONTENTS; 1443218822Sdim 1444218822Sdim /* bfd_make_section_with_flags() does not return very helpful 1445218822Sdim error codes, so check for the most likely user error first. */ 1446218822Sdim if (bfd_get_section_by_name (obfd, padd->name)) 1447218822Sdim { 1448218822Sdim non_fatal (_("can't add section '%s' - it already exists!"), padd->name); 1449218822Sdim return FALSE; 1450218822Sdim } 1451130561Sobrien else 1452218822Sdim { 1453218822Sdim padd->section = bfd_make_section_with_flags (obfd, padd->name, flags); 1454218822Sdim if (padd->section == NULL) 1455218822Sdim { 1456218822Sdim non_fatal (_("can't create section `%s': %s"), 1457218822Sdim padd->name, bfd_errmsg (bfd_get_error ())); 1458218822Sdim return FALSE; 1459218822Sdim } 1460218822Sdim } 146133965Sjdp 1462218822Sdim if (! bfd_set_section_size (obfd, padd->section, padd->size)) 1463130561Sobrien { 1464130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1465130561Sobrien return FALSE; 1466130561Sobrien } 146760484Sobrien 1468130561Sobrien if (pset != NULL) 1469130561Sobrien { 1470130561Sobrien if (pset->change_vma != CHANGE_IGNORE) 1471130561Sobrien if (! bfd_set_section_vma (obfd, padd->section, 1472130561Sobrien pset->vma_val)) 1473130561Sobrien { 1474130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1475130561Sobrien return FALSE; 1476130561Sobrien } 147733965Sjdp 1478130561Sobrien if (pset->change_lma != CHANGE_IGNORE) 147933965Sjdp { 1480130561Sobrien padd->section->lma = pset->lma_val; 148160484Sobrien 1482130561Sobrien if (! bfd_set_section_alignment 1483130561Sobrien (obfd, padd->section, 1484130561Sobrien bfd_section_alignment (obfd, padd->section))) 148560484Sobrien { 1486130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1487130561Sobrien return FALSE; 148860484Sobrien } 148933965Sjdp } 149033965Sjdp } 149133965Sjdp } 149233965Sjdp } 149333965Sjdp 1494130561Sobrien if (gnu_debuglink_filename != NULL) 1495130561Sobrien { 1496130561Sobrien gnu_debuglink_section = bfd_create_gnu_debuglink_section 1497130561Sobrien (obfd, gnu_debuglink_filename); 1498130561Sobrien 1499130561Sobrien if (gnu_debuglink_section == NULL) 1500130561Sobrien { 1501130561Sobrien bfd_nonfatal (gnu_debuglink_filename); 1502130561Sobrien return FALSE; 1503130561Sobrien } 1504130561Sobrien 1505218822Sdim /* Special processing for PE format files. We 1506218822Sdim have no way to distinguish PE from COFF here. */ 1507218822Sdim if (bfd_get_flavour (obfd) == bfd_target_coff_flavour) 1508218822Sdim { 1509218822Sdim bfd_vma debuglink_vma; 1510218822Sdim asection * highest_section; 1511218822Sdim asection * sec; 1512218822Sdim 1513218822Sdim /* The PE spec requires that all sections be adjacent and sorted 1514218822Sdim in ascending order of VMA. It also specifies that debug 1515218822Sdim sections should be last. This is despite the fact that debug 1516218822Sdim sections are not loaded into memory and so in theory have no 1517218822Sdim use for a VMA. 1518218822Sdim 1519218822Sdim This means that the debuglink section must be given a non-zero 1520218822Sdim VMA which makes it contiguous with other debug sections. So 1521218822Sdim walk the current section list, find the section with the 1522218822Sdim highest VMA and start the debuglink section after that one. */ 1523218822Sdim for (sec = obfd->sections, highest_section = NULL; 1524218822Sdim sec != NULL; 1525218822Sdim sec = sec->next) 1526218822Sdim if (sec->vma > 0 1527218822Sdim && (highest_section == NULL 1528218822Sdim || sec->vma > highest_section->vma)) 1529218822Sdim highest_section = sec; 1530218822Sdim 1531218822Sdim if (highest_section) 1532218822Sdim debuglink_vma = BFD_ALIGN (highest_section->vma 1533218822Sdim + highest_section->size, 1534218822Sdim /* FIXME: We ought to be using 1535218822Sdim COFF_PAGE_SIZE here or maybe 1536218822Sdim bfd_get_section_alignment() (if it 1537218822Sdim was set) but since this is for PE 1538218822Sdim and we know the required alignment 1539218822Sdim it is easier just to hard code it. */ 1540218822Sdim 0x1000); 1541218822Sdim else 1542218822Sdim /* Umm, not sure what to do in this case. */ 1543218822Sdim debuglink_vma = 0x1000; 1544218822Sdim 1545222204Sbenl (void) bfd_set_section_vma (obfd, gnu_debuglink_section, 1546222204Sbenl debuglink_vma); 1547218822Sdim } 1548130561Sobrien } 1549130561Sobrien 1550218822Sdim if (bfd_count_sections (obfd) != 0 1551218822Sdim && (gap_fill_set || pad_to_set)) 155233965Sjdp { 155333965Sjdp asection **set; 155433965Sjdp unsigned int c, i; 155533965Sjdp 155633965Sjdp /* We must fill in gaps between the sections and/or we must pad 155733965Sjdp the last section to a specified address. We do this by 155833965Sjdp grabbing a list of the sections, sorting them by VMA, and 155933965Sjdp increasing the section sizes as required to fill the gaps. 156033965Sjdp We write out the gap contents below. */ 156133965Sjdp 156233965Sjdp c = bfd_count_sections (obfd); 1563130561Sobrien osections = xmalloc (c * sizeof (asection *)); 156433965Sjdp set = osections; 1565130561Sobrien bfd_map_over_sections (obfd, get_sections, &set); 156633965Sjdp 156738889Sjdp qsort (osections, c, sizeof (asection *), compare_section_lma); 156833965Sjdp 1569130561Sobrien gaps = xmalloc (c * sizeof (bfd_size_type)); 157033965Sjdp memset (gaps, 0, c * sizeof (bfd_size_type)); 157133965Sjdp 157233965Sjdp if (gap_fill_set) 157333965Sjdp { 157433965Sjdp for (i = 0; i < c - 1; i++) 157533965Sjdp { 157633965Sjdp flagword flags; 157733965Sjdp bfd_size_type size; 157833965Sjdp bfd_vma gap_start, gap_stop; 157933965Sjdp 158033965Sjdp flags = bfd_get_section_flags (obfd, osections[i]); 158133965Sjdp if ((flags & SEC_HAS_CONTENTS) == 0 158233965Sjdp || (flags & SEC_LOAD) == 0) 158333965Sjdp continue; 158433965Sjdp 158533965Sjdp size = bfd_section_size (obfd, osections[i]); 158638889Sjdp gap_start = bfd_section_lma (obfd, osections[i]) + size; 158738889Sjdp gap_stop = bfd_section_lma (obfd, osections[i + 1]); 158833965Sjdp if (gap_start < gap_stop) 158933965Sjdp { 159033965Sjdp if (! bfd_set_section_size (obfd, osections[i], 159133965Sjdp size + (gap_stop - gap_start))) 159233965Sjdp { 159360484Sobrien non_fatal (_("Can't fill gap after %s: %s"), 1594104834Sobrien bfd_get_section_name (obfd, osections[i]), 1595104834Sobrien bfd_errmsg (bfd_get_error ())); 159633965Sjdp status = 1; 159733965Sjdp break; 159833965Sjdp } 159933965Sjdp gaps[i] = gap_stop - gap_start; 160033965Sjdp if (max_gap < gap_stop - gap_start) 160133965Sjdp max_gap = gap_stop - gap_start; 160233965Sjdp } 160333965Sjdp } 160433965Sjdp } 160533965Sjdp 160633965Sjdp if (pad_to_set) 160733965Sjdp { 160838889Sjdp bfd_vma lma; 160933965Sjdp bfd_size_type size; 161033965Sjdp 161138889Sjdp lma = bfd_section_lma (obfd, osections[c - 1]); 161233965Sjdp size = bfd_section_size (obfd, osections[c - 1]); 161338889Sjdp if (lma + size < pad_to) 161433965Sjdp { 161533965Sjdp if (! bfd_set_section_size (obfd, osections[c - 1], 161638889Sjdp pad_to - lma)) 161733965Sjdp { 161860484Sobrien non_fatal (_("Can't add padding to %s: %s"), 1619104834Sobrien bfd_get_section_name (obfd, osections[c - 1]), 1620104834Sobrien bfd_errmsg (bfd_get_error ())); 162133965Sjdp status = 1; 162233965Sjdp } 162333965Sjdp else 162433965Sjdp { 162538889Sjdp gaps[c - 1] = pad_to - (lma + size); 162638889Sjdp if (max_gap < pad_to - (lma + size)) 162738889Sjdp max_gap = pad_to - (lma + size); 162833965Sjdp } 162933965Sjdp } 163038889Sjdp } 163133965Sjdp } 163233965Sjdp 163389857Sobrien /* Symbol filtering must happen after the output sections 163489857Sobrien have been created, but before their contents are set. */ 163560484Sobrien dhandle = NULL; 163660484Sobrien if (convert_debugging) 163760484Sobrien dhandle = read_debugging_info (ibfd, isympp, symcount); 163833965Sjdp 163960484Sobrien if (strip_symbols == STRIP_DEBUG 164060484Sobrien || strip_symbols == STRIP_ALL 164160484Sobrien || strip_symbols == STRIP_UNNEEDED 1642130561Sobrien || strip_symbols == STRIP_NONDEBUG 164360484Sobrien || discard_locals != LOCALS_UNDEF 1644218822Sdim || localize_hidden 164560484Sobrien || strip_specific_list != NULL 164660484Sobrien || keep_specific_list != NULL 164760484Sobrien || localize_specific_list != NULL 1648218822Sdim || globalize_specific_list != NULL 164978828Sobrien || keepglobal_specific_list != NULL 165060484Sobrien || weaken_specific_list != NULL 1651130561Sobrien || prefix_symbols_string 165260484Sobrien || sections_removed 165360484Sobrien || sections_copied 165460484Sobrien || convert_debugging 165560484Sobrien || change_leading_char 165660484Sobrien || remove_leading_char 165760484Sobrien || redefine_sym_list 165860484Sobrien || weaken) 165960484Sobrien { 166060484Sobrien /* Mark symbols used in output relocations so that they 166160484Sobrien are kept, even if they are local labels or static symbols. 166233965Sjdp 166360484Sobrien Note we iterate over the input sections examining their 166460484Sobrien relocations since the relocations for the output sections 166560484Sobrien haven't been set yet. mark_symbols_used_in_relocations will 166660484Sobrien ignore input sections which have no corresponding output 166760484Sobrien section. */ 166860484Sobrien if (strip_symbols != STRIP_ALL) 166960484Sobrien bfd_map_over_sections (ibfd, 167060484Sobrien mark_symbols_used_in_relocations, 1671130561Sobrien isympp); 1672130561Sobrien osympp = xmalloc ((symcount + 1) * sizeof (asymbol *)); 167360484Sobrien symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount); 167460484Sobrien } 167533965Sjdp 167660484Sobrien if (convert_debugging && dhandle != NULL) 167760484Sobrien { 167860484Sobrien if (! write_debugging_info (obfd, dhandle, &symcount, &osympp)) 167933965Sjdp { 168060484Sobrien status = 1; 1681130561Sobrien return FALSE; 168233965Sjdp } 168333965Sjdp } 168433965Sjdp 168533965Sjdp bfd_set_symtab (obfd, osympp, symcount); 168633965Sjdp 168733965Sjdp /* This has to happen after the symbol table has been set. */ 1688130561Sobrien bfd_map_over_sections (ibfd, copy_section, obfd); 168933965Sjdp 169033965Sjdp if (add_sections != NULL) 169133965Sjdp { 169233965Sjdp struct section_add *padd; 169333965Sjdp 169433965Sjdp for (padd = add_sections; padd != NULL; padd = padd->next) 169533965Sjdp { 1696130561Sobrien if (! bfd_set_section_contents (obfd, padd->section, padd->contents, 1697130561Sobrien 0, padd->size)) 1698130561Sobrien { 1699130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1700130561Sobrien return FALSE; 1701130561Sobrien } 170233965Sjdp } 170333965Sjdp } 170433965Sjdp 1705130561Sobrien if (gnu_debuglink_filename != NULL) 1706130561Sobrien { 1707130561Sobrien if (! bfd_fill_in_gnu_debuglink_section 1708130561Sobrien (obfd, gnu_debuglink_section, gnu_debuglink_filename)) 1709130561Sobrien { 1710130561Sobrien bfd_nonfatal (gnu_debuglink_filename); 1711130561Sobrien return FALSE; 1712130561Sobrien } 1713130561Sobrien } 1714130561Sobrien 171533965Sjdp if (gap_fill_set || pad_to_set) 171633965Sjdp { 171733965Sjdp bfd_byte *buf; 171833965Sjdp int c, i; 171933965Sjdp 172033965Sjdp /* Fill in the gaps. */ 172133965Sjdp if (max_gap > 8192) 172233965Sjdp max_gap = 8192; 1723130561Sobrien buf = xmalloc (max_gap); 1724130561Sobrien memset (buf, gap_fill, max_gap); 172533965Sjdp 172633965Sjdp c = bfd_count_sections (obfd); 172733965Sjdp for (i = 0; i < c; i++) 172833965Sjdp { 172933965Sjdp if (gaps[i] != 0) 173033965Sjdp { 173133965Sjdp bfd_size_type left; 173233965Sjdp file_ptr off; 173333965Sjdp 173433965Sjdp left = gaps[i]; 173533965Sjdp off = bfd_section_size (obfd, osections[i]) - left; 173689857Sobrien 173733965Sjdp while (left > 0) 173833965Sjdp { 173933965Sjdp bfd_size_type now; 174033965Sjdp 174133965Sjdp if (left > 8192) 174233965Sjdp now = 8192; 174333965Sjdp else 174433965Sjdp now = left; 174560484Sobrien 174633965Sjdp if (! bfd_set_section_contents (obfd, osections[i], buf, 174733965Sjdp off, now)) 1748130561Sobrien { 1749130561Sobrien bfd_nonfatal (bfd_get_filename (obfd)); 1750130561Sobrien return FALSE; 1751130561Sobrien } 175260484Sobrien 175333965Sjdp left -= now; 175433965Sjdp off += now; 175533965Sjdp } 175633965Sjdp } 175733965Sjdp } 175833965Sjdp } 175933965Sjdp 1760218822Sdim /* Do not copy backend data if --extract-symbol is passed; anything 1761218822Sdim that needs to look at the section contents will fail. */ 1762218822Sdim if (extract_symbol) 1763218822Sdim return TRUE; 1764218822Sdim 176533965Sjdp /* Allow the BFD backend to copy any private data it understands 176633965Sjdp from the input BFD to the output BFD. This is done last to 176733965Sjdp permit the routine to look at the filtered symbol table, which is 176833965Sjdp important for the ECOFF code at least. */ 1769218822Sdim if (! bfd_copy_private_bfd_data (ibfd, obfd)) 177033965Sjdp { 177160484Sobrien non_fatal (_("%s: error copying private BFD data: %s"), 177260484Sobrien bfd_get_filename (obfd), 177360484Sobrien bfd_errmsg (bfd_get_error ())); 1774130561Sobrien return FALSE; 177533965Sjdp } 177689857Sobrien 177789857Sobrien /* Switch to the alternate machine code. We have to do this at the 177889857Sobrien very end, because we only initialize the header when we create 177989857Sobrien the first section. */ 1780218822Sdim if (use_alt_mach_code != 0) 1781218822Sdim { 1782218822Sdim if (! bfd_alt_mach_code (obfd, use_alt_mach_code)) 1783218822Sdim { 1784218822Sdim non_fatal (_("this target does not support %lu alternative machine codes"), 1785218822Sdim use_alt_mach_code); 1786218822Sdim if (bfd_get_flavour (obfd) == bfd_target_elf_flavour) 1787218822Sdim { 1788218822Sdim non_fatal (_("treating that number as an absolute e_machine value instead")); 1789218822Sdim elf_elfheader (obfd)->e_machine = use_alt_mach_code; 1790218822Sdim } 1791218822Sdim else 1792218822Sdim non_fatal (_("ignoring the alternative value")); 1793218822Sdim } 1794218822Sdim } 1795130561Sobrien 1796130561Sobrien return TRUE; 179733965Sjdp} 179833965Sjdp 179933965Sjdp/* Read each archive element in turn from IBFD, copy the 1800218822Sdim contents to temp file, and keep the temp file handle. 1801218822Sdim If 'force_output_target' is TRUE then make sure that 1802218822Sdim all elements in the new archive are of the type 1803218822Sdim 'output_target'. */ 180433965Sjdp 180533965Sjdpstatic void 1806218822Sdimcopy_archive (bfd *ibfd, bfd *obfd, const char *output_target, 1807218822Sdim bfd_boolean force_output_target) 180833965Sjdp{ 180933965Sjdp struct name_list 181033965Sjdp { 181133965Sjdp struct name_list *next; 181291041Sobrien const char *name; 181333965Sjdp bfd *obfd; 181433965Sjdp } *list, *l; 181533965Sjdp bfd **ptr = &obfd->archive_head; 181633965Sjdp bfd *this_element; 1817218822Sdim char * dir; 181833965Sjdp 181933965Sjdp /* Make a temp directory to hold the contents. */ 1820218822Sdim dir = make_tempdir (bfd_get_filename (obfd)); 1821218822Sdim if (dir == NULL) 1822218822Sdim fatal (_("cannot create tempdir for archive copying (error: %s)"), 1823218822Sdim strerror (errno)); 1824130561Sobrien 182533965Sjdp obfd->has_armap = ibfd->has_armap; 182633965Sjdp 182733965Sjdp list = NULL; 182833965Sjdp 182933965Sjdp this_element = bfd_openr_next_archived_file (ibfd, NULL); 183089857Sobrien 183189857Sobrien if (!bfd_set_format (obfd, bfd_get_format (ibfd))) 183289857Sobrien RETURN_NONFATAL (bfd_get_filename (obfd)); 183389857Sobrien 1834130561Sobrien while (!status && this_element != NULL) 183533965Sjdp { 183691041Sobrien char *output_name; 183791041Sobrien bfd *output_bfd; 183833965Sjdp bfd *last_element; 183960484Sobrien struct stat buf; 184060484Sobrien int stat_status = 0; 1841130561Sobrien bfd_boolean delete = TRUE; 184233965Sjdp 184391041Sobrien /* Create an output file for this member. */ 184491041Sobrien output_name = concat (dir, "/", 184591041Sobrien bfd_get_filename (this_element), (char *) 0); 184691041Sobrien 184791041Sobrien /* If the file already exists, make another temp dir. */ 184891041Sobrien if (stat (output_name, &buf) >= 0) 184991041Sobrien { 1850218822Sdim output_name = make_tempdir (output_name); 1851218822Sdim if (output_name == NULL) 1852218822Sdim fatal (_("cannot create tempdir for archive copying (error: %s)"), 1853218822Sdim strerror (errno)); 1854130561Sobrien 1855130561Sobrien l = xmalloc (sizeof (struct name_list)); 185691041Sobrien l->name = output_name; 185791041Sobrien l->next = list; 185891041Sobrien l->obfd = NULL; 185991041Sobrien list = l; 186091041Sobrien output_name = concat (output_name, "/", 186191041Sobrien bfd_get_filename (this_element), (char *) 0); 186291041Sobrien } 186391041Sobrien 186460484Sobrien if (preserve_dates) 186560484Sobrien { 186660484Sobrien stat_status = bfd_stat_arch_elt (this_element, &buf); 186789857Sobrien 186860484Sobrien if (stat_status != 0) 186960484Sobrien non_fatal (_("internal stat error on %s"), 187060484Sobrien bfd_get_filename (this_element)); 187160484Sobrien } 187260484Sobrien 1873130561Sobrien l = xmalloc (sizeof (struct name_list)); 187433965Sjdp l->name = output_name; 187533965Sjdp l->next = list; 1876218822Sdim l->obfd = NULL; 187733965Sjdp list = l; 187833965Sjdp 1879130561Sobrien if (bfd_check_format (this_element, bfd_object)) 1880218822Sdim { 1881218822Sdim /* PR binutils/3110: Cope with archives 1882218822Sdim containing multiple target types. */ 1883218822Sdim if (force_output_target) 1884218822Sdim output_bfd = bfd_openw (output_name, output_target); 1885218822Sdim else 1886218822Sdim output_bfd = bfd_openw (output_name, bfd_get_target (this_element)); 188760484Sobrien 1888218822Sdim if (output_bfd == NULL) 1889218822Sdim RETURN_NONFATAL (output_name); 1890218822Sdim 1891218822Sdim delete = ! copy_object (this_element, output_bfd); 1892218822Sdim 1893218822Sdim if (! delete 1894218822Sdim || bfd_get_arch (this_element) != bfd_arch_unknown) 1895218822Sdim { 1896218822Sdim if (!bfd_close (output_bfd)) 1897218822Sdim { 1898218822Sdim bfd_nonfatal (bfd_get_filename (output_bfd)); 1899218822Sdim /* Error in new object file. Don't change archive. */ 1900218822Sdim status = 1; 1901218822Sdim } 1902218822Sdim } 1903218822Sdim else 1904218822Sdim goto copy_unknown_element; 1905218822Sdim } 1906218822Sdim else 190733965Sjdp { 1908218822Sdim non_fatal (_("Unable to recognise the format of the input file `%s'"), 1909218822Sdim bfd_get_archive_filename (this_element)); 1910218822Sdim 1911218822Sdim output_bfd = bfd_openw (output_name, output_target); 1912218822Sdimcopy_unknown_element: 1913218822Sdim delete = !copy_unknown_object (this_element, output_bfd); 1914218822Sdim if (!bfd_close_all_done (output_bfd)) 1915218822Sdim { 1916218822Sdim bfd_nonfatal (bfd_get_filename (output_bfd)); 1917218822Sdim /* Error in new object file. Don't change archive. */ 1918218822Sdim status = 1; 1919218822Sdim } 192033965Sjdp } 192133965Sjdp 1922130561Sobrien if (delete) 1923130561Sobrien { 1924130561Sobrien unlink (output_name); 1925130561Sobrien status = 1; 1926130561Sobrien } 1927130561Sobrien else 1928130561Sobrien { 1929130561Sobrien if (preserve_dates && stat_status == 0) 1930130561Sobrien set_times (output_name, &buf); 193133965Sjdp 1932130561Sobrien /* Open the newly output file and attach to our list. */ 1933130561Sobrien output_bfd = bfd_openr (output_name, output_target); 193433965Sjdp 1935130561Sobrien l->obfd = output_bfd; 193633965Sjdp 1937130561Sobrien *ptr = output_bfd; 1938218822Sdim ptr = &output_bfd->archive_next; 193933965Sjdp 1940130561Sobrien last_element = this_element; 194133965Sjdp 1942130561Sobrien this_element = bfd_openr_next_archived_file (ibfd, last_element); 194333965Sjdp 1944130561Sobrien bfd_close (last_element); 1945130561Sobrien } 194633965Sjdp } 1947130561Sobrien *ptr = NULL; 194833965Sjdp 194933965Sjdp if (!bfd_close (obfd)) 195060484Sobrien RETURN_NONFATAL (bfd_get_filename (obfd)); 195133965Sjdp 195233965Sjdp if (!bfd_close (ibfd)) 195360484Sobrien RETURN_NONFATAL (bfd_get_filename (ibfd)); 195433965Sjdp 195533965Sjdp /* Delete all the files that we opened. */ 195633965Sjdp for (l = list; l != NULL; l = l->next) 195733965Sjdp { 195891041Sobrien if (l->obfd == NULL) 195991041Sobrien rmdir (l->name); 196091041Sobrien else 196191041Sobrien { 196291041Sobrien bfd_close (l->obfd); 196391041Sobrien unlink (l->name); 196491041Sobrien } 196533965Sjdp } 196633965Sjdp rmdir (dir); 196733965Sjdp} 196833965Sjdp 196933965Sjdp/* The top-level control. */ 197033965Sjdp 197133965Sjdpstatic void 1972130561Sobriencopy_file (const char *input_filename, const char *output_filename, 1973130561Sobrien const char *input_target, const char *output_target) 197433965Sjdp{ 197533965Sjdp bfd *ibfd; 1976130561Sobrien char **obj_matching; 1977130561Sobrien char **core_matching; 197833965Sjdp 1979130561Sobrien if (get_file_size (input_filename) < 1) 1980130561Sobrien { 1981130561Sobrien status = 1; 1982130561Sobrien return; 1983130561Sobrien } 1984130561Sobrien 198533965Sjdp /* To allow us to do "strip *" without dying on the first 198633965Sjdp non-object file, failures are nonfatal. */ 198733965Sjdp ibfd = bfd_openr (input_filename, input_target); 198833965Sjdp if (ibfd == NULL) 198960484Sobrien RETURN_NONFATAL (input_filename); 199033965Sjdp 199133965Sjdp if (bfd_check_format (ibfd, bfd_archive)) 199233965Sjdp { 1993218822Sdim bfd_boolean force_output_target; 199433965Sjdp bfd *obfd; 199533965Sjdp 199633965Sjdp /* bfd_get_target does not return the correct value until 199733965Sjdp bfd_check_format succeeds. */ 199833965Sjdp if (output_target == NULL) 1999218822Sdim { 2000218822Sdim output_target = bfd_get_target (ibfd); 2001218822Sdim force_output_target = FALSE; 2002218822Sdim } 2003218822Sdim else 2004218822Sdim force_output_target = TRUE; 200533965Sjdp 200633965Sjdp obfd = bfd_openw (output_filename, output_target); 200733965Sjdp if (obfd == NULL) 200860484Sobrien RETURN_NONFATAL (output_filename); 200960484Sobrien 2010218822Sdim copy_archive (ibfd, obfd, output_target, force_output_target); 201133965Sjdp } 2012130561Sobrien else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching)) 201333965Sjdp { 201433965Sjdp bfd *obfd; 2015130561Sobrien do_copy: 201633965Sjdp 201733965Sjdp /* bfd_get_target does not return the correct value until 201833965Sjdp bfd_check_format succeeds. */ 201933965Sjdp if (output_target == NULL) 202033965Sjdp output_target = bfd_get_target (ibfd); 202133965Sjdp 202233965Sjdp obfd = bfd_openw (output_filename, output_target); 202333965Sjdp if (obfd == NULL) 202460484Sobrien RETURN_NONFATAL (output_filename); 202533965Sjdp 2026218822Sdim if (! copy_object (ibfd, obfd)) 2027218822Sdim status = 1; 202833965Sjdp 202933965Sjdp if (!bfd_close (obfd)) 203060484Sobrien RETURN_NONFATAL (output_filename); 203133965Sjdp 203233965Sjdp if (!bfd_close (ibfd)) 203360484Sobrien RETURN_NONFATAL (input_filename); 2034130561Sobrien 203533965Sjdp } 203633965Sjdp else 203733965Sjdp { 2038130561Sobrien bfd_error_type obj_error = bfd_get_error (); 2039130561Sobrien bfd_error_type core_error; 2040130561Sobrien 2041130561Sobrien if (bfd_check_format_matches (ibfd, bfd_core, &core_matching)) 2042130561Sobrien { 2043130561Sobrien /* This probably can't happen.. */ 2044130561Sobrien if (obj_error == bfd_error_file_ambiguously_recognized) 2045130561Sobrien free (obj_matching); 2046130561Sobrien goto do_copy; 2047130561Sobrien } 2048130561Sobrien 2049130561Sobrien core_error = bfd_get_error (); 2050130561Sobrien /* Report the object error in preference to the core error. */ 2051130561Sobrien if (obj_error != core_error) 2052130561Sobrien bfd_set_error (obj_error); 2053130561Sobrien 205433965Sjdp bfd_nonfatal (input_filename); 205560484Sobrien 2056130561Sobrien if (obj_error == bfd_error_file_ambiguously_recognized) 205733965Sjdp { 2058130561Sobrien list_matching_formats (obj_matching); 2059130561Sobrien free (obj_matching); 206033965Sjdp } 2061130561Sobrien if (core_error == bfd_error_file_ambiguously_recognized) 2062130561Sobrien { 2063130561Sobrien list_matching_formats (core_matching); 2064130561Sobrien free (core_matching); 2065130561Sobrien } 206660484Sobrien 206733965Sjdp status = 1; 206833965Sjdp } 206933965Sjdp} 207033965Sjdp 207189857Sobrien/* Add a name to the section renaming list. */ 207233965Sjdp 207333965Sjdpstatic void 2074130561Sobrienadd_section_rename (const char * old_name, const char * new_name, 2075130561Sobrien flagword flags) 207689857Sobrien{ 207789857Sobrien section_rename * rename; 207889857Sobrien 207989857Sobrien /* Check for conflicts first. */ 208089857Sobrien for (rename = section_rename_list; rename != NULL; rename = rename->next) 208189857Sobrien if (strcmp (rename->old_name, old_name) == 0) 208289857Sobrien { 208389857Sobrien /* Silently ignore duplicate definitions. */ 208489857Sobrien if (strcmp (rename->new_name, new_name) == 0 208589857Sobrien && rename->flags == flags) 208689857Sobrien return; 2087104834Sobrien 208889857Sobrien fatal (_("Multiple renames of section %s"), old_name); 208989857Sobrien } 209089857Sobrien 2091130561Sobrien rename = xmalloc (sizeof (* rename)); 209289857Sobrien 209389857Sobrien rename->old_name = old_name; 209489857Sobrien rename->new_name = new_name; 209589857Sobrien rename->flags = flags; 209689857Sobrien rename->next = section_rename_list; 2097104834Sobrien 209889857Sobrien section_rename_list = rename; 209989857Sobrien} 210089857Sobrien 210189857Sobrien/* Check the section rename list for a new name of the input section 210289857Sobrien ISECTION. Return the new name if one is found. 210389857Sobrien Also set RETURNED_FLAGS to the flags to be used for this section. */ 210489857Sobrien 210589857Sobrienstatic const char * 2106130561Sobrienfind_section_rename (bfd * ibfd ATTRIBUTE_UNUSED, sec_ptr isection, 2107130561Sobrien flagword * returned_flags) 210889857Sobrien{ 210989857Sobrien const char * old_name = bfd_section_name (ibfd, isection); 211089857Sobrien section_rename * rename; 211189857Sobrien 211289857Sobrien /* Default to using the flags of the input section. */ 211389857Sobrien * returned_flags = bfd_get_section_flags (ibfd, isection); 211489857Sobrien 211589857Sobrien for (rename = section_rename_list; rename != NULL; rename = rename->next) 211689857Sobrien if (strcmp (rename->old_name, old_name) == 0) 211789857Sobrien { 211889857Sobrien if (rename->flags != (flagword) -1) 211989857Sobrien * returned_flags = rename->flags; 212089857Sobrien 212189857Sobrien return rename->new_name; 212289857Sobrien } 212389857Sobrien 212489857Sobrien return old_name; 212589857Sobrien} 212689857Sobrien 2127218822Sdim/* Once each of the sections is copied, we may still need to do some 2128218822Sdim finalization work for private section headers. Do that here. */ 2129218822Sdim 2130218822Sdimstatic void 2131218822Sdimsetup_bfd_headers (bfd *ibfd, bfd *obfd) 2132218822Sdim{ 2133218822Sdim const char *err; 2134218822Sdim 2135218822Sdim /* Allow the BFD backend to copy any private data it understands 2136218822Sdim from the input section to the output section. */ 2137218822Sdim if (! bfd_copy_private_header_data (ibfd, obfd)) 2138218822Sdim { 2139218822Sdim err = _("private header data"); 2140218822Sdim goto loser; 2141218822Sdim } 2142218822Sdim 2143218822Sdim /* All went well. */ 2144218822Sdim return; 2145218822Sdim 2146218822Sdimloser: 2147218822Sdim non_fatal (_("%s: error in %s: %s"), 2148218822Sdim bfd_get_filename (ibfd), 2149218822Sdim err, bfd_errmsg (bfd_get_error ())); 2150218822Sdim status = 1; 2151218822Sdim} 2152218822Sdim 215389857Sobrien/* Create a section in OBFD with the same 215489857Sobrien name and attributes as ISECTION in IBFD. */ 215589857Sobrien 215689857Sobrienstatic void 2157130561Sobriensetup_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 215833965Sjdp{ 2159130561Sobrien bfd *obfd = obfdarg; 216033965Sjdp struct section_list *p; 216133965Sjdp sec_ptr osection; 216260484Sobrien bfd_size_type size; 216333965Sjdp bfd_vma vma; 216433965Sjdp bfd_vma lma; 216533965Sjdp flagword flags; 216677298Sobrien const char *err; 216789857Sobrien const char * name; 2168130561Sobrien char *prefix = NULL; 2169104834Sobrien 2170130561Sobrien if (is_strip_section (ibfd, isection)) 217133965Sjdp return; 217233965Sjdp 2173130561Sobrien p = find_section_list (bfd_section_name (ibfd, isection), FALSE); 217433965Sjdp if (p != NULL) 2175130561Sobrien p->used = TRUE; 217633965Sjdp 217789857Sobrien /* Get the, possibly new, name of the output section. */ 217889857Sobrien name = find_section_rename (ibfd, isection, & flags); 2179104834Sobrien 2180130561Sobrien /* Prefix sections. */ 2181130561Sobrien if ((prefix_alloc_sections_string) 2182130561Sobrien && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC)) 2183130561Sobrien prefix = prefix_alloc_sections_string; 2184130561Sobrien else if (prefix_sections_string) 2185130561Sobrien prefix = prefix_sections_string; 2186130561Sobrien 2187130561Sobrien if (prefix) 2188130561Sobrien { 2189130561Sobrien char *n; 2190130561Sobrien 2191130561Sobrien n = xmalloc (strlen (prefix) + strlen (name) + 1); 2192130561Sobrien strcpy (n, prefix); 2193130561Sobrien strcat (n, name); 2194130561Sobrien name = n; 2195130561Sobrien } 2196130561Sobrien 2197218822Sdim if (p != NULL && p->set_flags) 2198218822Sdim flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC)); 2199218822Sdim else if (strip_symbols == STRIP_NONDEBUG 2200218822Sdim && obfd->xvec->flavour != bfd_target_elf_flavour 2201218822Sdim && (flags & SEC_ALLOC) != 0) 2202218822Sdim flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD); 220360484Sobrien 2204218822Sdim osection = bfd_make_section_anyway_with_flags (obfd, name, flags); 2205218822Sdim 220633965Sjdp if (osection == NULL) 220733965Sjdp { 220877298Sobrien err = _("making"); 220933965Sjdp goto loser; 221033965Sjdp } 221133965Sjdp 2212218822Sdim if (strip_symbols == STRIP_NONDEBUG 2213218822Sdim && obfd->xvec->flavour == bfd_target_elf_flavour 2214218822Sdim && (flags & SEC_ALLOC) != 0 2215218822Sdim && elf_section_type (osection) != SHT_NOTE 2216218822Sdim && (ibfd->xvec->flavour != bfd_target_elf_flavour 2217218822Sdim || elf_section_type (isection) != SHT_NOTE) 2218218822Sdim && (p == NULL || !p->set_flags)) 2219218822Sdim elf_section_type (osection) = SHT_NOBITS; 2220218822Sdim 222160484Sobrien size = bfd_section_size (ibfd, isection); 222260484Sobrien if (copy_byte >= 0) 222360484Sobrien size = (size + interleave - 1) / interleave; 2224218822Sdim else if (extract_symbol) 2225218822Sdim size = 0; 222660484Sobrien if (! bfd_set_section_size (obfd, osection, size)) 222733965Sjdp { 222877298Sobrien err = _("size"); 222933965Sjdp goto loser; 223033965Sjdp } 223133965Sjdp 223233965Sjdp vma = bfd_section_vma (ibfd, isection); 223360484Sobrien if (p != NULL && p->change_vma == CHANGE_MODIFY) 223460484Sobrien vma += p->vma_val; 223560484Sobrien else if (p != NULL && p->change_vma == CHANGE_SET) 223660484Sobrien vma = p->vma_val; 223733965Sjdp else 223860484Sobrien vma += change_section_address; 223960484Sobrien 2240218822Sdim if (! bfd_set_section_vma (obfd, osection, extract_symbol ? 0 : vma)) 224133965Sjdp { 224277298Sobrien err = _("vma"); 224333965Sjdp goto loser; 224433965Sjdp } 224533965Sjdp 224633965Sjdp lma = isection->lma; 224760484Sobrien if ((p != NULL) && p->change_lma != CHANGE_IGNORE) 224860484Sobrien { 224960484Sobrien if (p->change_lma == CHANGE_MODIFY) 225060484Sobrien lma += p->lma_val; 225160484Sobrien else if (p->change_lma == CHANGE_SET) 225260484Sobrien lma = p->lma_val; 225360484Sobrien else 225460484Sobrien abort (); 225560484Sobrien } 225633965Sjdp else 225760484Sobrien lma += change_section_address; 225860484Sobrien 2259218822Sdim osection->lma = extract_symbol ? 0 : lma; 226033965Sjdp 226160484Sobrien /* FIXME: This is probably not enough. If we change the LMA we 226260484Sobrien may have to recompute the header for the file as well. */ 2263130561Sobrien if (!bfd_set_section_alignment (obfd, 2264130561Sobrien osection, 2265130561Sobrien bfd_section_alignment (ibfd, isection))) 226633965Sjdp { 226777298Sobrien err = _("alignment"); 226833965Sjdp goto loser; 226933965Sjdp } 227033965Sjdp 227189857Sobrien /* Copy merge entity size. */ 227289857Sobrien osection->entsize = isection->entsize; 227389857Sobrien 227433965Sjdp /* This used to be mangle_section; we do here to avoid using 227533965Sjdp bfd_get_section_by_name since some formats allow multiple 227633965Sjdp sections with the same name. */ 227733965Sjdp isection->output_section = osection; 2278218822Sdim isection->output_offset = extract_symbol ? vma : 0; 227933965Sjdp 2280218822Sdim /* Do not copy backend data if --extract-symbol is passed; anything 2281218822Sdim that needs to look at the section contents will fail. */ 2282218822Sdim if (extract_symbol) 2283218822Sdim return; 2284218822Sdim 228533965Sjdp /* Allow the BFD backend to copy any private data it understands 228633965Sjdp from the input section to the output section. */ 2287218822Sdim if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) 228833965Sjdp { 228977298Sobrien err = _("private data"); 229033965Sjdp goto loser; 229133965Sjdp } 2292218822Sdim else if ((isection->flags & SEC_GROUP) != 0) 2293218822Sdim { 2294218822Sdim asymbol *gsym = group_signature (isection); 229533965Sjdp 2296218822Sdim if (gsym != NULL) 2297218822Sdim gsym->flags |= BSF_KEEP; 2298218822Sdim } 2299218822Sdim 230089857Sobrien /* All went well. */ 230133965Sjdp return; 230233965Sjdp 230333965Sjdploser: 230460484Sobrien non_fatal (_("%s: section `%s': error in %s: %s"), 230560484Sobrien bfd_get_filename (ibfd), 230660484Sobrien bfd_section_name (ibfd, isection), 230760484Sobrien err, bfd_errmsg (bfd_get_error ())); 230833965Sjdp status = 1; 230933965Sjdp} 231033965Sjdp 231133965Sjdp/* Copy the data of input section ISECTION of IBFD 231233965Sjdp to an output section with the same name in OBFD. 231333965Sjdp If stripping then don't copy any relocation info. */ 231433965Sjdp 231533965Sjdpstatic void 2316130561Sobriencopy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) 231733965Sjdp{ 2318130561Sobrien bfd *obfd = obfdarg; 231933965Sjdp struct section_list *p; 232033965Sjdp arelent **relpp; 232133965Sjdp long relcount; 232233965Sjdp sec_ptr osection; 232333965Sjdp bfd_size_type size; 232460484Sobrien long relsize; 2325104834Sobrien flagword flags; 232633965Sjdp 232789857Sobrien /* If we have already failed earlier on, 232889857Sobrien do not keep on generating complaints now. */ 232960484Sobrien if (status != 0) 233060484Sobrien return; 233160484Sobrien 2332130561Sobrien if (is_strip_section (ibfd, isection)) 233389857Sobrien return; 233433965Sjdp 2335130561Sobrien flags = bfd_get_section_flags (ibfd, isection); 2336104834Sobrien if ((flags & SEC_GROUP) != 0) 2337104834Sobrien return; 2338104834Sobrien 233933965Sjdp osection = isection->output_section; 2340218822Sdim size = bfd_get_section_size (isection); 234133965Sjdp 234233965Sjdp if (size == 0 || osection == 0) 234333965Sjdp return; 234433965Sjdp 2345130561Sobrien p = find_section_list (bfd_get_section_name (ibfd, isection), FALSE); 2346130561Sobrien 2347104834Sobrien /* Core files do not need to be relocated. */ 234889857Sobrien if (bfd_get_format (obfd) == bfd_core) 234989857Sobrien relsize = 0; 235089857Sobrien else 2351130561Sobrien { 2352130561Sobrien relsize = bfd_get_reloc_upper_bound (ibfd, isection); 235360484Sobrien 2354130561Sobrien if (relsize < 0) 2355130561Sobrien { 2356130561Sobrien /* Do not complain if the target does not support relocations. */ 2357130561Sobrien if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation) 2358130561Sobrien relsize = 0; 2359130561Sobrien else 2360130561Sobrien RETURN_NONFATAL (bfd_get_filename (ibfd)); 2361130561Sobrien } 2362130561Sobrien } 236360484Sobrien 236460484Sobrien if (relsize == 0) 2365130561Sobrien bfd_set_reloc (obfd, osection, NULL, 0); 236633965Sjdp else 236733965Sjdp { 2368130561Sobrien relpp = xmalloc (relsize); 236960484Sobrien relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp); 237060484Sobrien if (relcount < 0) 237160484Sobrien RETURN_NONFATAL (bfd_get_filename (ibfd)); 237233965Sjdp 237360484Sobrien if (strip_symbols == STRIP_ALL) 237433965Sjdp { 237560484Sobrien /* Remove relocations which are not in 2376104834Sobrien keep_strip_specific_list. */ 237760484Sobrien arelent **temp_relpp; 237860484Sobrien long temp_relcount = 0; 237960484Sobrien long i; 238060484Sobrien 2381130561Sobrien temp_relpp = xmalloc (relsize); 238260484Sobrien for (i = 0; i < relcount; i++) 2383130561Sobrien if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr), 2384130561Sobrien keep_specific_list)) 238560484Sobrien temp_relpp [temp_relcount++] = relpp [i]; 238660484Sobrien relcount = temp_relcount; 238760484Sobrien free (relpp); 238860484Sobrien relpp = temp_relpp; 238933965Sjdp } 239089857Sobrien 2391130561Sobrien bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount); 2392130561Sobrien if (relcount == 0) 2393130561Sobrien free (relpp); 239433965Sjdp } 239533965Sjdp 2396218822Sdim if (extract_symbol) 2397218822Sdim return; 239833965Sjdp 2399104834Sobrien if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS 240089857Sobrien && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS) 240133965Sjdp { 2402130561Sobrien void *memhunk = xmalloc (size); 240333965Sjdp 2404130561Sobrien if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size)) 240560484Sobrien RETURN_NONFATAL (bfd_get_filename (ibfd)); 240633965Sjdp 2407218822Sdim if (reverse_bytes) 2408218822Sdim { 2409218822Sdim /* We don't handle leftover bytes (too many possible behaviors, 2410218822Sdim and we don't know what the user wants). The section length 2411218822Sdim must be a multiple of the number of bytes to swap. */ 2412218822Sdim if ((size % reverse_bytes) == 0) 2413218822Sdim { 2414218822Sdim unsigned long i, j; 2415218822Sdim bfd_byte b; 2416218822Sdim 2417218822Sdim for (i = 0; i < size; i += reverse_bytes) 2418218822Sdim for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++) 2419218822Sdim { 2420218822Sdim bfd_byte *m = (bfd_byte *) memhunk; 2421218822Sdim 2422218822Sdim b = m[i + j]; 2423218822Sdim m[i + j] = m[(i + reverse_bytes) - (j + 1)]; 2424218822Sdim m[(i + reverse_bytes) - (j + 1)] = b; 2425218822Sdim } 2426218822Sdim } 2427218822Sdim else 2428218822Sdim /* User must pad the section up in order to do this. */ 2429218822Sdim fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"), 2430218822Sdim bfd_section_name (ibfd, isection), reverse_bytes); 2431218822Sdim } 2432218822Sdim 243360484Sobrien if (copy_byte >= 0) 2434130561Sobrien { 2435130561Sobrien /* Keep only every `copy_byte'th byte in MEMHUNK. */ 2436130561Sobrien char *from = (char *) memhunk + copy_byte; 2437130561Sobrien char *to = memhunk; 2438130561Sobrien char *end = (char *) memhunk + size; 243933965Sjdp 2440130561Sobrien for (; from < end; from += interleave) 2441130561Sobrien *to++ = *from; 2442130561Sobrien 2443130561Sobrien size = (size + interleave - 1 - copy_byte) / interleave; 2444130561Sobrien osection->lma /= interleave; 2445130561Sobrien } 2446130561Sobrien 2447130561Sobrien if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size)) 244860484Sobrien RETURN_NONFATAL (bfd_get_filename (obfd)); 244960484Sobrien 245033965Sjdp free (memhunk); 245133965Sjdp } 245238889Sjdp else if (p != NULL && p->set_flags && (p->flags & SEC_HAS_CONTENTS) != 0) 245338889Sjdp { 2454130561Sobrien void *memhunk = xmalloc (size); 245538889Sjdp 245638889Sjdp /* We don't permit the user to turn off the SEC_HAS_CONTENTS 245738889Sjdp flag--they can just remove the section entirely and add it 245838889Sjdp back again. However, we do permit them to turn on the 245938889Sjdp SEC_HAS_CONTENTS flag, and take it to mean that the section 246038889Sjdp contents should be zeroed out. */ 246138889Sjdp 246238889Sjdp memset (memhunk, 0, size); 2463130561Sobrien if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size)) 246460484Sobrien RETURN_NONFATAL (bfd_get_filename (obfd)); 246538889Sjdp free (memhunk); 246638889Sjdp } 246733965Sjdp} 246833965Sjdp 246933965Sjdp/* Get all the sections. This is used when --gap-fill or --pad-to is 247033965Sjdp used. */ 247133965Sjdp 247233965Sjdpstatic void 2473130561Sobrienget_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg) 247433965Sjdp{ 2475130561Sobrien asection ***secppp = secppparg; 247633965Sjdp 247733965Sjdp **secppp = osection; 247833965Sjdp ++(*secppp); 247933965Sjdp} 248033965Sjdp 248133965Sjdp/* Sort sections by VMA. This is called via qsort, and is used when 248233965Sjdp --gap-fill or --pad-to is used. We force non loadable or empty 248333965Sjdp sections to the front, where they are easier to ignore. */ 248433965Sjdp 248533965Sjdpstatic int 2486130561Sobriencompare_section_lma (const void *arg1, const void *arg2) 248733965Sjdp{ 2488130561Sobrien const asection *const *sec1 = arg1; 2489130561Sobrien const asection *const *sec2 = arg2; 249033965Sjdp flagword flags1, flags2; 249133965Sjdp 249233965Sjdp /* Sort non loadable sections to the front. */ 249333965Sjdp flags1 = (*sec1)->flags; 249433965Sjdp flags2 = (*sec2)->flags; 249533965Sjdp if ((flags1 & SEC_HAS_CONTENTS) == 0 249633965Sjdp || (flags1 & SEC_LOAD) == 0) 249733965Sjdp { 249833965Sjdp if ((flags2 & SEC_HAS_CONTENTS) != 0 249933965Sjdp && (flags2 & SEC_LOAD) != 0) 250033965Sjdp return -1; 250133965Sjdp } 250233965Sjdp else 250333965Sjdp { 250433965Sjdp if ((flags2 & SEC_HAS_CONTENTS) == 0 250533965Sjdp || (flags2 & SEC_LOAD) == 0) 250633965Sjdp return 1; 250733965Sjdp } 250833965Sjdp 250938889Sjdp /* Sort sections by LMA. */ 251038889Sjdp if ((*sec1)->lma > (*sec2)->lma) 251133965Sjdp return 1; 251238889Sjdp else if ((*sec1)->lma < (*sec2)->lma) 251333965Sjdp return -1; 251433965Sjdp 251538889Sjdp /* Sort sections with the same LMA by size. */ 2516218822Sdim if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2)) 251733965Sjdp return 1; 2518218822Sdim else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2)) 251933965Sjdp return -1; 252033965Sjdp 252133965Sjdp return 0; 252233965Sjdp} 252333965Sjdp 252433965Sjdp/* Mark all the symbols which will be used in output relocations with 252533965Sjdp the BSF_KEEP flag so that those symbols will not be stripped. 252633965Sjdp 252733965Sjdp Ignore relocations which will not appear in the output file. */ 252833965Sjdp 252933965Sjdpstatic void 2530130561Sobrienmark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg) 253133965Sjdp{ 2532130561Sobrien asymbol **symbols = symbolsarg; 253333965Sjdp long relsize; 253433965Sjdp arelent **relpp; 253533965Sjdp long relcount, i; 253633965Sjdp 253733965Sjdp /* Ignore an input section with no corresponding output section. */ 253833965Sjdp if (isection->output_section == NULL) 253933965Sjdp return; 254033965Sjdp 254133965Sjdp relsize = bfd_get_reloc_upper_bound (ibfd, isection); 254233965Sjdp if (relsize < 0) 2543130561Sobrien { 2544130561Sobrien /* Do not complain if the target does not support relocations. */ 2545130561Sobrien if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation) 2546130561Sobrien return; 2547130561Sobrien bfd_fatal (bfd_get_filename (ibfd)); 2548130561Sobrien } 254933965Sjdp 255033965Sjdp if (relsize == 0) 255133965Sjdp return; 255233965Sjdp 2553130561Sobrien relpp = xmalloc (relsize); 255433965Sjdp relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols); 255533965Sjdp if (relcount < 0) 255633965Sjdp bfd_fatal (bfd_get_filename (ibfd)); 255733965Sjdp 255833965Sjdp /* Examine each symbol used in a relocation. If it's not one of the 255933965Sjdp special bfd section symbols, then mark it with BSF_KEEP. */ 256033965Sjdp for (i = 0; i < relcount; i++) 256133965Sjdp { 256233965Sjdp if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol 256333965Sjdp && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol 256433965Sjdp && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol) 256533965Sjdp (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP; 256633965Sjdp } 256733965Sjdp 256833965Sjdp if (relpp != NULL) 256933965Sjdp free (relpp); 257033965Sjdp} 257133965Sjdp 257233965Sjdp/* Write out debugging information. */ 257333965Sjdp 2574130561Sobrienstatic bfd_boolean 2575130561Sobrienwrite_debugging_info (bfd *obfd, void *dhandle, 2576130561Sobrien long *symcountp ATTRIBUTE_UNUSED, 2577130561Sobrien asymbol ***symppp ATTRIBUTE_UNUSED) 257833965Sjdp{ 257933965Sjdp if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour) 258033965Sjdp return write_ieee_debugging_info (obfd, dhandle); 258133965Sjdp 258233965Sjdp if (bfd_get_flavour (obfd) == bfd_target_coff_flavour 258333965Sjdp || bfd_get_flavour (obfd) == bfd_target_elf_flavour) 258433965Sjdp { 258533965Sjdp bfd_byte *syms, *strings; 258633965Sjdp bfd_size_type symsize, stringsize; 258733965Sjdp asection *stabsec, *stabstrsec; 2588218822Sdim flagword flags; 258933965Sjdp 259033965Sjdp if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms, 259133965Sjdp &symsize, &strings, 259233965Sjdp &stringsize)) 2593130561Sobrien return FALSE; 259433965Sjdp 2595218822Sdim flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING; 2596218822Sdim stabsec = bfd_make_section_with_flags (obfd, ".stab", flags); 2597218822Sdim stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags); 259833965Sjdp if (stabsec == NULL 259933965Sjdp || stabstrsec == NULL 260033965Sjdp || ! bfd_set_section_size (obfd, stabsec, symsize) 260133965Sjdp || ! bfd_set_section_size (obfd, stabstrsec, stringsize) 260233965Sjdp || ! bfd_set_section_alignment (obfd, stabsec, 2) 2603218822Sdim || ! bfd_set_section_alignment (obfd, stabstrsec, 0)) 260433965Sjdp { 260560484Sobrien non_fatal (_("%s: can't create debugging section: %s"), 260660484Sobrien bfd_get_filename (obfd), 260760484Sobrien bfd_errmsg (bfd_get_error ())); 2608130561Sobrien return FALSE; 260933965Sjdp } 261033965Sjdp 261133965Sjdp /* We can get away with setting the section contents now because 261233965Sjdp the next thing the caller is going to do is copy over the 261333965Sjdp real sections. We may someday have to split the contents 261433965Sjdp setting out of this function. */ 2615130561Sobrien if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize) 2616130561Sobrien || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0, 2617130561Sobrien stringsize)) 261833965Sjdp { 261960484Sobrien non_fatal (_("%s: can't set debugging section contents: %s"), 262060484Sobrien bfd_get_filename (obfd), 262160484Sobrien bfd_errmsg (bfd_get_error ())); 2622130561Sobrien return FALSE; 262333965Sjdp } 262433965Sjdp 2625130561Sobrien return TRUE; 262633965Sjdp } 262733965Sjdp 262860484Sobrien non_fatal (_("%s: don't know how to write debugging information for %s"), 262960484Sobrien bfd_get_filename (obfd), bfd_get_target (obfd)); 2630130561Sobrien return FALSE; 263133965Sjdp} 263233965Sjdp 263333965Sjdpstatic int 2634130561Sobrienstrip_main (int argc, char *argv[]) 263533965Sjdp{ 2636130561Sobrien char *input_target = NULL; 2637130561Sobrien char *output_target = NULL; 2638130561Sobrien bfd_boolean show_version = FALSE; 2639130561Sobrien bfd_boolean formats_info = FALSE; 2640130561Sobrien int c; 2641130561Sobrien int i; 264233965Sjdp struct section_list *p; 264333965Sjdp char *output_file = NULL; 264433965Sjdp 2645130561Sobrien while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvw", 264633965Sjdp strip_options, (int *) 0)) != EOF) 264733965Sjdp { 264833965Sjdp switch (c) 264933965Sjdp { 265033965Sjdp case 'I': 265133965Sjdp input_target = optarg; 265233965Sjdp break; 265333965Sjdp case 'O': 265433965Sjdp output_target = optarg; 265533965Sjdp break; 265633965Sjdp case 'F': 265733965Sjdp input_target = output_target = optarg; 265833965Sjdp break; 265933965Sjdp case 'R': 2660130561Sobrien p = find_section_list (optarg, TRUE); 2661130561Sobrien p->remove = TRUE; 2662130561Sobrien sections_removed = TRUE; 266333965Sjdp break; 266433965Sjdp case 's': 266560484Sobrien strip_symbols = STRIP_ALL; 266633965Sjdp break; 266733965Sjdp case 'S': 266833965Sjdp case 'g': 266977298Sobrien case 'd': /* Historic BSD alias for -g. Used by early NetBSD. */ 267060484Sobrien strip_symbols = STRIP_DEBUG; 267133965Sjdp break; 267233965Sjdp case OPTION_STRIP_UNNEEDED: 267360484Sobrien strip_symbols = STRIP_UNNEEDED; 267433965Sjdp break; 267533965Sjdp case 'K': 267638889Sjdp add_specific_symbol (optarg, &keep_specific_list); 267733965Sjdp break; 267833965Sjdp case 'N': 267938889Sjdp add_specific_symbol (optarg, &strip_specific_list); 268033965Sjdp break; 268133965Sjdp case 'o': 268233965Sjdp output_file = optarg; 268333965Sjdp break; 268433965Sjdp case 'p': 2685130561Sobrien preserve_dates = TRUE; 268633965Sjdp break; 268733965Sjdp case 'x': 268860484Sobrien discard_locals = LOCALS_ALL; 268933965Sjdp break; 269033965Sjdp case 'X': 269160484Sobrien discard_locals = LOCALS_START_L; 269233965Sjdp break; 269333965Sjdp case 'v': 2694130561Sobrien verbose = TRUE; 269533965Sjdp break; 269633965Sjdp case 'V': 2697130561Sobrien show_version = TRUE; 269833965Sjdp break; 2699130561Sobrien case OPTION_FORMATS_INFO: 2700130561Sobrien formats_info = TRUE; 2701130561Sobrien break; 2702130561Sobrien case OPTION_ONLY_KEEP_DEBUG: 2703130561Sobrien strip_symbols = STRIP_NONDEBUG; 2704130561Sobrien break; 2705218822Sdim case OPTION_KEEP_FILE_SYMBOLS: 2706218822Sdim keep_file_symbols = 1; 2707218822Sdim break; 270833965Sjdp case 0: 270989857Sobrien /* We've been given a long option. */ 271089857Sobrien break; 2711130561Sobrien case 'w': 2712130561Sobrien wildcard = TRUE; 2713130561Sobrien break; 271489857Sobrien case 'H': 271533965Sjdp case 'h': 271633965Sjdp strip_usage (stdout, 0); 271733965Sjdp default: 271833965Sjdp strip_usage (stderr, 1); 271933965Sjdp } 272033965Sjdp } 272133965Sjdp 2722130561Sobrien if (formats_info) 2723130561Sobrien { 2724130561Sobrien display_info (); 2725130561Sobrien return 0; 2726130561Sobrien } 2727218822Sdim 272833965Sjdp if (show_version) 272933965Sjdp print_version ("strip"); 273033965Sjdp 273133965Sjdp /* Default is to strip all symbols. */ 273260484Sobrien if (strip_symbols == STRIP_UNDEF 273360484Sobrien && discard_locals == LOCALS_UNDEF 273433965Sjdp && strip_specific_list == NULL) 273560484Sobrien strip_symbols = STRIP_ALL; 273633965Sjdp 2737130561Sobrien if (output_target == NULL) 273833965Sjdp output_target = input_target; 273933965Sjdp 274033965Sjdp i = optind; 274133965Sjdp if (i == argc 274233965Sjdp || (output_file != NULL && (i + 1) < argc)) 274333965Sjdp strip_usage (stderr, 1); 274433965Sjdp 274533965Sjdp for (; i < argc; i++) 274633965Sjdp { 274733965Sjdp int hold_status = status; 274838889Sjdp struct stat statbuf; 274933965Sjdp char *tmpname; 275033965Sjdp 2751130561Sobrien if (get_file_size (argv[i]) < 1) 2752218822Sdim { 2753218822Sdim status = 1; 2754218822Sdim continue; 2755218822Sdim } 2756130561Sobrien 275738889Sjdp if (preserve_dates) 2758130561Sobrien /* No need to check the return value of stat(). 2759130561Sobrien It has already been checked in get_file_size(). */ 2760130561Sobrien stat (argv[i], &statbuf); 276138889Sjdp 2762218822Sdim if (output_file == NULL || strcmp (argv[i], output_file) == 0) 2763218822Sdim tmpname = make_tempname (argv[i]); 2764218822Sdim else 276533965Sjdp tmpname = output_file; 2766218822Sdim 2767218822Sdim if (tmpname == NULL) 2768218822Sdim { 2769218822Sdim non_fatal (_("could not create temporary file to hold stripped copy of '%s'"), 2770218822Sdim argv[i]); 2771218822Sdim status = 1; 2772218822Sdim continue; 2773218822Sdim } 2774218822Sdim 277533965Sjdp status = 0; 277633965Sjdp copy_file (argv[i], tmpname, input_target, output_target); 277733965Sjdp if (status == 0) 277833965Sjdp { 277933965Sjdp if (preserve_dates) 278038889Sjdp set_times (tmpname, &statbuf); 2781218822Sdim if (output_file != tmpname) 2782218822Sdim smart_rename (tmpname, output_file ? output_file : argv[i], 2783218822Sdim preserve_dates); 278433965Sjdp status = hold_status; 278533965Sjdp } 278633965Sjdp else 2787218822Sdim unlink_if_ordinary (tmpname); 2788218822Sdim if (output_file != tmpname) 278933965Sjdp free (tmpname); 279033965Sjdp } 279133965Sjdp 2792218822Sdim return status; 279333965Sjdp} 279433965Sjdp 279533965Sjdpstatic int 2796130561Sobriencopy_main (int argc, char *argv[]) 279733965Sjdp{ 279889857Sobrien char * binary_architecture = NULL; 2799130561Sobrien char *input_filename = NULL; 2800130561Sobrien char *output_filename = NULL; 2801218822Sdim char *tmpname; 2802130561Sobrien char *input_target = NULL; 2803130561Sobrien char *output_target = NULL; 2804130561Sobrien bfd_boolean show_version = FALSE; 2805130561Sobrien bfd_boolean change_warn = TRUE; 2806130561Sobrien bfd_boolean formats_info = FALSE; 280733965Sjdp int c; 280833965Sjdp struct section_list *p; 280938889Sjdp struct stat statbuf; 281033965Sjdp 2811130561Sobrien while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:w", 281233965Sjdp copy_options, (int *) 0)) != EOF) 281333965Sjdp { 281433965Sjdp switch (c) 281533965Sjdp { 281633965Sjdp case 'b': 281760484Sobrien copy_byte = atoi (optarg); 281833965Sjdp if (copy_byte < 0) 281960484Sobrien fatal (_("byte number must be non-negative")); 282033965Sjdp break; 282160484Sobrien 2822104834Sobrien case 'B': 2823104834Sobrien binary_architecture = optarg; 2824104834Sobrien break; 282589857Sobrien 282633965Sjdp case 'i': 282760484Sobrien interleave = atoi (optarg); 282833965Sjdp if (interleave < 1) 282960484Sobrien fatal (_("interleave must be positive")); 283033965Sjdp break; 283160484Sobrien 283233965Sjdp case 'I': 283333965Sjdp case 's': /* "source" - 'I' is preferred */ 283433965Sjdp input_target = optarg; 283533965Sjdp break; 283660484Sobrien 283733965Sjdp case 'O': 283833965Sjdp case 'd': /* "destination" - 'O' is preferred */ 283933965Sjdp output_target = optarg; 284033965Sjdp break; 284160484Sobrien 284233965Sjdp case 'F': 284333965Sjdp input_target = output_target = optarg; 284433965Sjdp break; 284560484Sobrien 284660484Sobrien case 'j': 2847130561Sobrien p = find_section_list (optarg, TRUE); 284860484Sobrien if (p->remove) 284960484Sobrien fatal (_("%s both copied and removed"), optarg); 2850130561Sobrien p->copy = TRUE; 2851130561Sobrien sections_copied = TRUE; 285260484Sobrien break; 285360484Sobrien 285433965Sjdp case 'R': 2855130561Sobrien p = find_section_list (optarg, TRUE); 285660484Sobrien if (p->copy) 285760484Sobrien fatal (_("%s both copied and removed"), optarg); 2858130561Sobrien p->remove = TRUE; 2859130561Sobrien sections_removed = TRUE; 286033965Sjdp break; 286160484Sobrien 286233965Sjdp case 'S': 286360484Sobrien strip_symbols = STRIP_ALL; 286433965Sjdp break; 286560484Sobrien 286633965Sjdp case 'g': 286760484Sobrien strip_symbols = STRIP_DEBUG; 286833965Sjdp break; 286960484Sobrien 287033965Sjdp case OPTION_STRIP_UNNEEDED: 287160484Sobrien strip_symbols = STRIP_UNNEEDED; 287233965Sjdp break; 287360484Sobrien 2874130561Sobrien case OPTION_ONLY_KEEP_DEBUG: 2875130561Sobrien strip_symbols = STRIP_NONDEBUG; 2876130561Sobrien break; 2877130561Sobrien 2878218822Sdim case OPTION_KEEP_FILE_SYMBOLS: 2879218822Sdim keep_file_symbols = 1; 2880218822Sdim break; 2881218822Sdim 2882130561Sobrien case OPTION_ADD_GNU_DEBUGLINK: 2883130561Sobrien gnu_debuglink_filename = optarg; 2884130561Sobrien break; 2885130561Sobrien 288633965Sjdp case 'K': 288738889Sjdp add_specific_symbol (optarg, &keep_specific_list); 288833965Sjdp break; 288960484Sobrien 289033965Sjdp case 'N': 289138889Sjdp add_specific_symbol (optarg, &strip_specific_list); 289233965Sjdp break; 289360484Sobrien 2894218822Sdim case OPTION_STRIP_UNNEEDED_SYMBOL: 2895218822Sdim add_specific_symbol (optarg, &strip_unneeded_list); 2896218822Sdim break; 2897218822Sdim 289838889Sjdp case 'L': 289938889Sjdp add_specific_symbol (optarg, &localize_specific_list); 290038889Sjdp break; 290160484Sobrien 2902218822Sdim case OPTION_GLOBALIZE_SYMBOL: 2903218822Sdim add_specific_symbol (optarg, &globalize_specific_list); 2904218822Sdim break; 2905218822Sdim 290678828Sobrien case 'G': 290778828Sobrien add_specific_symbol (optarg, &keepglobal_specific_list); 290878828Sobrien break; 290978828Sobrien 291038889Sjdp case 'W': 291138889Sjdp add_specific_symbol (optarg, &weaken_specific_list); 291238889Sjdp break; 291360484Sobrien 291433965Sjdp case 'p': 2915130561Sobrien preserve_dates = TRUE; 291633965Sjdp break; 291760484Sobrien 2918130561Sobrien case 'w': 2919130561Sobrien wildcard = TRUE; 2920130561Sobrien break; 2921130561Sobrien 292233965Sjdp case 'x': 292360484Sobrien discard_locals = LOCALS_ALL; 292433965Sjdp break; 292560484Sobrien 292633965Sjdp case 'X': 292760484Sobrien discard_locals = LOCALS_START_L; 292833965Sjdp break; 292960484Sobrien 293033965Sjdp case 'v': 2931130561Sobrien verbose = TRUE; 293233965Sjdp break; 293360484Sobrien 293433965Sjdp case 'V': 2935130561Sobrien show_version = TRUE; 293633965Sjdp break; 293760484Sobrien 2938130561Sobrien case OPTION_FORMATS_INFO: 2939130561Sobrien formats_info = TRUE; 2940130561Sobrien break; 2941130561Sobrien 294233965Sjdp case OPTION_WEAKEN: 2943130561Sobrien weaken = TRUE; 294433965Sjdp break; 294560484Sobrien 294633965Sjdp case OPTION_ADD_SECTION: 294733965Sjdp { 294833965Sjdp const char *s; 2949130561Sobrien off_t size; 295033965Sjdp struct section_add *pa; 295133965Sjdp int len; 295233965Sjdp char *name; 295333965Sjdp FILE *f; 295433965Sjdp 295533965Sjdp s = strchr (optarg, '='); 295660484Sobrien 295733965Sjdp if (s == NULL) 295860484Sobrien fatal (_("bad format for %s"), "--add-section"); 295933965Sjdp 2960130561Sobrien size = get_file_size (s + 1); 2961130561Sobrien if (size < 1) 2962218822Sdim { 2963218822Sdim status = 1; 2964218822Sdim break; 2965218822Sdim } 296633965Sjdp 2967130561Sobrien pa = xmalloc (sizeof (struct section_add)); 296833965Sjdp 296933965Sjdp len = s - optarg; 2970130561Sobrien name = xmalloc (len + 1); 297133965Sjdp strncpy (name, optarg, len); 297233965Sjdp name[len] = '\0'; 297333965Sjdp pa->name = name; 297433965Sjdp 297533965Sjdp pa->filename = s + 1; 2976130561Sobrien pa->size = size; 2977130561Sobrien pa->contents = xmalloc (size); 297833965Sjdp 297933965Sjdp f = fopen (pa->filename, FOPEN_RB); 298060484Sobrien 298133965Sjdp if (f == NULL) 2982130561Sobrien fatal (_("cannot open: %s: %s"), 2983130561Sobrien pa->filename, strerror (errno)); 298460484Sobrien 298533965Sjdp if (fread (pa->contents, 1, pa->size, f) == 0 298633965Sjdp || ferror (f)) 298760484Sobrien fatal (_("%s: fread failed"), pa->filename); 298860484Sobrien 298933965Sjdp fclose (f); 299033965Sjdp 299133965Sjdp pa->next = add_sections; 299233965Sjdp add_sections = pa; 299333965Sjdp } 299433965Sjdp break; 299560484Sobrien 299660484Sobrien case OPTION_CHANGE_START: 299760484Sobrien change_start = parse_vma (optarg, "--change-start"); 299833965Sjdp break; 299960484Sobrien 300060484Sobrien case OPTION_CHANGE_SECTION_ADDRESS: 300160484Sobrien case OPTION_CHANGE_SECTION_LMA: 300260484Sobrien case OPTION_CHANGE_SECTION_VMA: 300333965Sjdp { 300433965Sjdp const char *s; 300533965Sjdp int len; 300633965Sjdp char *name; 300760484Sobrien char *option = NULL; 300860484Sobrien bfd_vma val; 300960484Sobrien enum change_action what = CHANGE_IGNORE; 301033965Sjdp 301160484Sobrien switch (c) 301260484Sobrien { 301360484Sobrien case OPTION_CHANGE_SECTION_ADDRESS: 301460484Sobrien option = "--change-section-address"; 301560484Sobrien break; 301660484Sobrien case OPTION_CHANGE_SECTION_LMA: 301760484Sobrien option = "--change-section-lma"; 301860484Sobrien break; 301960484Sobrien case OPTION_CHANGE_SECTION_VMA: 302060484Sobrien option = "--change-section-vma"; 302160484Sobrien break; 302260484Sobrien } 302360484Sobrien 302433965Sjdp s = strchr (optarg, '='); 302533965Sjdp if (s == NULL) 302633965Sjdp { 302733965Sjdp s = strchr (optarg, '+'); 302833965Sjdp if (s == NULL) 302933965Sjdp { 303033965Sjdp s = strchr (optarg, '-'); 303133965Sjdp if (s == NULL) 303260484Sobrien fatal (_("bad format for %s"), option); 303333965Sjdp } 303433965Sjdp } 303533965Sjdp 303633965Sjdp len = s - optarg; 3037130561Sobrien name = xmalloc (len + 1); 303833965Sjdp strncpy (name, optarg, len); 303933965Sjdp name[len] = '\0'; 304033965Sjdp 3041130561Sobrien p = find_section_list (name, TRUE); 304233965Sjdp 304360484Sobrien val = parse_vma (s + 1, option); 304433965Sjdp 304560484Sobrien switch (*s) 304633965Sjdp { 304760484Sobrien case '=': what = CHANGE_SET; break; 304860484Sobrien case '-': val = - val; /* Drop through. */ 304960484Sobrien case '+': what = CHANGE_MODIFY; break; 305033965Sjdp } 305160484Sobrien 305260484Sobrien switch (c) 305360484Sobrien { 305460484Sobrien case OPTION_CHANGE_SECTION_ADDRESS: 305560484Sobrien p->change_vma = what; 305660484Sobrien p->vma_val = val; 305760484Sobrien /* Drop through. */ 305860484Sobrien 305960484Sobrien case OPTION_CHANGE_SECTION_LMA: 306060484Sobrien p->change_lma = what; 306160484Sobrien p->lma_val = val; 306260484Sobrien break; 306360484Sobrien 306460484Sobrien case OPTION_CHANGE_SECTION_VMA: 306560484Sobrien p->change_vma = what; 306660484Sobrien p->vma_val = val; 306760484Sobrien break; 306860484Sobrien } 306933965Sjdp } 307033965Sjdp break; 307160484Sobrien 307260484Sobrien case OPTION_CHANGE_ADDRESSES: 307360484Sobrien change_section_address = parse_vma (optarg, "--change-addresses"); 307460484Sobrien change_start = change_section_address; 307533965Sjdp break; 307660484Sobrien 307760484Sobrien case OPTION_CHANGE_WARNINGS: 3078130561Sobrien change_warn = TRUE; 307933965Sjdp break; 308060484Sobrien 308133965Sjdp case OPTION_CHANGE_LEADING_CHAR: 3082130561Sobrien change_leading_char = TRUE; 308333965Sjdp break; 308460484Sobrien 308533965Sjdp case OPTION_DEBUGGING: 3086130561Sobrien convert_debugging = TRUE; 308733965Sjdp break; 308860484Sobrien 308933965Sjdp case OPTION_GAP_FILL: 309033965Sjdp { 309133965Sjdp bfd_vma gap_fill_vma; 309233965Sjdp 309333965Sjdp gap_fill_vma = parse_vma (optarg, "--gap-fill"); 309433965Sjdp gap_fill = (bfd_byte) gap_fill_vma; 309533965Sjdp if ((bfd_vma) gap_fill != gap_fill_vma) 309633965Sjdp { 309760484Sobrien char buff[20]; 309860484Sobrien 309960484Sobrien sprintf_vma (buff, gap_fill_vma); 310060484Sobrien 310160484Sobrien non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"), 310260484Sobrien buff, gap_fill); 310333965Sjdp } 3104130561Sobrien gap_fill_set = TRUE; 310533965Sjdp } 310633965Sjdp break; 310760484Sobrien 310860484Sobrien case OPTION_NO_CHANGE_WARNINGS: 3109130561Sobrien change_warn = FALSE; 311033965Sjdp break; 311160484Sobrien 311233965Sjdp case OPTION_PAD_TO: 311333965Sjdp pad_to = parse_vma (optarg, "--pad-to"); 3114130561Sobrien pad_to_set = TRUE; 311533965Sjdp break; 311660484Sobrien 311733965Sjdp case OPTION_REMOVE_LEADING_CHAR: 3118130561Sobrien remove_leading_char = TRUE; 311933965Sjdp break; 312060484Sobrien 312160484Sobrien case OPTION_REDEFINE_SYM: 312260484Sobrien { 312360484Sobrien /* Push this redefinition onto redefine_symbol_list. */ 312460484Sobrien 312560484Sobrien int len; 312660484Sobrien const char *s; 312760484Sobrien const char *nextarg; 312860484Sobrien char *source, *target; 312960484Sobrien 313060484Sobrien s = strchr (optarg, '='); 313160484Sobrien if (s == NULL) 313289857Sobrien fatal (_("bad format for %s"), "--redefine-sym"); 313360484Sobrien 313460484Sobrien len = s - optarg; 3135130561Sobrien source = xmalloc (len + 1); 313660484Sobrien strncpy (source, optarg, len); 313760484Sobrien source[len] = '\0'; 313860484Sobrien 313960484Sobrien nextarg = s + 1; 314060484Sobrien len = strlen (nextarg); 3141130561Sobrien target = xmalloc (len + 1); 314260484Sobrien strcpy (target, nextarg); 314360484Sobrien 3144130561Sobrien redefine_list_append ("--redefine-sym", source, target); 314560484Sobrien 314660484Sobrien free (source); 314760484Sobrien free (target); 314860484Sobrien } 314960484Sobrien break; 315060484Sobrien 3151130561Sobrien case OPTION_REDEFINE_SYMS: 3152130561Sobrien add_redefine_syms_file (optarg); 3153130561Sobrien break; 3154130561Sobrien 315533965Sjdp case OPTION_SET_SECTION_FLAGS: 315633965Sjdp { 315733965Sjdp const char *s; 315833965Sjdp int len; 315933965Sjdp char *name; 316033965Sjdp 316133965Sjdp s = strchr (optarg, '='); 316233965Sjdp if (s == NULL) 316360484Sobrien fatal (_("bad format for %s"), "--set-section-flags"); 316433965Sjdp 316533965Sjdp len = s - optarg; 3166130561Sobrien name = xmalloc (len + 1); 316733965Sjdp strncpy (name, optarg, len); 316833965Sjdp name[len] = '\0'; 316933965Sjdp 3170130561Sobrien p = find_section_list (name, TRUE); 317133965Sjdp 3172130561Sobrien p->set_flags = TRUE; 317333965Sjdp p->flags = parse_flags (s + 1); 317433965Sjdp } 317533965Sjdp break; 317660484Sobrien 317789857Sobrien case OPTION_RENAME_SECTION: 317889857Sobrien { 317989857Sobrien flagword flags; 318089857Sobrien const char *eq, *fl; 318189857Sobrien char *old_name; 318289857Sobrien char *new_name; 318389857Sobrien unsigned int len; 318489857Sobrien 318589857Sobrien eq = strchr (optarg, '='); 318689857Sobrien if (eq == NULL) 318789857Sobrien fatal (_("bad format for %s"), "--rename-section"); 318889857Sobrien 318989857Sobrien len = eq - optarg; 319089857Sobrien if (len == 0) 319189857Sobrien fatal (_("bad format for %s"), "--rename-section"); 319289857Sobrien 3193130561Sobrien old_name = xmalloc (len + 1); 319489857Sobrien strncpy (old_name, optarg, len); 319589857Sobrien old_name[len] = 0; 319689857Sobrien 319789857Sobrien eq++; 319889857Sobrien fl = strchr (eq, ','); 319989857Sobrien if (fl) 320089857Sobrien { 320189857Sobrien flags = parse_flags (fl + 1); 320289857Sobrien len = fl - eq; 320389857Sobrien } 320489857Sobrien else 320589857Sobrien { 320689857Sobrien flags = -1; 320789857Sobrien len = strlen (eq); 320889857Sobrien } 320989857Sobrien 321089857Sobrien if (len == 0) 321189857Sobrien fatal (_("bad format for %s"), "--rename-section"); 321289857Sobrien 3213130561Sobrien new_name = xmalloc (len + 1); 321489857Sobrien strncpy (new_name, eq, len); 321589857Sobrien new_name[len] = 0; 321689857Sobrien 321789857Sobrien add_section_rename (old_name, new_name, flags); 321889857Sobrien } 321989857Sobrien break; 322089857Sobrien 322133965Sjdp case OPTION_SET_START: 322233965Sjdp set_start = parse_vma (optarg, "--set-start"); 3223130561Sobrien set_start_set = TRUE; 322433965Sjdp break; 322560484Sobrien 3226104834Sobrien case OPTION_SREC_LEN: 3227104834Sobrien Chunk = parse_vma (optarg, "--srec-len"); 3228104834Sobrien break; 322977298Sobrien 3230104834Sobrien case OPTION_SREC_FORCES3: 3231130561Sobrien S3Forced = TRUE; 3232104834Sobrien break; 323377298Sobrien 323478828Sobrien case OPTION_STRIP_SYMBOLS: 323578828Sobrien add_specific_symbols (optarg, &strip_specific_list); 323678828Sobrien break; 323778828Sobrien 3238218822Sdim case OPTION_STRIP_UNNEEDED_SYMBOLS: 3239218822Sdim add_specific_symbols (optarg, &strip_unneeded_list); 3240218822Sdim break; 3241218822Sdim 324278828Sobrien case OPTION_KEEP_SYMBOLS: 324378828Sobrien add_specific_symbols (optarg, &keep_specific_list); 324478828Sobrien break; 324578828Sobrien 3246218822Sdim case OPTION_LOCALIZE_HIDDEN: 3247218822Sdim localize_hidden = TRUE; 3248218822Sdim break; 3249218822Sdim 325078828Sobrien case OPTION_LOCALIZE_SYMBOLS: 325178828Sobrien add_specific_symbols (optarg, &localize_specific_list); 325278828Sobrien break; 325378828Sobrien 3254218822Sdim case OPTION_GLOBALIZE_SYMBOLS: 3255218822Sdim add_specific_symbols (optarg, &globalize_specific_list); 3256218822Sdim break; 3257218822Sdim 325878828Sobrien case OPTION_KEEPGLOBAL_SYMBOLS: 325978828Sobrien add_specific_symbols (optarg, &keepglobal_specific_list); 326078828Sobrien break; 326178828Sobrien 326278828Sobrien case OPTION_WEAKEN_SYMBOLS: 326378828Sobrien add_specific_symbols (optarg, &weaken_specific_list); 326478828Sobrien break; 326578828Sobrien 326689857Sobrien case OPTION_ALT_MACH_CODE: 3267218822Sdim use_alt_mach_code = strtoul (optarg, NULL, 0); 3268218822Sdim if (use_alt_mach_code == 0) 3269218822Sdim fatal (_("unable to parse alternative machine code")); 327089857Sobrien break; 327189857Sobrien 3272130561Sobrien case OPTION_PREFIX_SYMBOLS: 3273130561Sobrien prefix_symbols_string = optarg; 3274130561Sobrien break; 3275130561Sobrien 3276130561Sobrien case OPTION_PREFIX_SECTIONS: 3277130561Sobrien prefix_sections_string = optarg; 3278130561Sobrien break; 3279130561Sobrien 3280130561Sobrien case OPTION_PREFIX_ALLOC_SECTIONS: 3281130561Sobrien prefix_alloc_sections_string = optarg; 3282130561Sobrien break; 3283130561Sobrien 3284130561Sobrien case OPTION_READONLY_TEXT: 3285130561Sobrien bfd_flags_to_set |= WP_TEXT; 3286130561Sobrien bfd_flags_to_clear &= ~WP_TEXT; 3287130561Sobrien break; 3288130561Sobrien 3289130561Sobrien case OPTION_WRITABLE_TEXT: 3290130561Sobrien bfd_flags_to_clear |= WP_TEXT; 3291130561Sobrien bfd_flags_to_set &= ~WP_TEXT; 3292130561Sobrien break; 3293130561Sobrien 3294130561Sobrien case OPTION_PURE: 3295130561Sobrien bfd_flags_to_set |= D_PAGED; 3296130561Sobrien bfd_flags_to_clear &= ~D_PAGED; 3297130561Sobrien break; 3298130561Sobrien 3299130561Sobrien case OPTION_IMPURE: 3300130561Sobrien bfd_flags_to_clear |= D_PAGED; 3301130561Sobrien bfd_flags_to_set &= ~D_PAGED; 3302130561Sobrien break; 3303130561Sobrien 3304218822Sdim case OPTION_EXTRACT_SYMBOL: 3305218822Sdim extract_symbol = TRUE; 3306218822Sdim break; 3307218822Sdim 3308218822Sdim case OPTION_REVERSE_BYTES: 3309218822Sdim { 3310218822Sdim int prev = reverse_bytes; 3311218822Sdim 3312218822Sdim reverse_bytes = atoi (optarg); 3313218822Sdim if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0)) 3314218822Sdim fatal (_("number of bytes to reverse must be positive and even")); 3315218822Sdim 3316218822Sdim if (prev && prev != reverse_bytes) 3317218822Sdim non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"), 3318218822Sdim prev); 3319218822Sdim break; 3320218822Sdim } 3321218822Sdim 332233965Sjdp case 0: 3323130561Sobrien /* We've been given a long option. */ 3324130561Sobrien break; 332560484Sobrien 332689857Sobrien case 'H': 332733965Sjdp case 'h': 332833965Sjdp copy_usage (stdout, 0); 332960484Sobrien 333033965Sjdp default: 333133965Sjdp copy_usage (stderr, 1); 333233965Sjdp } 333333965Sjdp } 333433965Sjdp 3335130561Sobrien if (formats_info) 3336130561Sobrien { 3337130561Sobrien display_info (); 3338130561Sobrien return 0; 3339130561Sobrien } 3340218822Sdim 334133965Sjdp if (show_version) 334233965Sjdp print_version ("objcopy"); 334333965Sjdp 334433965Sjdp if (copy_byte >= interleave) 334560484Sobrien fatal (_("byte number must be less than interleave")); 334633965Sjdp 334733965Sjdp if (optind == argc || optind + 2 < argc) 334833965Sjdp copy_usage (stderr, 1); 334933965Sjdp 335033965Sjdp input_filename = argv[optind]; 335133965Sjdp if (optind + 1 < argc) 335233965Sjdp output_filename = argv[optind + 1]; 335333965Sjdp 335433965Sjdp /* Default is to strip no symbols. */ 335560484Sobrien if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF) 335660484Sobrien strip_symbols = STRIP_NONE; 335733965Sjdp 3358130561Sobrien if (output_target == NULL) 335933965Sjdp output_target = input_target; 336033965Sjdp 3361130561Sobrien if (binary_architecture != NULL) 336289857Sobrien { 336389857Sobrien if (input_target && strcmp (input_target, "binary") == 0) 3364104834Sobrien { 3365104834Sobrien const bfd_arch_info_type * temp_arch_info; 336689857Sobrien 336789857Sobrien temp_arch_info = bfd_scan_arch (binary_architecture); 336889857Sobrien 3369104834Sobrien if (temp_arch_info != NULL) 3370130561Sobrien { 3371130561Sobrien bfd_external_binary_architecture = temp_arch_info->arch; 3372130561Sobrien bfd_external_machine = temp_arch_info->mach; 3373130561Sobrien } 3374104834Sobrien else 3375104834Sobrien fatal (_("architecture %s unknown"), binary_architecture); 3376104834Sobrien } 337789857Sobrien else 337889857Sobrien { 337989857Sobrien non_fatal (_("Warning: input target 'binary' required for binary architecture parameter.")); 338089857Sobrien non_fatal (_(" Argument %s ignored"), binary_architecture); 338189857Sobrien } 338289857Sobrien } 338389857Sobrien 338438889Sjdp if (preserve_dates) 338580016Sobrien if (stat (input_filename, & statbuf) < 0) 3386130561Sobrien fatal (_("warning: could not locate '%s'. System error message: %s"), 3387130561Sobrien input_filename, strerror (errno)); 338838889Sjdp 3389130561Sobrien /* If there is no destination file, or the source and destination files 3390130561Sobrien are the same, then create a temp and rename the result into the input. */ 3391130561Sobrien if (output_filename == NULL || strcmp (input_filename, output_filename) == 0) 3392218822Sdim tmpname = make_tempname (input_filename); 3393218822Sdim else 3394218822Sdim tmpname = output_filename; 3395218822Sdim 3396218822Sdim if (tmpname == NULL) 3397218822Sdim fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), 3398218822Sdim input_filename, strerror (errno)); 3399218822Sdim 3400218822Sdim copy_file (input_filename, tmpname, input_target, output_target); 3401218822Sdim if (status == 0) 340233965Sjdp { 3403218822Sdim if (preserve_dates) 3404218822Sdim set_times (tmpname, &statbuf); 3405218822Sdim if (tmpname != output_filename) 3406218822Sdim smart_rename (tmpname, input_filename, preserve_dates); 340733965Sjdp } 340833965Sjdp else 3409218822Sdim unlink_if_ordinary (tmpname); 341089857Sobrien 341160484Sobrien if (change_warn) 341233965Sjdp { 341360484Sobrien for (p = change_sections; p != NULL; p = p->next) 341433965Sjdp { 341560484Sobrien if (! p->used) 341633965Sjdp { 341760484Sobrien if (p->change_vma != CHANGE_IGNORE) 341860484Sobrien { 341960484Sobrien char buff [20]; 342060484Sobrien 342160484Sobrien sprintf_vma (buff, p->vma_val); 342260484Sobrien 342360484Sobrien /* xgettext:c-format */ 342460484Sobrien non_fatal (_("%s %s%c0x%s never used"), 342560484Sobrien "--change-section-vma", 342660484Sobrien p->name, 342760484Sobrien p->change_vma == CHANGE_SET ? '=' : '+', 342860484Sobrien buff); 342960484Sobrien } 343060484Sobrien 343160484Sobrien if (p->change_lma != CHANGE_IGNORE) 343260484Sobrien { 343360484Sobrien char buff [20]; 343460484Sobrien 343560484Sobrien sprintf_vma (buff, p->lma_val); 343660484Sobrien 343760484Sobrien /* xgettext:c-format */ 343860484Sobrien non_fatal (_("%s %s%c0x%s never used"), 343960484Sobrien "--change-section-lma", 344060484Sobrien p->name, 344160484Sobrien p->change_lma == CHANGE_SET ? '=' : '+', 344260484Sobrien buff); 344360484Sobrien } 344433965Sjdp } 344533965Sjdp } 344633965Sjdp } 344733965Sjdp 344833965Sjdp return 0; 344933965Sjdp} 345033965Sjdp 345133965Sjdpint 3452130561Sobrienmain (int argc, char *argv[]) 345333965Sjdp{ 345460484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 345560484Sobrien setlocale (LC_MESSAGES, ""); 345660484Sobrien#endif 345789857Sobrien#if defined (HAVE_SETLOCALE) 345889857Sobrien setlocale (LC_CTYPE, ""); 345989857Sobrien#endif 346060484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 346160484Sobrien textdomain (PACKAGE); 346260484Sobrien 346333965Sjdp program_name = argv[0]; 346433965Sjdp xmalloc_set_program_name (program_name); 346533965Sjdp 346633965Sjdp START_PROGRESS (program_name, 0); 346733965Sjdp 3468218822Sdim expandargv (&argc, &argv); 3469218822Sdim 347060484Sobrien strip_symbols = STRIP_UNDEF; 347160484Sobrien discard_locals = LOCALS_UNDEF; 347233965Sjdp 347333965Sjdp bfd_init (); 347433965Sjdp set_default_bfd_target (); 347533965Sjdp 347633965Sjdp if (is_strip < 0) 347733965Sjdp { 347833965Sjdp int i = strlen (program_name); 347961843Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 348061843Sobrien /* Drop the .exe suffix, if any. */ 348161843Sobrien if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0) 348261843Sobrien { 348361843Sobrien i -= 4; 348461843Sobrien program_name[i] = '\0'; 348561843Sobrien } 348661843Sobrien#endif 348761843Sobrien is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0); 348833965Sjdp } 348933965Sjdp 349033965Sjdp if (is_strip) 349133965Sjdp strip_main (argc, argv); 349233965Sjdp else 349333965Sjdp copy_main (argc, argv); 349433965Sjdp 349533965Sjdp END_PROGRESS (program_name); 349633965Sjdp 349733965Sjdp return status; 349833965Sjdp} 3499