diff options
-rw-r--r-- | binutils/ChangeLog | 10 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 26 | ||||
-rw-r--r-- | binutils/objcopy.c | 50 | ||||
-rw-r--r-- | binutils/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/objcopy.exp | 34 |
5 files changed, 125 insertions, 1 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index d18d20d..bd622fb 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2007-04-20 Nathan Froyd <froydnj@codesourcery.com> + Phil Edwards <phil@codesourcery.com> + Thomas de Lellis <tdel@windriver.com> + + * objcopy.c (reverse_bytes): New variable. + (command_line_switch, copy_main): Add OPTION_REVERSE_ENDIAN. + (copy_options, copy_usage): Add "reverse-bytes" entry. + (copy_section): Reverse bytes within output sections. + * doc/binutils.texi: Document new objcopy option. + 2007-04-20 Nick Clifton <nickc@redhat.com> * rclex.l: Allow underscores at the start of identifiers. diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 04fdcc6..ec18bc8 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -987,6 +987,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}] [@option{--add-section} @var{sectionname}=@var{filename}] [@option{--rename-section} @var{oldname}=@var{newname}[,@var{flags}]] [@option{--change-leading-char}] [@option{--remove-leading-char}] + [@option{--reverse-bytes=}@var{num}] [@option{--srec-len=}@var{ival}] [@option{--srec-forceS3}] [@option{--redefine-sym} @var{old}=@var{new}] [@option{--redefine-syms=}@var{filename}] @@ -1052,6 +1053,7 @@ Note---@command{objcopy} is not able to change the endianness of its input files. If the input format has an endianness (some formats do not), @command{objcopy} can only copy the inputs into file formats that have the same endianness or which have no endianness (e.g., @samp{srec}). +(However, see the @option{--reverse-bytes} option.) @c man end @@ -1342,6 +1344,30 @@ different conventions for symbol names. This is different from when appropriate, regardless of the object file format of the output file. +@item --reverse-bytes=@var{num} +Reverse the bytes in a section with output contents. A section length must +be evenly divisible by the value given in order for the swap to be able to +take place. Reversing takes place before the interleaving is performed. + +This option is used typically in generating ROM images for problematic +target systems. For example, on some target boards, the 32-bit words +fetched from 8-bit ROMs are re-assembled in little-endian byte order +regardless of the CPU byte order. Depending on the programming model, the +endianness of the ROM may need to be modified. + +Consider a simple file with a section containing the following eight +bytes: @code{12345678}. + +Using @samp{--reverse-bytes=2} for the above example, the bytes in the +output file would be ordered @code{21436587}. + +Using @samp{--reverse-bytes=4} for the above example, the bytes in the +output file would be ordered @code{43218765}. + +By using @samp{--reverse-bytes=2} for the above example, followed by +@samp{--reverse-bytes=4} on the output file, the bytes in the second +output file would be ordered @code{34127856}. + @item --srec-len=@var{ival} Meaningful only for srec output. Set the maximum length of the Srecords being produced to @var{ival}. This length covers both address, data and diff --git a/binutils/objcopy.c b/binutils/objcopy.c index d02b3e0..92ccbbe 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -218,6 +218,11 @@ static char *prefix_alloc_sections_string = 0; /* True if --extract-symbol was passed on the command line. */ static bfd_boolean extract_symbol = FALSE; +/* If `reverse_bytes' is nonzero, then reverse the order of every chunk + of <reverse_bytes> bytes within each output section. */ +static int reverse_bytes = 0; + + /* 150 isn't special; it's just an arbitrary non-ASCII char value. */ enum command_line_switch { @@ -265,7 +270,8 @@ enum command_line_switch OPTION_WRITABLE_TEXT, OPTION_PURE, OPTION_IMPURE, - OPTION_EXTRACT_SYMBOL + OPTION_EXTRACT_SYMBOL, + OPTION_REVERSE_BYTES }; /* Options to handle if running as "strip". */ @@ -358,6 +364,7 @@ static struct option copy_options[] = {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR}, {"remove-section", required_argument, 0, 'R'}, {"rename-section", required_argument, 0, OPTION_RENAME_SECTION}, + {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES}, {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, {"set-start", required_argument, 0, OPTION_SET_START}, {"srec-len", required_argument, 0, OPTION_SREC_LEN}, @@ -471,6 +478,7 @@ copy_usage (FILE *stream, int exit_status) --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\ --change-leading-char Force output format's leading character style\n\ --remove-leading-char Remove leading character from global symbols\n\ + --reverse-bytes=<num> Reverse <num> bytes at a time, in output sections with content\n\ --redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\ --redefine-syms <file> --redefine-sym for all symbol pairs \n\ listed in <file>\n\ @@ -2383,6 +2391,32 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg) if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size)) RETURN_NONFATAL (bfd_get_filename (ibfd)); + if (reverse_bytes) + { + /* We don't handle leftover bytes (too many possible behaviors, + and we don't know what the user wants). The section length + must be a multiple of the number of bytes to swap. */ + if ((size % reverse_bytes) == 0) + { + unsigned long i, j; + bfd_byte b; + + for (i = 0; i < size; i += reverse_bytes) + for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++) + { + bfd_byte *m = (bfd_byte *) memhunk; + + b = m[i + j]; + m[i + j] = m[(i + reverse_bytes) - (j + 1)]; + m[(i + reverse_bytes) - (j + 1)] = b; + } + } + else + /* User must pad the section up in order to do this. */ + fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"), + bfd_section_name (ibfd, isection), reverse_bytes); + } + if (copy_byte >= 0) { /* Keep only every `copy_byte'th byte in MEMHUNK. */ @@ -3256,6 +3290,20 @@ copy_main (int argc, char *argv[]) extract_symbol = TRUE; break; + case OPTION_REVERSE_BYTES: + { + int prev = reverse_bytes; + + reverse_bytes = atoi (optarg); + if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0)) + fatal (_("number of bytes to reverse must be positive and even")); + + if (prev && prev != reverse_bytes) + non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"), + prev); + break; + } + case 0: /* We've been given a long option. */ break; diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index 3dfd768..7fb53d7 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-04-20 Nathan Froyd <froydnj@codesourcery.com> + Phil Edwards <phil@codesourcery.com> + Thomas de Lellis <tdel@windriver.com> + + * binutils-all/objcopy.exp: Add test for --reverse-bytes. + 2007-04-21 Richard Earnshaw <rearnsha@arm.com> * binutils-all/readelf.exp (regexp_diff): Delete. diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index cc56b4f..510f6ce 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -113,6 +113,40 @@ proc objcopy_test {testname srcfile} { objcopy_test "simple copy" bintest.s +# Test reversing bytes in a section. + +set reversed ${tempfile}-reversed +set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -j .data --reverse-bytes=4 $tempfile $reversed"] + +if ![string match "" $got] then { + fail "objcopy --reverse-bytes" +} else { + if [is_remote host] { + remote_upload host ${reversed} tmpdir/copy-reversed.o + set reversed tmpdir/copy-reversed.o + } + + set origdata [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s -j .data $tempfile"] + set revdata [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s -j .data $reversed"] + + set want "^ \[0-9\]+ (\[0-9\]+)" + set found_orig [regexp -lineanchor $want $origdata -> origdata] + set found_rev [regexp -lineanchor $want $revdata -> revdata] + + if {$found_orig == 0 || $found_rev == 0} then { + fail "objcopy --reverse-bytes" + } else { + scan $origdata "%2x%2x%2x%2x" b1 b2 b3 b4 + scan $revdata "%2x%2x%2x%2x" c4 c3 c2 c1 + + if {$b1 == $c1 && $b2 == $c2 && $b3 == $c3 && $b4 == $c4} then { + pass "objcopy --reverse-bytes" + } else { + fail "objcopy --reverse-bytes" + } + } +} + # Test generating S records. # We make the srec filename 8.3 compatible. Note that the header string |