diff options
-rw-r--r-- | binutils/ChangeLog | 10 | ||||
-rw-r--r-- | binutils/binutils.texi | 9 | ||||
-rw-r--r-- | binutils/objcopy.1 | 6 | ||||
-rw-r--r-- | binutils/objcopy.c | 166 |
4 files changed, 184 insertions, 7 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 774dbb8..fcb01fa 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -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 diff --git a/binutils/binutils.texi b/binutils/binutils.texi index 3c078f8..6776520 100644 --- a/binutils/binutils.texi +++ b/binutils/binutils.texi @@ -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. diff --git a/binutils/objcopy.1 b/binutils/objcopy.1 index e2876d1..652a9d8 100644 --- a/binutils/objcopy.1 +++ b/binutils/objcopy.1 @@ -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. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 70d118e..3308b51 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -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; |