* 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 43366b3ed2a3e3824bb62b1abeb483a28b71ecef..6e17da1d772cdc3c882f7eec2e079db7eaaa9f9f 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 4acc69d6b806abb9c421191c5c6487651f447cec..daa177768b03bba8bd64e52a14787f7426f247af 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 78877e63603a6fd3d8cba457a4525c5872826893..365c11a6cf8a61cae334f7b522939f5b6ebb3d54 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 673511fc17158d113c67ad3c62be8a7df77e6ea0..70d118e03c919fe784d39168b6dc30b847231cf0 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;
 }