* objcopy.c (gap_fill_set, gap_fill): New static variables.
authorIan Lance Taylor <ian@airs.com>
Thu, 20 Oct 1994 17:58:23 +0000 (17:58 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 20 Oct 1994 17:58:23 +0000 (17:58 +0000)
(copy_options): Accept --gap-fill.
(copy_usage): Mention --gap-fill.
(copy_object): Support --gap-fill.
(get_sections, compare_section_vma): New static functions.
(copy_main): Handle --gap-fill.
* binutils.texi, objcopy.1: Document --gap-fill.

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

index 774dbb8..fcb01fa 100644 (file)
@@ -1,3 +1,13 @@
+Thu Oct 20 13:51:31 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * objcopy.c (gap_fill_set, gap_fill): New static variables.
+       (copy_options): Accept --gap-fill.
+       (copy_usage): Mention --gap-fill.
+       (copy_object): Support --gap-fill.
+       (get_sections, compare_section_vma): New static functions.
+       (copy_main): Handle --gap-fill.
+       * binutils.texi, objcopy.1: Document --gap-fill.
+
 Wed Oct 19 14:09:16 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
 
        * Makefile.in (check): Add a dummy else clause to the if
index 3c078f8..6776520 100644 (file)
@@ -747,8 +747,8 @@ 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} ]
+        [ --gap-fill=@var{val} ] [ --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 ]
@@ -846,6 +846,11 @@ 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 --gap-fill @var{val}
+Fill gaps between sections with @var{val}.  This is done by increasing
+the size of the section with the lower address, and filling in the extra
+space created with @var{val}.
+
 @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.
index e2876d1..652a9d8 100644 (file)
@@ -25,6 +25,7 @@ objcopy \- copy and translate object files
 .RB "[\|" \-X\ |\ \-\-discard\-locals\fR "\|]" 
 .RB "[\|" \-b\ \fIbyte\fP |\ \-\-byte=\fIbyte\fP "\|]" 
 .RB "[\|" \-i\ \fIinterleave\fP |\ \-\-interleave=\fIinterleave\fP "\|]" 
+.RB "[\|" \-\-gap\-fill=\fIval\fP "\|]"
 .RB "[\|" \-\-set\-start=\fIval\fP "\|]"
 .RB "[\|" \-\-adjust\-start=\fIincr\fP "\|]"
 .RB "[\|" \-\-adjust\-vma=\fIincr\fP "\|]"
@@ -136,6 +137,11 @@ 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 \-\-gap\-fill=\fIval
+Fill gaps between sections with \fIval\fP.  This is done by increasing
+the size of the section with the lower address, and filling in the extra
+space created with \fIval\fP.
+.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.
index 70d118e..3308b51 100644 (file)
@@ -26,6 +26,8 @@
 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 get_sections PARAMS ((bfd *, asection *, PTR));
+static int compare_section_vma PARAMS ((const PTR, const PTR));
 static void mark_symbols_used_in_relocations PARAMS ((bfd *, asection *, PTR));
 
 #define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
@@ -91,6 +93,10 @@ static bfd_vma set_start;
 static bfd_vma adjust_section_vma = 0;
 static struct section_list *adjust_sections;
 
+/* Filling gaps between sections.  */
+static boolean gap_fill_set = false;
+static bfd_byte gap_fill;
+
 /* Options to handle if running as "strip".  */
 
 static struct option strip_options[] =
@@ -120,7 +126,8 @@ static struct option strip_options[] =
 #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_GAP_FILL (OPTION_ADJUST_WARNINGS + 1)
+#define OPTION_NO_ADJUST_WARNINGS (OPTION_GAP_FILL + 1)
 #define OPTION_SET_START (OPTION_NO_ADJUST_WARNINGS + 1)
 
 static struct option copy_options[] =
@@ -133,6 +140,7 @@ static struct option copy_options[] =
   {"discard-all", no_argument, 0, 'x'},
   {"discard-locals", no_argument, 0, 'X'},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
+  {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
   {"help", no_argument, 0, 'h'},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
   {"input-target", required_argument, 0, 'I'},
@@ -170,10 +178,11 @@ Usage: %s [-vVSgxX] [-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] [--discard-all] [--discard-locals]\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",
+       [--remove-section=section] [--gap-fill=val] [--set-start=val]\n\
+       [--adjust-start=incr] [--adjust-vma=incr]\n\
+       [--adjust-section-vma=section{=,+,-}val] [--adjust-warnings]\n\
+       [--no-adjust-warnings] [--verbose] [--version] [--help]\n\
+       in-file [out-file]\n",
           program_name);
   exit (status);
 }
@@ -302,6 +311,9 @@ copy_object (ibfd, obfd)
 {
   bfd_vma start;
   long symcount;
+  asection **osections = NULL;
+  bfd_size_type *gaps = NULL;
+  bfd_size_type max_gap = 0;
 
   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
     {
@@ -349,6 +361,58 @@ copy_object (ibfd, obfd)
      any output is done.  Thus, we traverse all sections multiple times.  */
   bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
 
+  if (gap_fill_set)
+    {
+      asection **set;
+      unsigned int c, i;
+
+      /* We must fill in gaps between the sections.  We do this by
+        grabbing a list of the sections, sorting them by VMA, and
+        adding new sections to occupy any gaps.  */
+
+      c = bfd_count_sections (obfd);
+      osections = (asection **) xmalloc (c * sizeof (asection *));
+      set = osections;
+      bfd_map_over_sections (obfd, get_sections, (void *) &set);
+
+      qsort (osections, c, sizeof (asection *), compare_section_vma);
+
+      gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
+      for (i = 0; i < c - 1; i++)
+       {
+         flagword flags;
+         bfd_size_type size;
+         bfd_vma gap_start, gap_stop;
+
+         flags = bfd_get_section_flags (obfd, osections[i]);
+         if ((flags & SEC_HAS_CONTENTS) == 0
+             || (flags & SEC_LOAD) == 0)
+           continue;
+
+         size = bfd_section_size (obfd, osections[i]);
+         gap_start = bfd_section_vma (obfd, osections[i]) + size;
+         gap_stop = bfd_section_vma (obfd, osections[i + 1]);
+         if (gap_start >= gap_stop)
+           gaps[i] = 0;
+         else
+           {
+             if (! bfd_set_section_size (obfd, osections[i],
+                                         size + (gap_stop - gap_start)))
+               {
+                 fprintf (stderr, "%s: Can't fill gap after %s: %s\n",
+                          program_name,
+                          bfd_get_section_name (obfd, osections[i]),
+                          bfd_errmsg (bfd_get_error()));
+                 status = 1;
+                 break;
+               }
+             gaps[i] = gap_stop - gap_start;
+             if (max_gap < gap_stop - gap_start)
+               max_gap = gap_stop - gap_start;
+           }
+       }
+    }
+
   /* Symbol filtering must happen after the output sections have
      been created, but before their contents are set.  */
   if (strip_symbols == strip_all && discard_locals == locals_undef)
@@ -396,6 +460,49 @@ copy_object (ibfd, obfd)
   /* This has to happen after the symbol table has been set.  */
   bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
 
+  if (gap_fill_set)
+    {
+      bfd_byte *buf;
+      int c, i;
+
+      /* Fill in the gaps.  */
+
+      if (max_gap > 8192)
+       max_gap = 8192;
+      buf = (bfd_byte *) xmalloc (max_gap);
+      memset (buf, gap_fill, max_gap);
+
+      c = bfd_count_sections (obfd);
+      for (i = 0; i < c - 1; i++)
+       {
+         if (gaps[i] != 0)
+           {
+             bfd_size_type left;
+             file_ptr off;
+
+             left = gaps[i];
+             off = bfd_section_size (obfd, osections[i]) - left;
+             while (left > 0)
+               {
+                 bfd_size_type now;
+
+                 if (left > 8192)
+                   now = 8192;
+                 else
+                   now = left;
+                 if (! bfd_set_section_contents (obfd, osections[i], buf,
+                                                 off, now))
+                   {
+                     nonfatal (bfd_get_filename (obfd));
+                     status = 1;
+                   }
+                 left -= now;
+                 off += now;
+               }
+           }
+       }
+    }
+
   /* Allow the BFD backend to copy any private data it understands
      from the input BFD to the output BFD.  This is done last to
      permit the routine to look at the filtered symbol table, which is
@@ -771,6 +878,39 @@ copy_section (ibfd, isection, obfdarg)
     }
 }
 
+/* Get all the sections.  This is used when --gap-fill is used.  */
+
+static void
+get_sections (obfd, osection, secppparg)
+     bfd *obfd;
+     asection *osection;
+     PTR secppparg;
+{
+  asection ***secppp = (asection ***) secppparg;
+
+  **secppp = osection;
+  ++(*secppp);
+}
+
+/* Sort sections by VMA.  This is called via qsort, and is used when
+   --gap-fill is used.  */
+
+static int
+compare_section_vma (arg1, arg2)
+     const PTR arg1;
+     const PTR arg2;
+{
+  const asection **sec1 = (const asection **) arg1;
+  const asection **sec2 = (const asection **) arg2;
+
+  if ((*sec1)->vma > (*sec2)->vma)
+    return 1;
+  else if ((*sec1)->vma < (*sec2)->vma)
+    return -1;
+  else
+    return 0;
+}
+
 /* Mark all the symbols which will be used in output relocations with
    the BSF_KEEP flag so that those symbols will not be stripped.
 
@@ -1121,6 +1261,22 @@ copy_main (argc, argv)
        case OPTION_ADJUST_WARNINGS:
          adjust_warn = true;
          break;
+       case OPTION_GAP_FILL:
+         {
+           bfd_vma gap_fill_vma;
+
+           gap_fill_vma = parse_vma (optarg, "--gap-fill");
+           gap_fill = (bfd_byte) gap_fill_vma;
+           if ((bfd_vma) gap_fill != gap_fill_vma)
+             {
+               fprintf (stderr, "%s: warning: truncating gap-fill from 0x",
+                        program_name);
+               fprintf_vma (stderr, gap_fill_vma);
+               fprintf (stderr, "to 0x%x\n", (unsigned int) gap_fill);
+             }
+           gap_fill_set = true;
+         }
+         break;
        case OPTION_NO_ADJUST_WARNINGS:
          adjust_warn = false;
          break;