public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] add --reverse option to objcopy
@ 2007-04-13 14:56 Nathan Froyd
  2007-04-13 17:06 ` H. J. Lu
  2007-04-20 13:35 ` Nick Clifton
  0 siblings, 2 replies; 5+ messages in thread
From: Nathan Froyd @ 2007-04-13 14:56 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1109 bytes --]

The attached patch is a forward-port of a patch originally proposed by
Thomas de Lellis:

http://sourceware.org/ml/binutils/2000-03/msg00319.html

The rationale from the original message:

  This patch solves problems trying to use the existing tools, to
  generate a ROM images for certain target systems where the byte order
  implemented in hardware did not match the endian the processor
  used. The ROM programmer did not have this functionality built in
  unfortunately.

  A new option "--reverse" has been added swap bytes within
  an output section... Given bytes in the order:

  01 02 03 04 05 06 07 08

  Allows users to re-order them as:

  02 01 04 03 06 05 08 07 (2 byte reversal)
  04 03 02 01 08 07 06 05 (4 byte reversal)
  03 04 01 02 07 08 05 06 (combination 2 & 4 byte reversal)

There was no comment on his original message, and we have customers who
still find this functionality useful.

Changes from the original patch:

* The original patch's documentation has been converted into texinfo;
* Patch has been cleaned up a little bit;
* A DejaGNU testcase has been added.

OK?

-Nathan

[-- Attachment #2: reverse.patch --]
[-- Type: text/plain, Size: 7778 bytes --]

binutils/
2007-04-13  Nathan Froyd  <froydnj@codesourcery.com>
	    Phil Edwards  <phil@codesourcery.com>
	    Thomas de Lellis <tdel@windriver.com>

        * objcopy.c (reverse_endian):  New variable.
        (command_line_switch, copy_main):  Add OPTION_REVERSE_ENDIAN.
        (copy_options, copy_usage):  Add "reverse" entry.
        (copy_section):  Reverse bytes within output sections.
        * doc/binutils.texi:  Document new objcopy option.

binutils/testsuite/
2007-04-13  Nathan Froyd  <froydnj@codesourcery.com>
	    Phil Edwards  <phil@codesourcery.com>
	    Thomas de Lellis <tdel@windriver.com>

	* binutils-all/objcopy.exp: Add test for --reverse.

--- binutils/doc/binutils.texi	(revision 168708)
+++ binutils/doc/binutils.texi	(local)
@@ -987,6 +987,7 @@ objcopy [@option{-F} @var{bfdname}|@opti
         [@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=}@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 
 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} option.)
 
 @c man end
 
@@ -1342,6 +1344,29 @@ different conventions for symbol names. 
 when appropriate, regardless of the object file format of the output
 file.
 
+@item --reverse=@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=2} for the above example, the bytes in the output
+file would be ordered @code{21436587}.
+
+Using @samp{--reverse=4} for the above example, the bytes in the output
+file would be ordered @code{43218765}.
+
+By using @samp{--reverse=2} followed by @samp{--reverse=4}, then bytes
+ordered @code{34127856} would be generated.
+
 @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
--- binutils/objcopy.c	(revision 168708)
+++ binutils/objcopy.c	(local)
@@ -218,6 +218,11 @@ static char *prefix_alloc_sections_strin
 /* True if --extract-symbol was passed on the command line.  */
 static bfd_boolean extract_symbol = FALSE;
 
+/* If `reverse_endian' is nonzero, then reverse the order of every chunk
+   of <reverse_endian> bytes within each output section.  */
+static int reverse_endian = 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_ENDIAN
   };
 
 /* 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", required_argument, 0, OPTION_REVERSE_ENDIAN},
   {"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_statu
      --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=<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 isectio
       if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
 	RETURN_NONFATAL (bfd_get_filename (ibfd));
 
+      if (reverse_endian)
+	{
+	  /* 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_endian) == 0)
+	    {
+	      unsigned long i, j;
+	      bfd_byte b;
+
+	      for (i = 0; i < size; i += reverse_endian)
+		for (j = 0; j < (unsigned long)(reverse_endian / 2); j++)
+		  {
+		    bfd_byte *m = (bfd_byte*)memhunk;
+
+		    b = m[i + j];
+		    m[i + j] = m[(i + reverse_endian) - (j + 1)];
+		    m[(i + reverse_endian) - (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_endian);
+	}
+
       if (copy_byte >= 0)
 	{
 	  /* Keep only every `copy_byte'th byte in MEMHUNK.  */
@@ -3256,6 +3290,12 @@ copy_main (int argc, char *argv[])
 	  extract_symbol = TRUE;
 	  break;
 
+	case OPTION_REVERSE_ENDIAN:
+	  reverse_endian = atoi (optarg);
+	  if ((reverse_endian <= 0) || ((reverse_endian % 2) != 0))
+	    fatal (_("number of bytes to reverse must be positive and even"));
+	  break;
+
 	case 0:
 	  /* We've been given a long option.  */
 	  break;
--- binutils/testsuite/binutils-all/objcopy.exp	(revision 168708)
+++ binutils/testsuite/binutils-all/objcopy.exp	(local)
@@ -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=4 $tempfile $reversed"]
+
+if ![string match "" $got] then {
+    fail "objcopy --reverse"
+} 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"
+    } 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"
+        } else {
+            fail "objcopy --reverse"
+        }
+    }
+}
+
 # Test generating S records.
 
 # We make the srec filename 8.3 compatible. Note that the header string

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-04-21  7:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-13 14:56 [PATCH] add --reverse option to objcopy Nathan Froyd
2007-04-13 17:06 ` H. J. Lu
2007-04-20 13:35 ` Nick Clifton
2007-04-20 17:19   ` Nathan Froyd
2007-04-21 11:38     ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).