X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=21f579366dd6b390c5820ec0108064c1a7b42d6b;hb=23ccc829e251d20c40a4337d2ae6057a0bb951aa;hp=5fd77775d701a6c2af2e65eb2d8a5f7cc04e3d2f;hpb=252b5132c753830d5fd56823373aed85f2a0db63;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 5fd77775d7..21f579366d 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1,5 +1,5 @@ /* objcopy.c -- copy object file from input to output, optionally massaging it. - Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999 + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -25,6 +25,7 @@ #include "getopt.h" #include "libiberty.h" #include "budbg.h" +#include "filenames.h" #include /* A list of symbols to explicitly strip out, or to keep. A linked @@ -38,6 +39,14 @@ struct symlist struct symlist *next; }; +/* A list to support redefine_sym. */ +struct redefine_node +{ + char *source; + char *target; + struct redefine_node *next; +}; + static void copy_usage PARAMS ((FILE *, int)); static void strip_usage PARAMS ((FILE *, int)); static flagword parse_flags PARAMS ((const char *)); @@ -60,6 +69,8 @@ static void copy_file PARAMS ((const char *, const char *, const char *, const char *)); static int strip_main PARAMS ((int, char **)); static int copy_main PARAMS ((int, char **)); +static const char *lookup_sym_redefinition PARAMS((const char *)); +static void redefine_list_append PARAMS ((const char *, const char *)); #define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;} @@ -111,6 +122,7 @@ struct section_list const char * name; /* Section name. */ boolean used; /* Whether this entry was used. */ boolean remove; /* Whether to remove this section. */ + boolean copy; /* Whether to copy this section. */ enum change_action change_vma;/* Whether to change or set VMA. */ bfd_vma vma_val; /* Amount to change by or set to. */ enum change_action change_lma;/* Whether to change or set LMA. */ @@ -121,6 +133,7 @@ struct section_list static struct section_list *change_sections; static boolean sections_removed; +static boolean sections_copied; /* Changes to the start address. */ static bfd_vma change_start = 0; @@ -170,12 +183,13 @@ static boolean change_leading_char = false; static boolean remove_leading_char = false; -/* List of symbols to strip, keep, localize, and weaken. */ +/* List of symbols to strip, keep, localize, weaken, or redefine. */ static struct symlist *strip_specific_list = NULL; static struct symlist *keep_specific_list = NULL; static struct symlist *localize_specific_list = NULL; static struct symlist *weaken_specific_list = NULL; +static struct redefine_node *redefine_sym_list = NULL; /* If this is true, we weaken global symbols (set BSF_WEAK). */ @@ -200,6 +214,9 @@ static boolean weaken = false; #define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1) #define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1) #define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1) +#define OPTION_REDEFINE_SYM (OPTION_WEAKEN + 1) +#define OPTION_SREC_LEN (OPTION_REDEFINE_SYM + 1) +#define OPTION_SREC_FORCES3 (OPTION_SREC_LEN + 1) /* Options to handle if running as "strip". */ @@ -246,6 +263,7 @@ static struct option copy_options[] = {"debugging", no_argument, 0, OPTION_DEBUGGING}, {"discard-all", no_argument, 0, 'x'}, {"discard-locals", no_argument, 0, 'X'}, + {"only-section", required_argument, 0, 'j'}, {"format", required_argument, 0, 'F'}, /* Obsolete */ {"gap-fill", required_argument, 0, OPTION_GAP_FILL}, {"help", no_argument, 0, 'h'}, @@ -273,6 +291,9 @@ static struct option copy_options[] = {"version", no_argument, 0, 'V'}, {"weaken", no_argument, 0, OPTION_WEAKEN}, {"weaken-symbol", required_argument, 0, 'W'}, + {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM}, + {"srec-len", required_argument, 0, OPTION_SREC_LEN}, + {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3}, {0, no_argument, 0, 0} }; @@ -284,38 +305,72 @@ extern char *program_name; -1 means if we should use argv[0] to decide. */ extern int is_strip; +/* The maximum length of an S record. This variable is declared in srec.c + and can be modified by the --srec-len parameter. */ +extern unsigned int Chunk; + +/* Restrict the generation of Srecords to type S3 only. + This variable is declare in bfd/srec.c and can be toggled + on by the --srec-forceS3 command line switch. */ +extern boolean S3Forced; static void copy_usage (stream, exit_status) FILE *stream; int exit_status; { + fprintf (stream, _("Usage: %s in-file [out-file]\n"), program_name); + fprintf (stream, _(" The switches are:\n")); fprintf (stream, _("\ -Usage: %s [-vVSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\ - [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\ - [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ - [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ - [--discard-locals] [--debugging] [--remove-section=section]\n"), - program_name); - fprintf (stream, _("\ - [--gap-fill=val] [--pad-to=address] [--preserve-dates]\n\ - [--set-start=val] \n\ - [--change-start=incr] [--change-addresses=incr] \n\ - (--adjust-start and --adjust-vma are aliases for these two) \n\ - [--change-section-address=section{=,+,-}val]\n\ - (--adjust-section-vma is an alias for --change-section-address)\n\ - [--change-section-lma=section{=,+,-}val]\n\ - [--change-section-vma=section{=,+,-}val]\n\ - [--adjust-warnings] [--no-adjust-warnings]\n\ - [--change-warnings] [--no-change-warnings]\n\ - [--set-section-flags=section=flags] [--add-section=sectionname=filename]\n\ - [--keep-symbol symbol] [-K symbol] [--strip-symbol symbol] [-N symbol]\n\ - [--localize-symbol symbol] [-L symbol] [--weaken-symbol symbol]\n\ - [-W symbol] [--change-leading-char] [--remove-leading-char] [--weaken]\n\ - [--verbose] [--version] [--help] in-file [out-file]\n")); + -I --input-target Assume input file is in format \n\ + -O --output-target Create an output file in format \n\ + -F --target Set both input and output format to \n\ + --debugging Convert debugging information, if possible\n\ + -p --preserve-dates Copy modified/access timestamps to the output\n\ + -j --only-section Only copy section into the output\n\ + -R --remove-section Remove section from the output\n\ + -S --strip-all Remove all symbol and relocation information\n\ + -g --strip-debug Remove all debugging symbols\n\ + --strip-unneeded Remove all symbols not needed by relocations\n\ + -N --strip-symbol Do not copy symbol \n\ + -K --keep-symbol Only copy symbol \n\ + -L --localize-symbol Force symbol to be marked as a local\n\ + -W --weaken-symbol Force symbol to be marked as a weak\n\ + --weaken Force all global symbols to be marked as weak\n\ + -x --discard-all Remove all non-global symbols\n\ + -X --discard-locals Remove any compiler-generated symbols\n\ + -i --interleave Only copy one out of every bytes\n\ + -b --byte Select byte in every interleaved block\n\ + --gap-fill Fill gaps between sections with \n\ + --pad-to Pad the last section up to address \n\ + --set-start Set the start address to \n\ + {--change-start|--adjust-start} \n\ + Add to the start address\n\ + {--change-addresses|--adjust-vma} \n\ + Add to LMA, VMA and start addresses\n\ + {--change-section-address|--adjust-section-vma} {=|+|-}\n\ + Change LMA and VMA of section by \n\ + --change-section-lma {=|+|-}\n\ + Change the LMA of section by \n\ + --change-section-vma {=|+|-}\n\ + Change the VMA of section by \n\ + {--[no-]change-warnings|--[no-]adjust-warnings}\n\ + Warn if a named section does not exist\n\ + --set-section-flags =\n\ + Set section 's properties to \n\ + --add-section = Add section found in to output\n\ + --change-leading-char Force output format's leading character style\n\ + --remove-leading-char Remove leading character from global symbols\n\ + --redefine-sym = Redefine symbol name to \n\ + --srec-len Restrict the length of generated Srecords\n\ + --srec-forceS3 Restrict the type of generated Srecords to S3\n\ + -v --verbose List all object files modified\n\ + -V --version Display this program's version number\n\ + -h --help Display this output\n\ +")); list_supported_targets (program_name, stream); if (exit_status == 0) - fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (exit_status); } @@ -324,17 +379,30 @@ strip_usage (stream, exit_status) FILE *stream; int exit_status; { + fprintf (stream, _("Usage: %s in-file(s)\n"), program_name); + fprintf (stream, _(" The switches are:\n")); fprintf (stream, _("\ -Usage: %s [-vVsSpgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\ - [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ - [--strip-all] [--strip-debug] [--strip-unneeded] [--discard-all]\n\ - [--discard-locals] [--keep-symbol symbol] [-K symbol]\n\ - [--strip-symbol symbol] [-N symbol] [--remove-section=section]\n\ - [-o file] [--preserve-dates] [--verbose] [--version] [--help] file...\n"), - program_name); + -I --input-target Assume input file is in format \n\ + -O --output-target Create an output file in format \n\ + -F --target Set both input and output format to \n\ + -p --preserve-dates Copy modified/access timestamps to the output\n\ + -R --remove-section Remove section from the output\n\ + -s --strip-all Remove all symbol and relocation information\n\ + -g -S --strip-debug Remove all debugging symbols\n\ + --strip-unneeded Remove all symbols not needed by relocations\n\ + -N --strip-symbol Do not copy symbol \n\ + -K --keep-symbol Only copy symbol \n\ + -x --discard-all Remove all non-global symbols\n\ + -X --discard-locals Remove any compiler-generated symbols\n\ + -v --verbose List all object files modified\n\ + -V --version Display this program's version number\n\ + -h --help Display this output\n\ + -o Place stripped output into \n\ +")); + list_supported_targets (program_name, stream); if (exit_status == 0) - fprintf (stream, _("Report bugs to bug-gnu-utils@gnu.org\n")); + fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (exit_status); } @@ -367,10 +435,13 @@ parse_flags (s) else if (strncasecmp (fname, s, len) == 0) ret |= fval PARSE_FLAG ("alloc", SEC_ALLOC); PARSE_FLAG ("load", SEC_LOAD); + PARSE_FLAG ("noload", SEC_NEVER_LOAD); PARSE_FLAG ("readonly", SEC_READONLY); + PARSE_FLAG ("debug", SEC_DEBUGGING); PARSE_FLAG ("code", SEC_CODE); PARSE_FLAG ("data", SEC_DATA); PARSE_FLAG ("rom", SEC_ROM); + PARSE_FLAG ("share", SEC_SHARED); PARSE_FLAG ("contents", SEC_HAS_CONTENTS); #undef PARSE_FLAG else @@ -381,7 +452,8 @@ parse_flags (s) strncpy (copy, s, len); copy[len] = '\0'; non_fatal (_("unrecognized section flag `%s'"), copy); - fatal (_("supported flags: alloc, load, readonly, code, data, rom, contents")); + fatal (_("supported flags: %s"), + "alloc, load, noload, readonly, debug, code, data, rom, share, contents"); } s = snext; @@ -411,6 +483,7 @@ find_section_list (name, add) p->name = name; p->used = false; p->remove = false; + p->copy = false; p->change_vma = CHANGE_IGNORE; p->change_lma = CHANGE_IGNORE; p->vma_val = 0; @@ -426,7 +499,7 @@ find_section_list (name, add) /* Add a symbol to strip_specific_list. */ -static void +static void add_specific_symbol (name, list) const char *name; struct symlist **list; @@ -461,7 +534,7 @@ is_specified_symbol (name, list) static boolean is_strip_section (abfd, sec) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; asection *sec; { struct section_list *p; @@ -474,10 +547,15 @@ is_strip_section (abfd, sec) || convert_debugging)) return true; - if (! sections_removed) + if (! sections_removed && ! sections_copied) return false; + p = find_section_list (bfd_get_section_name (abfd, sec), false); - return p != NULL && p->remove ? true : false; + if (sections_removed && p != NULL && p->remove) + return true; + if (sections_copied && (p == NULL || ! p->copy)) + return true; + return false; } /* Choose which symbol entries to copy; put the result in OSYMS. @@ -493,6 +571,8 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) { register asymbol **from = isyms, **to = osyms; long src_count = 0, dst_count = 0; + int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) + == HAS_RELOC; for (; src_count < symcount; src_count++) { @@ -501,6 +581,15 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) const char *name = bfd_asymbol_name (sym); int keep; + if (redefine_sym_list) + { + const char *old_name, *new_name; + + old_name = bfd_asymbol_name (sym); + new_name = lookup_sym_redefinition (old_name); + name = bfd_asymbol_name (sym) = new_name; + } + if (change_leading_char && (bfd_get_symbol_leading_char (abfd) != bfd_get_symbol_leading_char (obfd)) @@ -538,6 +627,9 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags & BSF_KEEP) != 0)) keep = 1; + else if (relocatable /* Relocatable file. */ + && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0) + keep = 1; else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ || (flags & BSF_WEAK) != 0 || bfd_is_und_section (bfd_get_section (sym)) @@ -582,6 +674,64 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) return dst_count; } +static const char * +lookup_sym_redefinition (source) + const char *source; +{ + const char *result; + struct redefine_node *list; + + result = source; + + for (list = redefine_sym_list; list != NULL; list = list->next) + { + if (strcmp (source, list->source) == 0) + { + result = list->target; + break; + } + } + return result; +} + +/* Add a node to a symbol redefine list */ + +static void +redefine_list_append (source, target) + const char *source; + const char *target; +{ + struct redefine_node **p; + struct redefine_node *list; + struct redefine_node *new_node; + + for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next) + { + if (strcmp (source, list->source) == 0) + { + fatal (_("%s: Multiple redefinition of symbol \"%s\""), + "--redefine-sym", + source); + } + + if (strcmp (target, list->target) == 0) + { + fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"), + "--redefine-sym", + target); + } + } + + new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node)); + + new_node->source = strdup (source); + new_node->target = strdup (target); + new_node->next = NULL; + + *p = new_node; +} + + /* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long. Adjust *SIZE. */ @@ -594,7 +744,7 @@ filter_bytes (memhunk, size) for (; from < end; from += interleave) *to++ = *from; - if (*size % interleave > copy_byte) + if (*size % interleave > (bfd_size_type) copy_byte) *size = (*size / interleave) + 1; else *size /= interleave; @@ -642,13 +792,13 @@ copy_object (ibfd, obfd) non_fatal (_("Warning: Output file cannot represent architecture %s"), bfd_printable_arch_mach (bfd_get_arch (ibfd), bfd_get_mach (ibfd))); - + if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (ibfd)); if (isympp) free (isympp); - + if (osympp != isympp) free (osympp); @@ -674,7 +824,7 @@ copy_object (ibfd, obfd) else { flagword flags; - + if (! bfd_set_section_size (obfd, padd->section, padd->size)) RETURN_NONFATAL (bfd_get_filename (obfd)); @@ -686,7 +836,7 @@ copy_object (ibfd, obfd) flags = pset->flags | SEC_HAS_CONTENTS; else flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; - + if (! bfd_set_section_flags (obfd, padd->section, flags)) RETURN_NONFATAL (bfd_get_filename (obfd)); @@ -695,11 +845,11 @@ copy_object (ibfd, obfd) if (pset->change_vma != CHANGE_IGNORE) if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val)) RETURN_NONFATAL (bfd_get_filename (obfd)); - + if (pset->change_lma != CHANGE_IGNORE) { padd->section->lma = pset->lma_val; - + if (! bfd_set_section_alignment (obfd, padd->section, bfd_section_alignment (obfd, padd->section))) @@ -798,16 +948,16 @@ copy_object (ibfd, obfd) symsize = bfd_get_symtab_upper_bound (ibfd); if (symsize < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + osympp = isympp = (asymbol **) xmalloc (symsize); symcount = bfd_canonicalize_symtab (ibfd, isympp); if (symcount < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (convert_debugging) dhandle = read_debugging_info (ibfd, isympp, symcount); - - if (strip_symbols == STRIP_DEBUG + + if (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_ALL || strip_symbols == STRIP_UNNEEDED || discard_locals != LOCALS_UNDEF @@ -816,14 +966,16 @@ copy_object (ibfd, obfd) || localize_specific_list != NULL || weaken_specific_list != NULL || sections_removed + || sections_copied || convert_debugging || change_leading_char || remove_leading_char + || redefine_sym_list || weaken) { /* Mark symbols used in output relocations so that they are kept, even if they are local labels or static symbols. - + Note we iterate over the input sections examining their relocations since the relocations for the output sections haven't been set yet. mark_symbols_used_in_relocations will @@ -962,6 +1114,16 @@ copy_archive (ibfd, obfd, output_target) (char *) NULL); bfd *output_bfd = bfd_openw (output_name, output_target); bfd *last_element; + struct stat buf; + int stat_status = 0; + + if (preserve_dates) + { + stat_status = bfd_stat_arch_elt (this_element, &buf); + if (stat_status != 0) + non_fatal (_("internal stat error on %s"), + bfd_get_filename (this_element)); + } l = (struct name_list *) xmalloc (sizeof (struct name_list)); l->name = output_name; @@ -984,6 +1146,9 @@ copy_archive (ibfd, obfd, output_target) status = 1; } + if (preserve_dates && stat_status == 0) + set_times (output_name, &buf); + /* Open the newly output file and attach to our list. */ output_bfd = bfd_openr (output_name, output_target); @@ -1073,13 +1238,13 @@ copy_file (input_filename, output_filename, input_target, output_target) else { bfd_nonfatal (input_filename); - + if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } - + status = 1; } } @@ -1100,7 +1265,7 @@ setup_section (ibfd, isection, obfdarg) bfd_vma vma; bfd_vma lma; flagword flags; - char *err; + const char *err; if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 && (strip_symbols == STRIP_DEBUG @@ -1114,14 +1279,16 @@ setup_section (ibfd, isection, obfdarg) if (p != NULL) p->used = true; - if (p != NULL && p->remove) + if (sections_removed && p != NULL && p->remove) + return; + if (sections_copied && (p == NULL || ! p->copy)) return; osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection)); - + if (osection == NULL) { - err = "making"; + err = _("making"); goto loser; } @@ -1130,10 +1297,10 @@ setup_section (ibfd, isection, obfdarg) size = (size + interleave - 1) / interleave; if (! bfd_set_section_size (obfd, osection, size)) { - err = "size"; + err = _("size"); goto loser; } - + vma = bfd_section_vma (ibfd, isection); if (p != NULL && p->change_vma == CHANGE_MODIFY) vma += p->vma_val; @@ -1141,10 +1308,10 @@ setup_section (ibfd, isection, obfdarg) vma = p->vma_val; else vma += change_section_address; - + if (! bfd_set_section_vma (obfd, osection, vma)) { - err = "vma"; + err = _("vma"); goto loser; } @@ -1160,7 +1327,7 @@ setup_section (ibfd, isection, obfdarg) } else lma += change_section_address; - + osection->lma = lma; /* FIXME: This is probably not enough. If we change the LMA we @@ -1170,7 +1337,7 @@ setup_section (ibfd, isection, obfdarg) bfd_section_alignment (ibfd, isection)) == false) { - err = "alignment"; + err = _("alignment"); goto loser; } @@ -1179,7 +1346,7 @@ setup_section (ibfd, isection, obfdarg) flags = p->flags | (flags & SEC_HAS_CONTENTS); if (!bfd_set_section_flags (obfd, osection, flags)) { - err = "flags"; + err = _("flags"); goto loser; } @@ -1193,7 +1360,7 @@ setup_section (ibfd, isection, obfdarg) from the input section to the output section. */ if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) { - err = "private data"; + err = _("private data"); goto loser; } @@ -1230,7 +1397,7 @@ copy_section (ibfd, isection, obfdarg) complaints now. */ if (status != 0) return; - + if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 && (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_UNNEEDED @@ -1243,7 +1410,9 @@ copy_section (ibfd, isection, obfdarg) p = find_section_list (bfd_section_name (ibfd, isection), false); - if (p != NULL && p->remove) + if (sections_removed && p != NULL && p->remove) + return; + if (sections_copied && (p == NULL || ! p->copy)) return; osection = isection->output_section; @@ -1256,7 +1425,7 @@ copy_section (ibfd, isection, obfdarg) relsize = bfd_get_reloc_upper_bound (ibfd, isection); if (relsize < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (relsize == 0) bfd_set_reloc (obfd, osection, (arelent **) NULL, 0); else @@ -1265,7 +1434,7 @@ copy_section (ibfd, isection, obfdarg) relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp); if (relcount < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); - + if (strip_symbols == STRIP_ALL) { /* Remove relocations which are not in @@ -1273,7 +1442,7 @@ copy_section (ibfd, isection, obfdarg) arelent **temp_relpp; long temp_relcount = 0; long i; - + temp_relpp = (arelent **) xmalloc (relsize); for (i = 0; i < relcount; i++) if (is_specified_symbol @@ -1287,7 +1456,7 @@ copy_section (ibfd, isection, obfdarg) bfd_set_reloc (obfd, osection, (relcount == 0 ? (arelent **) NULL : relpp), relcount); } - + isection->_cooked_size = isection->_raw_size; isection->reloc_done = true; @@ -1299,7 +1468,7 @@ copy_section (ibfd, isection, obfdarg) size)) RETURN_NONFATAL (bfd_get_filename (ibfd)); - if (copy_byte >= 0) + if (copy_byte >= 0) filter_bytes (memhunk, &size); if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0, @@ -1331,7 +1500,7 @@ copy_section (ibfd, isection, obfdarg) static void get_sections (obfd, osection, secppparg) - bfd *obfd; + bfd *obfd ATTRIBUTE_UNUSED; asection *osection; PTR secppparg; { @@ -1438,8 +1607,8 @@ static boolean write_debugging_info (obfd, dhandle, symcountp, symppp) bfd *obfd; PTR dhandle; - long *symcountp; - asymbol ***symppp; + long *symcountp ATTRIBUTE_UNUSED; + asymbol ***symppp ATTRIBUTE_UNUSED; { if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour) return write_ieee_debugging_info (obfd, dhandle); @@ -1513,7 +1682,7 @@ strip_main (argc, argv) struct section_list *p; char *output_file = NULL; - while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpgxXVv", + while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXVv", strip_options, (int *) 0)) != EOF) { switch (c) @@ -1537,6 +1706,7 @@ strip_main (argc, argv) break; case 'S': case 'g': + case 'd': /* Historic BSD alias for -g. Used by early NetBSD. */ strip_symbols = STRIP_DEBUG; break; case OPTION_STRIP_UNNEEDED: @@ -1644,7 +1814,7 @@ copy_main (argc, argv) struct section_list *p; struct stat statbuf; - while ((c = getopt_long (argc, argv, "b:i:I:K:N:s:O:d:F:L:R:SpgxXVvW:", + while ((c = getopt_long (argc, argv, "b:i:I:j:K:N:s:O:d:F:L:R:SpgxXVvW:", copy_options, (int *) 0)) != EOF) { switch (c) @@ -1654,66 +1824,95 @@ copy_main (argc, argv) if (copy_byte < 0) fatal (_("byte number must be non-negative")); break; + case 'i': interleave = atoi (optarg); if (interleave < 1) fatal (_("interleave must be positive")); break; + case 'I': case 's': /* "source" - 'I' is preferred */ input_target = optarg; break; + case 'O': case 'd': /* "destination" - 'O' is preferred */ output_target = optarg; break; + case 'F': input_target = output_target = optarg; break; + + case 'j': + p = find_section_list (optarg, true); + if (p->remove) + fatal (_("%s both copied and removed"), optarg); + p->copy = true; + sections_copied = true; + break; + case 'R': p = find_section_list (optarg, true); + if (p->copy) + fatal (_("%s both copied and removed"), optarg); p->remove = true; sections_removed = true; break; + case 'S': strip_symbols = STRIP_ALL; break; + case 'g': strip_symbols = STRIP_DEBUG; break; + case OPTION_STRIP_UNNEEDED: strip_symbols = STRIP_UNNEEDED; break; + case 'K': add_specific_symbol (optarg, &keep_specific_list); break; + case 'N': add_specific_symbol (optarg, &strip_specific_list); break; + case 'L': add_specific_symbol (optarg, &localize_specific_list); break; + case 'W': add_specific_symbol (optarg, &weaken_specific_list); break; + case 'p': preserve_dates = true; break; + case 'x': discard_locals = LOCALS_ALL; break; + case 'X': discard_locals = LOCALS_START_L; break; + case 'v': verbose = true; break; + case 'V': show_version = true; break; + case OPTION_WEAKEN: weaken = true; break; + case OPTION_ADD_SECTION: { const char *s; @@ -1724,9 +1923,9 @@ copy_main (argc, argv) FILE *f; s = strchr (optarg, '='); - + if (s == NULL) - fatal (_("bad format for --add-section NAME=FILENAME")); + fatal (_("bad format for %s"), "--add-section"); if (stat (s + 1, & st) < 0) fatal (_("cannot stat: %s: %s"), s + 1, strerror (errno)); @@ -1745,10 +1944,10 @@ copy_main (argc, argv) pa->contents = (bfd_byte *) xmalloc (pa->size); f = fopen (pa->filename, FOPEN_RB); - + if (f == NULL) fatal (_("cannot open: %s: %s"), pa->filename, strerror (errno)); - + if (fread (pa->contents, 1, pa->size, f) == 0 || ferror (f)) fatal (_("%s: fread failed"), pa->filename); @@ -1759,9 +1958,11 @@ copy_main (argc, argv) add_sections = pa; } break; + case OPTION_CHANGE_START: change_start = parse_vma (optarg, "--change-start"); break; + case OPTION_CHANGE_SECTION_ADDRESS: case OPTION_CHANGE_SECTION_LMA: case OPTION_CHANGE_SECTION_VMA: @@ -1769,17 +1970,23 @@ copy_main (argc, argv) const char *s; int len; char *name; - char *option; + char *option = NULL; bfd_vma val; - enum change_action what; - + enum change_action what = CHANGE_IGNORE; + switch (c) { - case OPTION_CHANGE_SECTION_ADDRESS: option = "--change-section-address"; break; - case OPTION_CHANGE_SECTION_LMA: option = "--change-section-lma"; break; - case OPTION_CHANGE_SECTION_VMA: option = "--change-section-vma"; break; + case OPTION_CHANGE_SECTION_ADDRESS: + option = "--change-section-address"; + break; + case OPTION_CHANGE_SECTION_LMA: + option = "--change-section-lma"; + break; + case OPTION_CHANGE_SECTION_VMA: + option = "--change-section-vma"; + break; } - + s = strchr (optarg, '='); if (s == NULL) { @@ -1807,19 +2014,19 @@ copy_main (argc, argv) case '-': val = - val; /* Drop through. */ case '+': what = CHANGE_MODIFY; break; } - + switch (c) { case OPTION_CHANGE_SECTION_ADDRESS: p->change_vma = what; p->vma_val = val; /* Drop through. */ - + case OPTION_CHANGE_SECTION_LMA: p->change_lma = what; p->lma_val = val; break; - + case OPTION_CHANGE_SECTION_VMA: p->change_vma = what; p->vma_val = val; @@ -1827,19 +2034,24 @@ copy_main (argc, argv) } } break; + case OPTION_CHANGE_ADDRESSES: change_section_address = parse_vma (optarg, "--change-addresses"); change_start = change_section_address; break; + case OPTION_CHANGE_WARNINGS: change_warn = true; break; + case OPTION_CHANGE_LEADING_CHAR: change_leading_char = true; break; + case OPTION_DEBUGGING: convert_debugging = true; break; + case OPTION_GAP_FILL: { bfd_vma gap_fill_vma; @@ -1849,25 +2061,61 @@ copy_main (argc, argv) if ((bfd_vma) gap_fill != gap_fill_vma) { char buff[20]; - + sprintf_vma (buff, gap_fill_vma); - + non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"), buff, gap_fill); } gap_fill_set = true; } break; + case OPTION_NO_CHANGE_WARNINGS: change_warn = false; break; + case OPTION_PAD_TO: pad_to = parse_vma (optarg, "--pad-to"); pad_to_set = true; break; + case OPTION_REMOVE_LEADING_CHAR: remove_leading_char = true; break; + + case OPTION_REDEFINE_SYM: + { + /* Push this redefinition onto redefine_symbol_list. */ + + int len; + const char *s; + const char *nextarg; + char *source, *target; + + s = strchr (optarg, '='); + if (s == NULL) + { + fatal (_("bad format for %s"), "--redefine-sym"); + } + + len = s - optarg; + source = (char *) xmalloc (len + 1); + strncpy (source, optarg, len); + source[len] = '\0'; + + nextarg = s + 1; + len = strlen (nextarg); + target = (char *) xmalloc (len + 1); + strcpy (target, nextarg); + + redefine_list_append (source, target); + + free (source); + free (target); + } + break; + case OPTION_SET_SECTION_FLAGS: { const char *s; @@ -1876,7 +2124,7 @@ copy_main (argc, argv) s = strchr (optarg, '='); if (s == NULL) - fatal (_("bad format for --set-section-flags")); + fatal (_("bad format for %s"), "--set-section-flags"); len = s - optarg; name = (char *) xmalloc (len + 1); @@ -1889,14 +2137,26 @@ copy_main (argc, argv) p->flags = parse_flags (s + 1); } break; + case OPTION_SET_START: set_start = parse_vma (optarg, "--set-start"); set_start_set = true; break; + + case OPTION_SREC_LEN: + Chunk = parse_vma (optarg, "--srec-len"); + break; + + case OPTION_SREC_FORCES3: + S3Forced = true; + break; + case 0: break; /* we've been given a long option */ + case 'h': copy_usage (stdout, 0); + default: copy_usage (stderr, 1); } @@ -1937,7 +2197,7 @@ copy_main (argc, argv) copy_file (input_filename, tmpname, input_target, output_target); if (status == 0) - { + { if (preserve_dates) set_times (tmpname, &statbuf); smart_rename (tmpname, input_filename, preserve_dates); @@ -1963,22 +2223,24 @@ copy_main (argc, argv) char buff [20]; sprintf_vma (buff, p->vma_val); - + /* xgettext:c-format */ - non_fatal (_("Warning: --change-section-vma %s%c0x%s never used"), + non_fatal (_("%s %s%c0x%s never used"), + "--change-section-vma", p->name, p->change_vma == CHANGE_SET ? '=' : '+', buff); } - + if (p->change_lma != CHANGE_IGNORE) { char buff [20]; sprintf_vma (buff, p->lma_val); - + /* xgettext:c-format */ - non_fatal (_("Warning: --change-section-lma %s%c0x%s never used"), + non_fatal (_("%s %s%c0x%s never used"), + "--change-section-lma", p->name, p->change_lma == CHANGE_SET ? '=' : '+', buff); @@ -2015,7 +2277,15 @@ main (argc, argv) if (is_strip < 0) { int i = strlen (program_name); - is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip") == 0); +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + /* Drop the .exe suffix, if any. */ + if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0) + { + i -= 4; + program_name[i] = '\0'; + } +#endif + is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0); } if (is_strip)