* objcopy.c (struct section_list): Add fields used, adjust, val.
authorIan Lance Taylor <ian@airs.com>
Tue, 18 Oct 1994 15:49:53 +0000 (15:49 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 18 Oct 1994 15:49:53 +0000 (15:49 +0000)
(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.

binutils/ChangeLog
binutils/binutils.texi
binutils/objcopy.1
binutils/objcopy.c

index 43366b3..6e17da1 100644 (file)
@@ -1,3 +1,24 @@
+Tue Oct 18 11:12:01 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * 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  <ian@sanguine.cygnus.com>
 
        * configure.in (configdirs): Remove definition--testsuite is no
@@ -7,6 +28,11 @@ Fri Oct 14 14:38:13 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
        (check): Rewrite.
        (clean, distclean): Don't recur into testsuite directory.
 
+Thu Oct 13 19:24:09 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
+
+       * Makefile.in (VERSION): Updated to 2.5.
+       * Version 2.5 released.
+
 Tue Oct 11 15:26:42 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
 
        * Makefile.in (sysdump.o): Depends upon sysroff.c.
index 4acc69d..daa1777 100644 (file)
@@ -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}.
index 78877e6..365c11a 100644 (file)
@@ -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
index 673511f..70d118e 100644 (file)
 #include "sysdep.h"
 #include "bucomm.h"
 #include <getopt.h>
+#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;
 }