diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 43366b3ed2..6e17da1d77 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,24 @@ +Tue Oct 18 11:12:01 1994 Ian Lance Taylor + + * objcopy.c (struct section_list): Add fields used, adjust, val. + (adjust_start, set_start_set, set_start): New static variables. + (adjust_section_vma, adjust_sections): New static variables. + (copy_options): Add --adjust-start, --adjust-vma, + --adjust-section-vma, --adjust-warnings, --no-adjust-warnings, + --set-start. + (parse_vma): New static function. + (copy_usage): Mention new options. + (copy_object): Handle --set-start and --adjust-start. + (setup_section): Correct type of last argument to PTR. Set used + field if section is removed. Handle --adjust-vma and + --adjust-section-vma. + (copy_section): Correct type of last argument to PTR. + (mark_symbols_used_in_relocations): Likewise. + (strip_main): Clear used field when handling -R. + (copy_main): Handle new options. + * binutils.texi (objcopy): Document new options. + * objcopy.1: Document new options. + Fri Oct 14 14:38:13 1994 Ian Lance Taylor * configure.in (configdirs): Remove definition--testsuite is no @@ -7,6 +28,11 @@ Fri Oct 14 14:38:13 1994 Ian Lance Taylor (check): Rewrite. (clean, distclean): Don't recur into testsuite directory. +Thu Oct 13 19:24:09 1994 Ken Raeburn + + * Makefile.in (VERSION): Updated to 2.5. + * Version 2.5 released. + Tue Oct 11 15:26:42 1994 Ian Lance Taylor * Makefile.in (sysdump.o): Depends upon sysroff.c. diff --git a/binutils/binutils.texi b/binutils/binutils.texi index 4acc69d6b8..daa177768b 100644 --- a/binutils/binutils.texi +++ b/binutils/binutils.texi @@ -747,6 +747,10 @@ objcopy [ -F @var{bfdname} | --target=@var{bfdname} ] [ -b @var{byte} | --byte=@var{byte} ] [ -i @var{interleave} | --interleave=@var{interleave} ] [ -R @var{sectionname} | --remove-section=@var{sectionname} ] + [ --set-start=@var{val} ] [ --adjust-start=@var{incr} ] + [ --adjust-vma=@var{incr} ] + [ --adjust-section-vma=@var{section}@{=,+,-@}@var{val} ] + [ --adjust-warnings ] [ --no-adjust-warnings ] [ -v | --verbose ] [ -V | --version ] [ --help ] @var{infile} [@var{outfile}] @end smallexample @@ -827,6 +831,38 @@ copy with the @var{-b} or @samp{--byte} option. The default is 4. @code{objcopy} ignores this option if you do not specify either @samp{-b} or @samp{--byte}. +@item --set-start @var{val} +Set the address of the new file to @var{val}. Not all object file +formats support setting the start address. + +@item --adjust-start @var{incr} +Adjust the start address by adding @var{incr}. Not all object file +formats support setting the start address. + +@item --adjust-vma @var{incr} +Adjust the address of all sections, as well as the start address, by +adding @var{incr}. Some object file formats do not permit section +addresses to be changed arbitrarily. Note that this does not relocate +the sections; if the program expects sections to be loaded at a certain +address, and this option is used to change the sections such that they +are loaded at a different address, the program may fail. + +@item --adjust-section-vma @var{section}@{=,+,-@}@var{val} +Set or adjust the address of the named @var{section}. If @samp{=} is +used, the section address is set to @var{val}. Otherwise, @var{val} is +added to or subtracted from the section address. See the comments under +@samp{--adjust-vma}, above. If @var{section} does not exist in the +input file, a warning will be issued, unless @samp{--no-adjust-warnings} +is used. + +@item --adjust-warnings +If @samp{--adjust-section-vma} is used, and the named section does not +exist, issue a warning. This is the default. + +@item --no-adjust-warnings +Do not issue a warning if @samp{--adjust-section-vma} is used, even if +the named section does not exist. + @item -V @itemx --version Show the version number of @code{objcopy}. diff --git a/binutils/objcopy.1 b/binutils/objcopy.1 index 78877e6360..365c11a6cf 100644 --- a/binutils/objcopy.1 +++ b/binutils/objcopy.1 @@ -1,6 +1,6 @@ .\" Copyright (c) 1991 Free Software Foundation .\" See section COPYING for conditions for redistribution -.TH objcopy 1 "June 1993" "cygnus support" "GNU Development Tools" +.TH objcopy 1 "October 1994" "cygnus support" "GNU Development Tools" .de BP .sp .ti \-.2i @@ -23,8 +23,14 @@ objcopy \- copy and translate object files .RB "[\|" \-g\ |\ \-\-strip\-debug\fR "\|]" .RB "[\|" \-x\ |\ \-\-discard\-all\fR "\|]" .RB "[\|" \-X\ |\ \-\-discard\-locals\fR "\|]" -.RB "[\|" \-b\ \fIbyte\fP |\ \-\-byte=\fIbyte\fP "\|]" -.RB "[\|" \-i\ \fIinterleave\fP |\ \-\-interleave=\fIinterleave\fP "\|]" +.RB "[\|" \-b\ \fIbyte\fP |\ \-\-byte=\fIbyte\fP "\|]" +.RB "[\|" \-i\ \fIinterleave\fP |\ \-\-interleave=\fIinterleave\fP "\|]" +.RB "[\|" \-\-set\-start=\fIval\fP "\|]" +.RB "[\|" \-\-adjust\-start=\fIincr\fP "\|]" +.RB "[\|" \-\-adjust\-vma=\fIincr\fP "\|]" +.RB "[\|" \-\-adjust\-section\-vma=\fIsection{=,+,-}val\fP "\|]" +.RB "[\|" \-\-adjust\-warnings "\|]" +.RB "[\|" \-\-no\-adjust\-warnings "\|]" .RB "[\|" \-v\ |\ \-\-verbose\fR "\|]" .RB "[\|" \-V\ |\ \-\-version\fR "\|]" .RB "[\|" \-\-help\fR "\|]" @@ -104,6 +110,38 @@ Only copy one out of every \fIinterleave\fP bytes. Which one to copy is selected by the \fB\-b\fP or \fB\-\-byte\fP option. The default is 4. The interleave is ignored if neither \fB\-b\fP nor \fB\-\-byte\fP is given. .TP +.B \fB\-\-set\-start=\fIval +Set the start address of the new file to \fIval\fP. Not all object +file formats support setting the start address. +.TP +.B \fB\-\-adjust\-start=\fIincr +Adjust the start address by adding \fIincr\fP. Not all object file +formats support setting the start address. +.TP +.B \fB\-\-adjust\-vma=\fIincr +Adjust the address of all sections, as well as the start address, by +adding \fIincr\fP. Some object file formats do not permit section +addresses to be changed arbitrarily. Note that this does not relocate +the sections; if the program expects sections to be loaded at a +certain address, and this option is used to change the sections such +that they are loaded at a different address, the program may fail. +.TP +.B \fB\-\-adjust\-section\-vma=\fIsection{=,+,-}val +Set or adjust the address of the named \fIsection\fP. If \fI=\fP is +used, the section address is set to \fIval\fP. Otherwise, \fIval\fP +is added to or subtracted from the section address. See the comments +under \fB\-\-adjust\-vma\fP, above. If \fIsection\fP does not exist +in the input file, a warning will be issued, unless +\fB\-\-no\-adjust\-warnings\fP is used. +.TP +.B \fB\-\-adjust\-warnings +If \fB\-\-adjust\-section\-vma\fP is used, and the named section does +not exist, issue a warning. This is the default. +.TP +.B \fB\-\-no\-adjust\-warnings +Do not issue a warning if \fB\-\-adjust\-section\-vma\fP is used, even +if the named section does not exist. +.TP .B \-v\fR, \fB\-\-verbose Verbose output: list all object files modified. In the case of archives, "\fBobjcopy \-V\fR" lists all members of the archive. @@ -128,7 +166,7 @@ The GNU Binary Utilities\c \&, Roland H. Pesch (June 1993). .SH COPYING -Copyright (c) 1993 Free Software Foundation, Inc. +Copyright (c) 1993,1994 Free Software Foundation, Inc. .PP Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 673511fc17..70d118e03c 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -21,10 +21,12 @@ #include "sysdep.h" #include "bucomm.h" #include +#include "libiberty.h" -static void setup_section (); -static void copy_section (); -static void mark_symbols_used_in_relocations (); +static bfd_vma parse_vma PARAMS ((const char *, const char *)); +static void setup_section PARAMS ((bfd *, asection *, PTR)); +static void copy_section PARAMS ((bfd *, asection *, PTR)); +static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR)); #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;} @@ -59,6 +61,36 @@ enum locals_action /* Which local symbols to remove. Overrides strip_all. */ static enum locals_action discard_locals; +/* Structure used to hold lists of sections and actions to take. */ + +struct section_list +{ + /* Next section to adjust. */ + struct section_list *next; + /* Section name. */ + const char *name; + /* Whether this entry was used. */ + boolean used; + /* Remaining fields only used if not on remove_sections list. */ + /* Whether to adjust or set VMA. */ + boolean adjust; + /* Amount to adjust by or set to. */ + bfd_vma val; +}; + +/* List of sections to remove. */ + +static struct section_list *remove_sections; + +/* Adjustments to the start address. */ +static bfd_vma adjust_start = 0; +static boolean set_start_set = false; +static bfd_vma set_start; + +/* Adjustments to section VMA's. */ +static bfd_vma adjust_section_vma = 0; +static struct section_list *adjust_sections; + /* Options to handle if running as "strip". */ static struct option strip_options[] = @@ -71,6 +103,7 @@ static struct option strip_options[] = {"input-target", required_argument, 0, 'I'}, {"output-format", required_argument, 0, 'O'}, /* Obsolete */ {"output-target", required_argument, 0, 'O'}, + {"remove-section", required_argument, 0, 'R'}, {"strip-all", no_argument, 0, 's'}, {"strip-debug", no_argument, 0, 'S'}, {"target", required_argument, 0, 'F'}, @@ -81,8 +114,21 @@ static struct option strip_options[] = /* Options to handle if running as "objcopy". */ +/* 150 isn't special; it's just an arbitrary non-ASCII char value. */ + +#define OPTION_ADJUST_START 150 +#define OPTION_ADJUST_VMA (OPTION_ADJUST_START + 1) +#define OPTION_ADJUST_SECTION_VMA (OPTION_ADJUST_VMA + 1) +#define OPTION_ADJUST_WARNINGS (OPTION_ADJUST_SECTION_VMA + 1) +#define OPTION_NO_ADJUST_WARNINGS (OPTION_ADJUST_WARNINGS + 1) +#define OPTION_SET_START (OPTION_NO_ADJUST_WARNINGS + 1) + static struct option copy_options[] = { + {"adjust-start", required_argument, 0, OPTION_ADJUST_START}, + {"adjust-vma", required_argument, 0, OPTION_ADJUST_VMA}, + {"adjust-section-vma", required_argument, 0, OPTION_ADJUST_SECTION_VMA}, + {"adjust-warnings", no_argument, 0, OPTION_ADJUST_WARNINGS}, {"byte", required_argument, 0, 'b'}, {"discard-all", no_argument, 0, 'x'}, {"discard-locals", no_argument, 0, 'X'}, @@ -91,8 +137,11 @@ static struct option copy_options[] = {"input-format", required_argument, 0, 'I'}, /* Obsolete */ {"input-target", required_argument, 0, 'I'}, {"interleave", required_argument, 0, 'i'}, + {"no-adjust-warnings", no_argument, 0, OPTION_NO_ADJUST_WARNINGS}, {"output-format", required_argument, 0, 'O'}, /* Obsolete */ {"output-target", required_argument, 0, 'O'}, + {"remove-section", required_argument, 0, 'R'}, + {"set-start", required_argument, 0, OPTION_SET_START}, {"strip-all", no_argument, 0, 'S'}, {"strip-debug", no_argument, 0, 'g'}, {"target", required_argument, 0, 'F'}, @@ -118,10 +167,13 @@ copy_usage (stream, status) { fprintf (stream, "\ Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\ - [-i interleave] [--interleave=interleave] [--byte=byte]\n\ + [-R section] [-i interleave] [--interleave=interleave] [--byte=byte]\n\ [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\ - [--verbose] [--version] [--help] in-file [out-file]\n", + [--remove-section=section] [--set-start=val] [--adjust-start=incr]\n\ + [--adjust-vma=incr] [--adjust-section-vma=section{=,+,-}val]\n\ + [--adjust-warnings] [--no-adjust-warnings] [--verbose] [--version]\n\ + [--help] in-file [out-file]\n", program_name); exit (status); } @@ -132,14 +184,33 @@ strip_usage (stream, status) int status; { fprintf (stream, "\ -Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\ +Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-R section]\n\ [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\ [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\ - [--verbose] [--version] [--help] file...\n", + [--remove-section=section] [--verbose] [--version] [--help] file...\n", program_name); exit (status); } +/* Parse a string into a VMA, with a fatal error if it can't be + parsed. */ + +static bfd_vma +parse_vma (s, arg) + const char *s; + const char *arg; +{ + bfd_vma ret; + const char *end; + + ret = bfd_scan_vma (s, &end, 0); + if (*end != '\0') + { + fprintf (stderr, "%s: %s: bad number: %s\n", program_name, arg, s); + exit (1); + } + return ret; +} /* Return the name of a temporary file in the same directory as FILENAME. */ @@ -191,7 +262,7 @@ filter_symbols (abfd, osyms, isyms, symcount) if ((flags & BSF_GLOBAL) /* Keep if external. */ || (flags & BSF_KEEP) /* Keep if used in a relocation. */ - || bfd_get_section (sym) == &bfd_und_section + || bfd_is_und_section (bfd_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))) keep = 1; else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */ @@ -229,6 +300,7 @@ copy_object (ibfd, obfd) bfd *ibfd; bfd *obfd; { + bfd_vma start; long symcount; if (!bfd_set_format (obfd, bfd_get_format (ibfd))) @@ -241,7 +313,13 @@ copy_object (ibfd, obfd) bfd_get_filename(ibfd), bfd_get_target(ibfd), bfd_get_filename(obfd), bfd_get_target(obfd)); - if (!bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) + if (set_start_set) + start = set_start; + else + start = bfd_get_start_address (ibfd); + start += adjust_start; + + if (!bfd_set_start_address (obfd, start) || !bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) & bfd_applicable_file_flags (obfd)))) @@ -307,7 +385,7 @@ copy_object (ibfd, obfd) section. */ bfd_map_over_sections (ibfd, mark_symbols_used_in_relocations, - (void *)isympp); + (PTR)isympp); osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); symcount = filter_symbols (ibfd, osympp, isympp, symcount); } @@ -442,7 +520,14 @@ copy_file (input_filename, output_filename, input_target, output_target) if (bfd_check_format (ibfd, bfd_archive)) { - bfd *obfd = bfd_openw (output_filename, output_target); + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); if (obfd == NULL) { nonfatal (output_filename); @@ -451,7 +536,14 @@ copy_file (input_filename, output_filename, input_target, output_target) } else if (bfd_check_format_matches (ibfd, bfd_object, &matching)) { - bfd *obfd = bfd_openw (output_filename, output_target); + bfd *obfd; + + /* bfd_get_target does not return the correct value until + bfd_check_format succeeds. */ + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + + obfd = bfd_openw (output_filename, output_target); if (obfd == NULL) { nonfatal (output_filename); @@ -485,12 +577,15 @@ copy_file (input_filename, output_filename, input_target, output_target) as ISECTION in IBFD. */ static void -setup_section (ibfd, isection, obfd) +setup_section (ibfd, isection, obfdarg) bfd *ibfd; sec_ptr isection; - bfd *obfd; + PTR obfdarg; { + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; sec_ptr osection; + bfd_vma vma; char *err; if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0 @@ -499,6 +594,15 @@ setup_section (ibfd, isection, obfd) || discard_locals == locals_all)) return; + for (p = remove_sections; p != NULL; p = p->next) + { + if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0) + { + p->used = true; + return; + } + } + osection = bfd_make_section_anyway (obfd, bfd_section_name (ibfd, isection)); if (osection == NULL) { @@ -514,10 +618,23 @@ setup_section (ibfd, isection, obfd) goto loser; } - if (bfd_set_section_vma (obfd, - osection, - bfd_section_vma (ibfd, isection)) - == false) + vma = bfd_section_vma (ibfd, isection); + for (p = adjust_sections; p != NULL; p = p->next) + { + if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0) + { + if (p->adjust) + vma += p->val; + else + vma = p->val; + p->used = true; + break; + } + } + if (p == NULL) + vma += adjust_section_vma; + + if (! bfd_set_section_vma (obfd, osection, vma)) { err = "vma"; goto loser; @@ -569,11 +686,13 @@ loser: If stripping then don't copy any relocation info. */ static void -copy_section (ibfd, isection, obfd) +copy_section (ibfd, isection, obfdarg) bfd *ibfd; sec_ptr isection; - bfd *obfd; + PTR obfdarg; { + bfd *obfd = (bfd *) obfdarg; + struct section_list *p; arelent **relpp; long relcount; sec_ptr osection; @@ -587,6 +706,10 @@ copy_section (ibfd, isection, obfd) return; } + for (p = remove_sections; p != NULL; p = p->next) + if (strcmp (p->name, bfd_section_name (ibfd, isection)) == 0) + return; + osection = isection->output_section; size = bfd_get_section_size_before_reloc (isection); @@ -654,11 +777,12 @@ copy_section (ibfd, isection, obfd) Ignore relocations which will not appear in the output file. */ static void -mark_symbols_used_in_relocations (ibfd, isection, symbols) +mark_symbols_used_in_relocations (ibfd, isection, symbolsarg) bfd *ibfd; sec_ptr isection; - asymbol **symbols; + PTR symbolsarg; { + asymbol **symbols = (asymbol **) symbolsarg; long relsize; arelent **relpp; long relcount, i; @@ -680,9 +804,9 @@ mark_symbols_used_in_relocations (ibfd, isection, symbols) special bfd section symbols, then mark it with BSF_KEEP. */ for (i = 0; i < relcount; i++) { - if (*relpp[i]->sym_ptr_ptr != bfd_com_section.symbol - && *relpp[i]->sym_ptr_ptr != bfd_abs_section.symbol - && *relpp[i]->sym_ptr_ptr != bfd_und_section.symbol) + if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol + && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol) (*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP; } @@ -781,7 +905,7 @@ strip_main (argc, argv) boolean show_version = false; int c, i; - while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv", + while ((c = getopt_long (argc, argv, "I:O:F:R:sSgxXVv", strip_options, (int *) 0)) != EOF) { switch (c) @@ -795,6 +919,17 @@ strip_main (argc, argv) case 'F': input_target = output_target = optarg; break; + case 'R': + { + struct section_list *n; + + n = (struct section_list *) xmalloc (sizeof (struct section_list)); + n->name = optarg; + n->used = false; + n->next = remove_sections; + remove_sections = n; + } + break; case 's': strip_symbols = strip_all; break; @@ -865,12 +1000,14 @@ copy_main (argc, argv) int argc; char *argv[]; { - char *input_filename, *output_filename; + char *input_filename = NULL, *output_filename = NULL; char *input_target = NULL, *output_target = NULL; boolean show_version = false; + boolean adjust_warn = true; int c; + struct section_list *p; - while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv", + while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:R:SgxXVv", copy_options, (int *) 0)) != EOF) { switch (c) @@ -904,6 +1041,13 @@ copy_main (argc, argv) case 'F': input_target = output_target = optarg; break; + case 'R': + p = (struct section_list *) xmalloc (sizeof (struct section_list)); + p->name = optarg; + p->used = false; + p->next = remove_sections; + remove_sections = p; + break; case 'S': strip_symbols = strip_all; break; @@ -922,6 +1066,68 @@ copy_main (argc, argv) case 'V': show_version = true; break; + case OPTION_ADJUST_START: + adjust_start = parse_vma (optarg, "--adjust-start"); + break; + case OPTION_ADJUST_SECTION_VMA: + { + const char *s; + int len; + char *name; + + p = (struct section_list *) xmalloc (sizeof (struct section_list)); + s = strchr (optarg, '='); + if (s != NULL) + { + p->adjust = false; + p->val = parse_vma (s + 1, "--adjust-section-vma"); + } + else + { + s = strchr (optarg, '+'); + if (s == NULL) + { + s = strchr (optarg, '-'); + if (s == NULL) + { + fprintf (stderr, + "%s: bad format for --adjust-section-vma\n", + program_name); + exit (1); + } + } + p->adjust = true; + p->val = parse_vma (s + 1, "--adjust-section-vma"); + if (*s == '-') + p->val = - p->val; + } + + len = s - optarg; + name = (char *) xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + p->name = name; + + p->used = false; + + p->next = adjust_sections; + adjust_sections = p; + } + break; + case OPTION_ADJUST_VMA: + adjust_section_vma = parse_vma (optarg, "--adjust-vma"); + adjust_start = adjust_section_vma; + break; + case OPTION_ADJUST_WARNINGS: + adjust_warn = true; + break; + case OPTION_NO_ADJUST_WARNINGS: + adjust_warn = false; + break; + case OPTION_SET_START: + set_start = parse_vma (optarg, "--set-start"); + set_start_set = true; + break; case 0: break; /* we've been given a long option */ case 'h': @@ -975,6 +1181,24 @@ copy_main (argc, argv) copy_file (input_filename, output_filename, input_target, output_target); } + if (adjust_warn) + { + for (p = adjust_sections; p != NULL; p = p->next) + { + if (! p->used) + { + fprintf (stderr, "%s: warning: --adjust-section-vma %s%c0x", + program_name, p->name, + p->adjust ? '=' : '+'); + fprintf_vma (stderr, p->val); + fprintf (stderr, " never used\n"); + } + } + } + + /* We could issue similar warnings for remove_sections, but I don't + think that would be as useful. */ + return 0; }