This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: gas .incbin pseudo-op


Hi all,

this patch adds a .incbin directive to gas to include files
verbatim at the current location, as found in many other assemblers.
I'm a bit surprised this has not come up before, but the archives
didn't reveal anything.

Syntax:
.incbin "file"[,skip[,count]]

The same search path as .include is searched for the file,
but the local directory is tried first.

Tested on i*86-*-linux*, i*86-cygwin and arm-elf-thumb,
there is also a testcase attached.

Comments?

Regards,
Anders

gas/ChangeLog
	* read.c (s_incbin): New .incbin function.
	* read.c (potable): Add "incbin" pseudo-op.
	* read.h: Add s_incbin prototype.
	* doc/as.texinfo (incbin): Document .incbin pseudo-op.

gas/testsuite/ChangeLog
	* gas/all/gas.exp: Run incbin test.
	* gas/all/incbin.s: New file.
	* gas/all/incbin.d: New file.
--- gas/read.h.old	Fri Jun 29 17:39:25 2001
+++ gas/read.h	Fri Jun 29 17:40:09 2001
@@ -181,3 +181,4 @@ extern void s_text PARAMS ((int));
 extern void stringer PARAMS ((int append_zero));
 extern void s_xstab PARAMS ((int what));
 extern void s_rva PARAMS ((int));
+extern void s_incbin PARAMS ((int));
--- gas/read.c.old	Fri Jun 29 17:39:28 2001
+++ gas/read.c	Fri Jun 29 17:40:09 2001
@@ -349,6 +349,7 @@ static const pseudo_typeS potable[] = {
   {"ifne", s_if, (int) O_ne},
   {"ifnes", s_ifeqs, 1},
   {"ifnotdef", s_ifdef, 1},
+  {"incbin", s_incbin, 0},
   {"include", s_include, 0},
   {"int", cons, 4},
   {"irp", s_irp, 0},
@@ -4898,6 +4899,125 @@ equals (sym_name, reassign)
       ignore_rest_of_line ();
       mri_comment_end (stop, stopc);
     }
+}
+
+/* .incbin -- include a file verbatim at the current location */
+
+void
+s_incbin (x)
+     int x ATTRIBUTE_UNUSED;
+{
+  FILE *binfile;
+  char *path;
+  char *filename;
+
+  char *binfrag;
+
+  long skip;
+  long chunk;
+  long bytes;
+  int i;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  SKIP_WHITESPACE ();
+  filename = demand_copy_string (&i);
+  if (filename == NULL)
+    return;
+
+  path = NULL;
+  binfile = NULL;
+  
+  SKIP_WHITESPACE ();
+  skip = 0;
+  chunk = 0;
+
+  /* Look for optional skip and count */
+  if (*input_line_pointer == ',')
+    {
+      ++input_line_pointer;
+      skip = get_absolute_expression ();
+      SKIP_WHITESPACE ();
+
+      if (*input_line_pointer == ',')
+	{
+	  ++input_line_pointer;
+	  chunk = get_absolute_expression ();
+	  if (chunk == 0)
+	    {
+	      as_warn (_(".incbin count zero, ignoring `%s'"), filename);
+	      goto done;
+	    }
+	  SKIP_WHITESPACE ();
+	}
+    }
+  demand_empty_rest_of_line ();
+
+  /* Try opening absolute path first, then try include dirs */
+  binfile = fopen (filename, "rb");
+  if (binfile == NULL)
+    {
+      path = xmalloc ((unsigned long) i + include_dir_maxlen + 5);
+      for (i = 0; i < include_dir_count; i++)
+	{
+	  strcpy (path, include_dirs[i]);
+	  strcat (path, "/");
+	  strcat (path, filename);
+	  if (NULL != (binfile = fopen (path, "rb")))
+	    break;
+	}
+      if (binfile == NULL)
+	{
+	  as_bad (_("file not found: %s"), filename);
+	  goto done;
+	}
+    }
+  else
+    path = xstrdup (filename);
+  
+  register_dependency (path);
+
+  /* If a count was not specified use the size of the file */
+  if (chunk == 0)
+    {
+      if (fseek (binfile, 0, SEEK_END) != 0)
+	{
+	  as_bad (_("seek failed `%s'"), path);
+	  goto done;
+	}
+      chunk = ftell (binfile);
+      if (skip > chunk)
+	{
+	  as_bad (_("skip amount (%ld) larger than file size (%ld)"),
+		  skip, chunk);
+	  goto done;
+	}
+      chunk -= skip;
+    }
+
+  /* Allocate frag space and store file contents in it */
+  binfrag = frag_more (chunk);
+  if (fseek (binfile, skip, SEEK_SET) != 0)
+    {
+      as_bad (_("could not skip in file `%s'"), path);
+      goto done;
+    }
+
+  bytes = fread (binfrag, 1, chunk, binfile);
+  if (bytes < chunk)
+    {
+      as_warn (_("truncated file `%s', %ld of %ld bytes read"),
+	       path, bytes, chunk);
+    }
+
+done:
+  if (binfile != NULL)
+    fclose (binfile);
+  if (path)
+  free (path);
+  return;
 }
 
 /* .include -- include a file at this point.  */
--- gas/doc/as.texinfo.old	Fri Jun 29 17:39:38 2001
+++ gas/doc/as.texinfo	Fri Jun 29 17:40:33 2001
@@ -3448,6 +3448,7 @@ Some machine configurations provide addi
 * hword::                       @code{.hword @var{expressions}}
 * Ident::                       @code{.ident}
 * If::                          @code{.if @var{absolute expression}}
+* Incbin::                      @code{.incbin "@var{file}"[,@var{skip}[,@var{count}]]}
 * Include::                     @code{.include "@var{file}"}
 * Int::                         @code{.int @var{expressions}}
 @ifset ELF
@@ -4119,6 +4120,21 @@ Assembles the following section of code 
 Like @code{.ifeqs}, but the sense of the test is reversed: this assembles the
 following section of code if the two strings are not the same.
 @end table
+
+@node Incbin
+@section @code{.incbin "@var{file}"[,@var{skip}[,@var{count}]]}
+
+@cindex @code{incbin} directive
+@cindex binary files, including
+The @code{incbin} directive includes @var{file} verbatim at the current
+location. You can control the search paths used with the @samp{-I} command-line
+option (@pxref{Invoking,,Command-Line Options}).  Quotation marks are required
+around @var{file}.
+
+The @var{skip} argument skips a number of bytes from the start of the
+@var{file}.  The @var{count} argument indicates the maximum number of bytes to
+read. Note that the data from is not aligned in any way, make sure to proper
+alignment is provided before and after the @code{incbin} directive.
 
 @node Include
 @section @code{.include "@var{file}"}
--- gas/testsuite/gas/all/gas.exp.old	Fri Jun 29 17:43:40 2001
+++ gas/testsuite/gas/all/gas.exp	Fri Jun 29 17:45:24 2001
@@ -156,6 +156,8 @@
     test_cond
 }
 
+run_dump_test incbin
+
 # FIXME: this is here cause of a bug in DejaGnu 1.1.1. When it is no longer
 #        in use, then this can be removed.
 if [info exists errorInfo] then {
--- /dev/null	Tue May  5 22:32:27 1998
+++ gas/testsuite/gas/all/incbin.s	Fri Jun 29 17:09:09 2001
@@ -0,0 +1,5 @@
+.data
+.incbin "incbin.s"
+.incbin "incbin.s",0,28
+.incbin "incbin.s",15,9
+.p2align 4
--- /dev/null	Tue May  5 22:32:27 1998
+++ gas/testsuite/gas/all/incbin.d	Fri Jun 29 17:09:09 2001
@@ -0,0 +1,17 @@
+#as: -I$srcdir/$subdir
+#objdump: -s -j .data
+#name: incbin
+
+# Test the incbin pseudo-op
+
+.*: .*
+
+Contents of section .data:
+ 0000 2e646174 610a2e69 6e636269 6e202269  .data..incbin "i
+ 0010 6e636269 6e2e7322 0a2e696e 6362696e  ncbin.s"..incbin
+ 0020 2022696e 6362696e 2e73222c 302c3238   "incbin.s",0,28
+ 0030 0a2e696e 6362696e 2022696e 6362696e  ..incbin "incbin
+ 0040 2e73222c 31352c39 0a2e7032 616c6967  .s",15,9..p2alig
+ 0050 6e20340a 2e646174 610a2e69 6e636269  n 4..data..incbi
+ 0060 6e202269 6e636269 6e2e7322 0a2e696e  n "incbin.s"..in
+ 0070 696e6362 696e2e73 22000000 00000000  incbin.s".......

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]